PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : RN-MotorCtrl macht nicht was ich möchte!!



visualman
29.03.2007, 09:25
Hallo Ihr,

ich möchte den Rn-MotorCtrl für die Ansteuerung meiner Motoren verwenden. Es war so gedacht, dass ich über RS232 die im Datenblatt angegebenen Befehle verwende und somit die Bewegung der Motoren überwache(Lageregelung) und das der RN-MotorCtrl die Geschwindkeitsreglung übernimmt( und den Rest:Temp, Strom usw.)

Mir ist ein Unstimmigkeiten im Datenblatt aufgefallen:
Wegmessung wird die in Zentimeter oder Millimeter übermittel. In der Überschrift, für die Befehlsbeschreibung steht zumindest Millimeter und dann immer Zentimeter.

Weiteres Problem:

Einstellung der Encoderscheibe geht nur bis 255 Impulse pro Umdrehung, ich habe aber 360. Das Problem lässt sich umgehen wenn ich 180 einstelle und die anderen Werte, wie Millimeter pro Umdrehung und Maximale Drehzahl anpasse bzw umrechne.

Aber trotzdem geht die Geschwindigkeitsregelung nicht, der Motor dreht hoch, auch wenn ich die Befehler mit dem PC-Steuerungsprogramm schicke.:-(

Daten meines Motors:
Untersetzung: 30:1
Drehzahl: 216 Umdr/min
Encoder : 360 Impulse

Frage:
Wenn ich einen Befehl hinsende(RS232), warte ich solange bis etwas von RN-MotorCtrl zurück kommt.(d.h. Interrupt von Uart). Leider funktioniert das nicht immer. Schickt mir das Board immer zwei Bytes zurück oder kommt es manchmal zum Fehler?

Ich hoffe ihr könnt mir helfen?

Vielen Dank im voraus für euche Antworten und Ideen.

Wenn ihr mehr Infos braucht Fragt ebenfalls

Gruß

Frank
29.03.2007, 14:25
An einer Stelle gibts wohl noch kleinen Tippfehler in der Doku, sorry. Die Wegstrecke wird natürlich in Zentimetern und nicht Millimetern zurückgegeben. Bei der genauen Befehlssyntax wirds auch in der Doku richtig beschrieben.
Unterstützt werden allerdings nur Drehgeber bis maximal 255 Impulse pro Umdrehung, mehr geht in der Firmware nicht.
Was das Board bei jedem Befehl zurückliefert kann man am einfachsten mit dem PC-Testprogramm untersuchen. Das können je nach Befehl unterschiedlich viele Bytes sein da ja manchmal Werte übertragen werden.
Wenn du geeigneten Drehgeber angeschlossen hast, dann kannst du mit dem Drehzahlbefehl im PC Demoprogramm auch diese Funktion austesten, geht garantiert.

visualman
29.03.2007, 18:03
Tippfehler passieren immer. Das mit den Zentimeter ist auch nicht so schlimm.

Schlimmer ist Drehzahlregelung, die bei mir nciht richtig funktioniert. Der MotorCtrl dreht bis zur höhsten Drehzahl. Egal welche Werte ich übergeben.

Jetzt habe ich zusätzlich festgestellt, dass der Wert für die Impulse scheinbar nicht richtig gespeichert wird. Laut Datenblatt wird der Wert in W4 (PC-Steuerungsprogramm) angezeigt. Dort steht immer eine 30 egal was ich hinsende.

:-(

Helft mir

Edit: Zwei Stunden später, ich bin der Verzweiflung nah(weitere Probleme):

Im Datenblatt steht geschrieben, dass man bei erfolgreichem Senden eines Befehls 99 zurück bekommen. Das erste Byte ist der Fehlercode und das zweite Byte ist immer 254[rnmotorcontrol.pdf]. Leider ist der erste Rückgabewert nie char=99 und der zweite nie char=254. Wenn ich auf auf '9'(char 57) überprüfe, dann funktioniert ab und zu ein Sendeversuch.

Frank
29.03.2007, 22:23
Nicht die Geduld verlieren, ich denke es ist einfach noch ein Denkfehler bei Dir.
Schreib doch erst mal was Du eine Firmware Version hast, die kann man mit dem PC Programm abrufen. Dann wan du für eine PC Steuerprogramm Version hast, steht in der Programmtitelleiste.
Dann gib genau an was du für Einstellungen vorgenommen hast und was für Rückgaben genau bei welchem Befehl kommen.
Rufe pe rBefehl mal alle EEprom Daten mit Steuerprogramm ab und poste oder maile sie einfach.
Ich vermute das du irgendwo was falsches eingestellt hast, vielleicht bei Umdrehungszahl des Motors oder bei Getriebeuntersetzung. Gib mal alles genau an, das ist sicher besser als wenn wir hier so im Nebel stochern.

visualman
31.03.2007, 13:18
Hallo Frank und ihr lieben Zuschauer,

ich fasse mal alles zusammen.

Ich möchte mit einem Atmega32 das RN-MotorCtrl (MC) steuern(RS232). Der Atmega selber bekommt seine Vorgaben vom I2C Master (Brain).

Für die RS232 Datenübertragung vom Atmega32(Slave) zum MC verwende ich die Bibliothek von Peter Fleury, die funktioniert auch ohne Probleme. Ich habe die Funktionen von Peter Fleury um ein Funktion uart_getcWait(int Timeout) erweitert. Das funktioniert auch, da bin ich mir zu 99.9% sicher.

UART Wait:

Der Uart0 Interrupt wird erzeugt wenn ein Zeichen empfangen wurde. In diesem Interrupt hab ich einen globalen Counter, den ich bei jedem Interrupt hochzähle. Wenn ich nun uart_getcWait aufrufe wartet die Funktion solange bis der Counter größer als 0 wird. Nachdem die Funktion ein Char aus dem Buffer geholt hat, wird der Counter wieder um eins verringert. Meines erachtens funktioniert das auch.


unsigned int uart_getcWait(int timeout)
{
unsigned char tmptail;
unsigned char data;

int i=0;

while(rcvUart0Counter==0)
{

if(i>=timeout)
{
return 0;
}
i++;
_delay_ms(1);
}



if(rcvUart0Counter>0)
rcvUart0Counter--;

if ( UART_RxHead == UART_RxTail ) {
return 0; /* no data available */
}

/* calculate /store buffer index */
tmptail = (UART_RxTail + 1) & UART_RX_BUFFER_MASK;
UART_RxTail = tmptail;

/* get data from receive buffer */
data = UART_RxBuf[tmptail];

return (UART_LastRxError << 8) + data;

}/* uart_getcWait */

Physikalische Verbindung zwischen Mc und Atemga32:

Anfangs habe ich einen Max232 verwendet für die Datenübertragung. Ausserdem kann man ja auch schell das PC-Steuerungsprogramm anschließen. Um aber den Max aus Fehlerquelle auszuschließen habe ich den Max vom MC entfernt und direkt an den Atmega angeschlossen(Uart<->Uart). Leider hat sich nix geändert.

Nun meine Code zum senden an die MC:



#include "lib/I2CSlave.h"

#define Timeout 500

int uart_checkResults(){

int result[10];
int i;

//Wenn alles klappt kommt 99 zurück
// 2 Bytes müssen zurück kommen

result[0]=uart_getcWait(Timeout);
result[1]=uart_getcWait(Timeout);

//Lampen für Fehleranzeige
if(result[0]==99 || result[1]==254){
PORTA = resetBit(PORTA,0);
return true;
}else{
PORTA = setBit(PORTA,0);
}

//Lampen für Fehleranzeige
if(result[1] == 254){
PORTA = setBit(PORTA,1);
}else{
PORTA = resetBit(PORTA,1);
}

if(result[0]==5 || result[0]==1 || result[0]==2 || result[0]==3 || result[0]==4|| result[0]==6 || result[0]==20){
PORTA = setBit(PORTA,7);
txbuffer[0]='R';
}else{
PORTA = resetBit(PORTA,7);
}

if(result[0]==0){
PORTA = setBit(PORTA,3);
txbuffer[0]='R';
}else{
PORTA = resetBit(PORTA,3);
}

LEDS = resetBit(LEDS,LED1);
return false;
}

void uart_setMotorSpeed(int a,int b){
do{
uart_putc((char) 35);
uart_putc((char) 35);
uart_putc((char) 3);
uart_putc((char) 2);
uart_putc((char) a);
uart_putc((char) b);
}while(!uart_checkResults());
};

void uart_setDirection(int a,int b){
do{
uart_putc((char) 35);
uart_putc((char) 35);
uart_putc((char) 3);
uart_putc((char) 5);
uart_putc((char) a);
uart_putc((char) b);
}while(!uart_checkResults());
};

uint8_t uart_getReasonMotorStop(){
char res[1];

do{
uart_putc((char) 35);
uart_putc((char) 35);
uart_putc((char) 1);
uart_putc((char) 43);
res[0]=uart_getcWait(Timeout); //Solange warten bis Datenempfangen wurden
}while(!uart_checkResults());

return res[0];
};

//a->Motorwahl b-> LowByte c-> HighByte
void uart_setMotorControlSpeed(int a,int b,int c){
do{
uart_putc((char) 35);
uart_putc((char) 35);
uart_putc((char) 4);
uart_putc((char) 3);
uart_putc((char) a);
uart_putc((char) b);
uart_putc((char) c);
}while(!uart_checkResults());

};

//a -> Motorwahl
void uart_resetPath(int a){
int i;
do{

for(i=0;i<=9;i++) uart_getc();
uart_putc((char) 35);
uart_putc((char) 35);
uart_putc((char) 2);
uart_putc((char) 4);
uart_putc((char) a);
}while(!uart_checkResults());
};

//a -> Motorwahl --Rückgabe 2 Bytes -> 1. LowByte 2. HighByte
long uart_getMotorCurrent(int a){
char res[10];

do{
uart_putc((char) 35);
uart_putc((char) 35);
uart_putc((char) 2);
uart_putc((char) 40);
uart_putc((char) a);
res[0]=uart_getcWait(Timeout); //Solange warten bis Datenempfangen wurden
res[1]=uart_getcWait(Timeout);
}while(!uart_checkResults());

return TOWORD(res[0],res[1]);
};
//a -> Motorwahl --Rückgabe 2 Bytes -> 1. LowByte 2. HighByte
long uart_getRevolutionPerMin(int a){
char res[2];

do{
uart_putc((char) 35);
uart_putc((char) 35);
uart_putc((char) 2);
uart_putc((char) 41);
uart_putc((char) a);
res[0]=uart_getcWait(Timeout); //Solange warten bis Datenempfangen wurden
res[1]=uart_getcWait(Timeout);
}while(!uart_checkResults());

return TOWORD(res[0],res[1]);
};

//a -> Motorwahl --Rückgabe 4 Bytes -> 1. LowWord Low 2. LowWord High 3. HighWord Low 4. HighWord High
uint32_t uart_getPath(int a){
char res[4];

do{
uart_putc((char) 35);
uart_putc((char) 35);
uart_putc((char) 2);
uart_putc((char) 42);
uart_putc((char) a);
res[0]=uart_getcWait(Timeout); //Solange warten bis Datenempfangen wurden
res[1]=uart_getcWait(Timeout);
res[2]=uart_getcWait(Timeout);
res[3]=uart_getcWait(Timeout);
res[4]=uart_getcWait(Timeout);
}while(!uart_checkResults());

return TODWORD(res[0],res[1],res[3],res[4]);
};


Diese Funktionen sollen die Kommunikation übernehmen. Der einzelne Befehl soll dabei solange an die MC gesendet werden bis die richtigen Zeichen zurückkommen. Datenblatt: 1. Byte-> Fehlercode, 2. Byte 254

Vielleicht seht ihr einen Fehler.

@Frank: Was ist mit dem W4. Du liest bestimmt beim "Einstellung lesen" (PC-Steuerprog) den EEPROM aus. Steht W4 wirklich für die Einstellung der Encoder.

Frank
02.04.2007, 15:55
Hallo,
du hast vermutlich Firmware 1.3 nehme ich mal an.
Ja die W-Werte sind so wie in der Anleitung dokumentiert. W4 ist in der Tat die Encoder-Markierungszahl. Normalerweise steht da immer 120 drin. Die meisten ändern dies auch nie da in der Regel immer der 120er Drehgeber mitbestellt wird.
Daher ist es bislang auch nicht aufgefallen das es in der V 1.3 ein Bug bei der Veränderung dieses Wertes gibt, ich habe das gerade genauer untersucht. Wird ein anderer Wert rein geschrieben, so können dort Zufallswerte abgelegt werden.
Hier hilft leider nur ein Update des Chips. Der Bug ist inzwischen behoben. Wer also die Encodermarkierungszahl ändern will, sollte darauf achten das min. die Firmware-Version 1.4 im Chip steckt. Firmware Version kann man mit dem PC Programm abrufen.
Wer einen ältere Firmware hat, muss den Chip zum Austausch leider einsenden.
Einfach mal Kontakt aufnehmen mit http://www.robotikhardware.de/bilder/mail.gif


Gruß Frank

visualman
03.04.2007, 08:54
@ Frank

Was sagst du zu meiner Beschreibung, ich sehe keine Fehler bzw. Denkfehler mehr. Die verstecken sich zu gut. Ich seh den Wald vor lauter Bäumen nicht.

@Motor
Den Motor habe ich auch von RH gekauft. Der EMG32.

Frank
03.04.2007, 09:52
Hi,
zu deinem Programm kann ich leider nix sagen da ich C bei AVR´s nicht benutze.
Generell ist nur zu sagen das du dir anhand der Doku und des PC-Testprogrammes ein Überblick über die Rückgabewerte machen solltest. Jeder Befehl kann unterschiedlich viele Zeichen zurück liefern, daher kann man nicht alle gleich behandeln.

Der Motor EMG32 wird derzeit, bei der Drehzahlregelung, wegen der hohen Impulszahl von 360 nicht unterstützt. Es gibt sicherlich spätern mal ein Update der Firmware, so das auch dort Drehzahl geregelt werden kann, aber momentan kann ich dazu noch keinen Zeitpunkt nennen. Die Rückgaben des Boards werden vielleicht in einem späteren Update auf Binärdaten umgestellt werden, dadurch wäre dann die Auswertung noch leichter. Es muss nur noch gecheckt werden ob das noch in den Chip paßt, der war sehr voll.
Momentan müsstest du dich mit V 1.4 anfreunden und vielleicht erstmal auf Drehzahlgeber verzichten. Ich hoffe das kurz nach den Ferien ein Update möglich ist.

visualman
03.04.2007, 15:39
Schade. Dann muss ich wohl selber Hand anlegen. Werde mich trotzdem mal beim support melden.

@Rückgabe allgemein.

Es werden für jeden Befehl unterschiedliche Anworten erwartet. Das habe ich beachtet.

Für jeden Befehl kommt aber auf jeden Fall die 2 Bytes(1. Byte = 99 und 2. Byte 254)

Also:

Datenbytes(low,high) + 2 Bytes für die Bestätigung

Leider funkt das irgendwie nicht richtig.

Wenn das 1. Byte auf Ascii '9' ( char=57) überprüfe dann leuchtet zum Bespiel ne Lampe auf. komisch?

visualman
05.04.2007, 14:58
Hallo Frank,

das PWM Signal kann ich bereits ohne Probleme generieren. Trotzdem drehen meine Motoren nicht.

Laut Schaltplan sind die Ports PD6 und PD7 für Motor 1 und PB5 und PB0 für Motor2 verantwortlich.
IN-A und IN-B müssen unterschiedlich sein damit die Richtung festgelegt werden kann.

Könntest du mal bitte schauen ob die Ports wirklich stimmen.

Beste Grüße

Frank
06.04.2007, 10:07
Hi,
eigene Firmware ist richtig arbeit sag ich dir wenn du auch noch Drehzahlregelung und I2C und RS232 und RC integrierst, da muss Timing gut stimmen damit sich da snicht in die quere kommt Aber kann natürlich auch Spaß machen. Also die veröffentlichten Schaltpläne stimmen alle. Aus Zeitmangel kann ich jetzt nicht alles genau zerpflücken aber die Motorports kann ich dir nochmal auflisten:

Motor1_pwm Alias Portd.3
Motor1_in1 Alias Portd.6
Motor1_in2 Alias Portd.7

Motor2_pwm Alias Portb.3
Motor2_in1 Alias Portb.0
Motor2_in2 Alias Portb.5

Die stimmen so definitiv, ich setze RN-MotorControl ja selbst für einige Modelle ein.
Gruß Frank

visualman
06.04.2007, 10:25
Zum glück bin ich nicht alleine.

I2C reicht mir vollkommen aus.

Also hast du timer 2 für das PWM genommen.Da liegt auch schon der Fehler. Hab mich da mal wieder verguckt.

OC2A
OC2B

sind nicht gleich OC1A und OC1B.

Kann man das nciht über die jp9 und jp10 vertauschen.

Frank
06.04.2007, 11:04
Ja richtig, durch die Jumper kann man die Ports auch umbelegen, je nachdem was gerade günstiger ist. Ich verwende aber immer ober Standard-Belegung.

visualman
06.04.2007, 20:26
Hallo Frank,

hast du T1 und T0 für die Zählung der Encoder verwendet. Du müsstest die übrigen Timer, Timer1 und Timer2 dafür genommen haben?

Mal schauen ob ich dann den 16 Bit Timer für die PWM nehme und die beiden 8bit Timer/Counter zum zählen der Inkrementale der Encoder.

Dann müsste es ja dann ohne Probleme funktonieren.

Jetzt noch eine Kaskadenregelung mit einer schönen Strommessung und dann sollte alles funktionieren.

Wie hast du die Regelung gelöst?

Gruß