Ok, jetzt hab ich das auch verstanden.
Danke nochmal für eure Hilfe.
lg
Michi
Hallo,
die Funktionen haben einen Rückgabewert (Variable)! Der wird direkt in der if Bedingung ausgewertet. Ist in C egal ob ich nun schreibe
int x = funktion();
if(x) {}
oder
if(funktion()) {}
... aber nur sofern x später nicht mehr gebraucht wird natürlich.
siehe Link weiter obenUnd warum braucht man bei if(strcmp(receiveBuffer, "Ein")==0) das "==0", was soll denn da 0 sein?
0 heisst gleich. Alles andere nicht.http://www.cplusplus.com/reference/c...string/strcmp/
Returns an integral value indicating the relationship between the strings:
A zero value indicates that both strings are equal.
A value greater than zero indicates that the first character that does not match has a greater value in str1 than in str2; And a value less than zero indicates the opposite.
MfG,
SlyD
Ok, jetzt hab ich das auch verstanden.
Danke nochmal für eure Hilfe.
lg
Michi
Da es das gleiche Thema ist klinke ich ich hier auch mal ein. Zuerst danke SlyD für den HInweis auf dieses Thema.
Nun mal ne Frage.
Was macht dieser Code denn genau? Ich weiß gern was ich da in einem Programm verwende.Code:char receiveBuffer[UART_RECEIVE_BUFFER_SIZE+1]; uint8_t getInputLine(void) { static uint8_t buffer_pos = 0; if(getBufferLength()) { receiveBuffer[buffer_pos] = readChar(); if(receiveBuffer[buffer_pos]=='\n') { receiveBuffer[buffer_pos]='\0'; buffer_pos = 0; return 1; } else if(buffer_pos >= 32) { receiveBuffer[32]='\0'; buffer_pos = 0; return 2; } buffer_pos++; } return 0; }
Ist die Variable UART_RECEIVE_BUFFER_SIZE denn schon definiert? Oder muss ich die selber definieren aufgrund der Menge an Zeichen die ich definiere?
Die Funktion oben geht ja den kompletten receiveBuffer Zeichen für Zeichen durch und jagt readChar() darüber. Was macht readChar() den mit den Zeichen?
Dann, ein Abbruchkriterium ist ja wenn als Zeichen '\n' gefunden wird. Ich vermute das kann ich auch einfach durch andere "Zeilenendzeichen" ersetzen? Also z.B. mit '\r'.
Was bringt es eigentlich wenn man ein Zeichen mit '\0' überschreibt?
Meine letzte aber wohl komischste Frage überhaupt, wo befinden sich denn nach der Funktion überhaupt die eingelesenen Zeichen?
Wenn ich die Funktion ja aufrufe liefert die mir nur je nach Zustand ein 0, eine 1 oder eine 2 zurück. Oder seh ich das grad richtig das am Ende alle Zeichen der Reihe nach in receiveBuffer[0..Ende] stehen?
EDIT: Nachdem ich das ganze geschrieben hab un noch ein paar mal drüber nachgedacht hab glaub ich das ich das doch verstanden hab. Narf immer das gleiche ^^
EDIT2: Aber eine Frage habe ich immernoch, wie kann ich es denn realisieren dass ich in einer Zeile z.B. "050 050" übertragen kann und dann im RP6 das in zwei Variable mit jeweils 50 umsetze?
Ich will da nämlich Geschwindigkeitswerte übertragen und eben auf für Kurven z.B. "075 125" oder sowas
Kann ich denn von dieser Variable vom Typ Char einfach die ersten drei Zeichen irgendwie rausnehmen und in eine integer schreiben? Weiß da einer wie man sowas macht?
EDIT3: Habe nun rausgefunden das sich das ein char mittels
int i = atoi (char) in etwa umwandeln lässt.
Werde das daheim dann mal testen.
Hmm nun probier ich da schon eine Weile rum, aber irgendwie funktioniert da irgendwas nicht so wie es soll.
Mein Quelltext sieht derzeit so aus.
Aber aus einem mir unerfindlichen Grund kommt er immer nur bis zur LCD Anzeige "fertig".Code:#include "RP6ControlLib.h" #include "RP6I2CmasterTWI.h" #include "RP6Control_I2CMasterLib.h" void I2C_transmissionError(uint8_t errorState) { writeString_P("\nI2C ERROR - TWI STATE: 0x"); writeInteger(errorState, HEX); writeChar('\n'); } char receiveBuffer[8]; char dir_char[1], speed_1_char[3], speed_2_char[3]; void getInputLine(void) { clearLCD(); writeStringLCD("getinputline"); static uint8_t buffer_pos = 0; if(getBufferLength()) { receiveBuffer[buffer_pos] = readChar(); if((receiveBuffer[buffer_pos]=='\n')||(receiveBuffer[buffer_pos]=='\r')) { receiveBuffer[buffer_pos]='\0'; buffer_pos = 0; } else if(buffer_pos >= 8) { receiveBuffer[7]='\0'; buffer_pos = 0; } buffer_pos++; } } uint8_t speed_1=0; uint8_t speed_2=0; uint8_t direction=0; uint8_t speed_max=200; int main(void) { initRP6Control(); initLCD(); mSleep(500); I2CTWI_initMaster(100); I2CTWI_setTransmissionErrorHandler(I2C_transmissionError); setLEDs(0); mSleep(500); sound(180,80,25); sound(220,80,0); while(1) { task_checkINT0(); task_I2CTWI(); clearLCD(); writeStringLCD("fertig"); mSleep(500); clearLCD(); //uerbtragung in der form 1050080 //1. erste stelle richtung //richtung vorwaerts -> 1 //richtung rueckwaerts -> 2 //drehen links -> 3 //drehen rechts -> 4 //2.-4. stelle speed_1 (linke kette) //5.-7. stelle speed_2 (rechte kette) getInputLine(); direction=atoi(dir_char); speed_1=atoi(speed_1_char); speed_2=atoi(speed_2_char); writeStringLCD("d:"); writeIntegerLCD(direction, 10); writeStringLCD("s1:"); writeIntegerLCD(speed_1, 10); writeStringLCD("s2:"); writeIntegerLCD(speed_2, 10); } return 0; }
Anfangs hatte ich das getInputLine(); mal vor der LCD-Ausgabe für "Fertig", da ist er erst in diese funktion gegangen und hat mir den text "getinputline" angezeigt und danach "fertig". Doch jetzt wo ich die Reihenfolge der zwei getauscht habe macht er das auch nicht mehr.
Ich wär für jeden Hinweis dankbar.
Grüße vogel
Hallo vogel0815,
schau dir noch mal genau das Beispiel von RobotMichi vom 9.8.09 an! Da wird gezeigt, wie getInputLine() verwendet wird.
Zu einer deiner früheren Fragen:
Ein bestimmtes "Zeichen" überschreibt man häufiger mit 0, und zwar das Stringende. Wenn man Zeichen in receiveBuffer schreibt, dann kann man den ganzen Buffer als String auslesen, wenn im letzten Byte eine 0 ist, also der String Null-terminiert ist.Was bringt es eigentlich wenn man ein Zeichen mit '\0' überschreibt?
Gruß Dirk
Also ich hab das nun mal ein bissl umgeändert und probier das wie folgt:
aber irgendwie klappt da gar nix.Code:#include "RP6ControlLib.h" #include "RP6I2CmasterTWI.h" #include "RP6Control_I2CMasterLib.h" void I2C_transmissionError(uint8_t errorState) { writeString_P("\nI2C ERROR - TWI STATE: 0x"); writeInteger(errorState, HEX); writeChar('\n'); } char receiveBuffer[UART_RECEIVE_BUFFER_SIZE+1]; uint8_t getInputLine(void) { clearLCD(); writeStringLCD("getinput"); mSleep(500); static uint8_t buffer_pos = 0; if(getBufferLength()) { receiveBuffer[buffer_pos] = readChar(); if(receiveBuffer[buffer_pos]=='\r') { receiveBuffer[buffer_pos]='\0'; buffer_pos = 0; return 1; } else if(buffer_pos >= 32) { receiveBuffer[32]='\0'; buffer_pos = 0; return 2; } buffer_pos++; } return 0; } uint8_t setonce2=false, setonce3=false; /* LCD Texte einmalig setzen bei betreten des Zustandes LCD-Display 2*16 Zeichen */ void LCDText(uint8_t nmbr) { switch (nmbr) { case 1: showScreenLCD("Starting up! One", "moment please."); break; case 2: setonce3=false; if (!setonce2) { setonce2=true; showScreenLCD("################","################"); } break; case 3: setonce2=false; if (!setonce3) { setonce3=true; showScreenLCD("################","################"); } break; } } uint8_t speed_max=200; int main(void) { initRP6Control(); initLCD(); mSleep(500); I2CTWI_initMaster(100); I2CTWI_setTransmissionErrorHandler(I2C_transmissionError); LCDText(1); setLEDs(0); mSleep(500); sound(180,80,25); sound(220,80,0); while(1) { task_checkINT0(); task_I2CTWI(); clearLCD(); writeStringLCD("fertig"); mSleep(500); if(getInputLine()) { if(strcmp(receiveBuffer, "Ein")==0) { clearLCD(); writeStringLCD("ein"); mSleep(500); } if(strcmp(receiveBuffer, "Aus")==0) { clearLCD(); writeStringLCD("aus"); mSleep(500); } } } return 0; }
Der RP6 rennt zwar sein Programm durch und zeigt mir auch die Textausgaben "fertig" und "getinputline" an so wie er soll, aber die ankommenden daten wertet er irgendwie nicht aus.
Die Daten schicke ich mittels eines bluetooth moduls das ich auch schon mal als schleife ans notebook gehängt hab, das klappt so wie es soll.
Hab auch die baudrate im rp6 auf 19200 geändert wie das modul derzeit eingestellt ist.
Aber selbst wenn ich das eigene UART interface benutze, und das dann auch mit der normalen baudrate im RP6 funktioniert das nicht.
ich hab das gefühl der hat irgendein problem mit dem datenempfang.
Ein writeString(receiveBuffer) als Debug Ausgabe könnte schon helfen um zu sehen WAS denn genau ankommt. Oder noch besser in einer Schleife die ASCII Codes ausgeben lassen (writeInteger(receiveBuffer[i],DEC))
Immer wenn irgendwas nicht funktioniert solltest Du versuchen die Variablen Inhalte auszugeben. Dafür ist die serielle Schnittstelle ja auch da
Der Grund warum es nicht funktioniert liegt wohl hier:
mSleep(500);
(kommt an zwei Stellen vor!)
Damit funktioniert das task System nicht mehr!
mSleep darfst Du nur für kurze Pausen <20ms verwenden wenn Du task_ABCD Funktionen in der Hauptschleife aufrufst.
getInputline ist im prinzip auch so eine Art von Task Funktion und muss MEHRFACH aufgerufen werden damit es funktioniert.
Die Funktion verarbeitet jedes ankommende Zeichen EINZELN damit das nebenläufig verwendet werden kann und nichts anderes blockiert.
Wenn man das anders haben möchte muss man das if gegen while austauschen...
Die bessere Lösung ist aber von mSleep komplett auf die Stopwatches (Software Timer) umzusteigen.
MfG,
SlyD
Also ich hab da heute mal weiter gemacht, und nu funktioniert das so wie es soll
Mein Code sieht nun so aus.
Die Steuerung vom RP6 über Bluetooth und Labview, wie es später auch geschehen soll funktioniert nun auch einwandfrei.Code:#include "RP6ControlLib.h" #include "RP6I2CmasterTWI.h" #include "RP6Control_I2CMasterLib.h" void I2C_transmissionError(uint8_t errorState) { writeString_P("\nI2C ERROR - TWI STATE: 0x"); writeInteger(errorState, HEX); writeChar('\n'); } char receiveBuffer[8]; // our reception buffer is one byte larger // than the data we want to receive, because // we also need to receive the "Newline" character! void getInputLine(void) { clearReceptionBuffer(); // Make sure reception Buffer is empty and no junk data // is left in it. uint8_t buffer_pos = 0; while(true) // Loop until we received one line of Data! { if(getBufferLength()) // Check if we still have data (means getBufferLength() { // is not zero) receiveBuffer[buffer_pos] = readChar(); // get next character from reception buffer if(receiveBuffer[buffer_pos]=='\n') // End of line detected! { receiveBuffer[buffer_pos]='\0'; // Terminate String with a 0, so other routines. buffer_pos = 0; // can determine where it ends! // We also overwrite the Newline character here. break; // We are done and can leave reception loop! } else if(buffer_pos >= 7) // IMPORTANT: We can not receive more { // characters than "charsToReceive" because // our buffer wouldn't be large enough! receiveBuffer[7]='\0'; // So if we receive more characters, we just // stop reception and terminate the String. writeString_P("\n\nZu viele Zeichen eingegeben FEHLER!\n"); break; // We are done and can leave reception loop! } buffer_pos++; } } } /* char-array von receivebuffer in seine einzelteile zerlegen und ebenfalls in einem char-array sowie diese neuen char-arrays umwandeln in integerzahlen */ static int speed_1=0; static int speed_2=0; static int direction=0; char dir_char[2]; char speed_1_char[4]; char speed_2_char[4]; void splitbuffer(void) { dir_char[0]=0; dir_char[0]=receiveBuffer[0]; direction=atoi(dir_char); int i=0; while (i<3) { speed_1_char[i]=receiveBuffer[i+1]; speed_2_char[i]=receiveBuffer[i+4]; i++; } speed_1=atoi(speed_1_char); speed_2=atoi(speed_2_char); } int speed_max=200; int main(void) { initRP6Control(); initLCD(); I2CTWI_initMaster(100); I2CTWI_setTransmissionErrorHandler(I2C_transmissionError); setLEDs(0); sound(180,80,25); sound(220,80,0); while(1) { task_checkINT0(); task_I2CTWI(); writeString_P("\nget input\n"); getInputLine(); splitbuffer(); if(speed_1>200) { speed_1=speed_max; } if(speed_2>200) { speed_2=speed_max; } switch (direction) { case 1: //vorwaerts fahren writeInteger(1,DEC); writeChar('\n'); changeDirection(FWD); //richtung wechseln nach forward moveAtSpeed(speed_1, speed_2); break; case 2: //rueckwaerts fahren writeInteger(2,DEC); writeChar('\n'); changeDirection(BWD); //richtung wechseln nach backward moveAtSpeed(speed_1, speed_2); break; case 3: //links drehen writeInteger(3,DEC); writeChar('\n'); changeDirection(FWD); //forward sonst leichte verwirrung moveAtSpeed(speed_1, speed_2); break; case 4: //rechts drehen writeInteger(4,DEC); writeChar('\n'); changeDirection(FWD); moveAtSpeed(speed_1, speed_2); break; default: writeInteger(5,DEC); writeChar('\n'); moveAtSpeed(0,0); } } return 0; }
Nun muss ich nur noch am RP6 mal die Encoder richtig einstellen, aber da macht mir derzeit der RP6Loader zicken. Irgendwie ist der grad verdammt lahm was die Textausgabe dort angeht. Der hängt ewig hinterher. Aber deswegen hab ich mal im Arexx forum die frage gestellt.
Nur eine Sache kapier ich nicht. In meinem Quellcode oben teile ich den 7-stelligen Inhalt des receivebuffers auf auf 3 einzelne char-arrays.
das erste zeichen in das erste array, und dann je 3 zeichen in die anderen arrays. Im Code oben habe ich diese neuen Arrays aber jeweils ein zeichen größer machen müssen als das was da rein kommt. Also statt einem Zeichen hab ich das 2 Zeichen groß machen müssen, und anstelle von 3 Zeichen 4 Zeichen. Sonst hat das einfach nicht funktioniert. Hat irgendjemand eine idee warum das so ist? ist ja schließlich schon etwas komisch.
Ansonste Grüße und danke für eure Hilfe.
> Nur eine Sache kapier ich nicht.
receiveBuffer[buffer_pos]='\0';
// Terminate String with a 0, so other routines.
// can determine where it ends!
Und wenn Du atoi verwendest musst Du die Arrays auch 0 terminieren!
Lesezeichen