PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : nette sonntagsaufgabe: fehler im programm...



andieh
25.01.2009, 12:25
Hallo Freunde!

Seit ca. 2 Wochen bin ich jetzt stolzer Besitzer des RP6 und hatte ja schon seit Anfang an die Idee, meinen Roboter per RS232 zu steuern. Der "Server" läuft jedoch nicht auf dem PC, sondern auf einem modifizierten Fonera Router. Die Verbindung steht, erste Lenkversuche haben auch geklappt. Jetzt haben wir uns eine Gui zusammengebaut, die auch noch verschiedene Informationen (Bumper gedrückt, Obstacles in Sicht, Motorgeschwindigkeit) vom Roboter anfragt und geliefert bekommt. Nur jetzt haben wir angefangen, eben auch mit diesen Daten zu arbeiten und da liegt das Problem, bei zu vielen Anfragen verschluckt sich der RP6 anscheinend und schickt komische Dinge.

Zum Testen verbinde ich mich mit Telnet auf den Server, der auf der Fonera läuft und sende Commands. Die Fonera leitet diese Befehle an den RP6 über seriell weiter und erhält Antworten, die natürlich zurück zu telnet geschickt werden. commands fangen immer mit einem $ an und schließen mit einem &. alles andere wird vom server verworfen, auch auf dem RP6 schaue ich nicht nach dem absatz als endzeichen, sondern auf das &! Hier ein Beispiel was passiert:



$START& //startet das programm auf dem rp6
Starting RP6 Program! //rückgabe
$Q|ALL& //messwerte werden angefragt
$M|BL:0|BR:0|LDRL:798|LDRR:907|UBAT:830|OL:0|OR:0| ML:0|MR:0& //antwort
$Q|ALL& //messwerte werden angefragt
$M|BL:0|BR:0|LDRL:801|LDRR:909|UBAT:830|OL:0|OR:0| ML:0|MR:0& //antwort
$D|BU& // motorspeed soll um 10 erhöht werden
$M|BL:0|BR:0|LDRL:802|LDRR:910|UBAT:830|OL:0|OR:0| ML:0|MR:0& // messwerte kommen an, aber motorspeed wird trotzdem erhöht!
$D|BU& // noch mal motorspeed erhöhen
$OK& // aknowledge, also speed wurde erhöht
$Q|ALL& // messwerte anfragen
$Q|ALL& // keine antwort, noch mal anfragen
$Q|ALL& // immer noch nix, noch mal anfragen
$M|BL:0|BR:0|LDRL:811|LDRR:912|UBAT:826|OL:0|OR:0| ML:10|MR:10& // antwort
$D|STOP& // alles stoppen
$M|BL:0|BR:0|LDRL:811|LDRR:912|UBAT:826|OL:0|OR:0| ML:10|MR:10& // schon wieder kommen die messwerte an, aber rp6 stoppt trotzdem!


irgendwie scheint der buffer auf dem rp6 komische sachen zu speichern und zu verschicken. die befehle kommen auf jeden fall an, aber die antwort ist falsch.

Ich komme einfach nicht mehr weiter. seit 2-3 Tagen suche in intensiv nach dem Fehler aber ich kann den Code schon nicht mehr sehen. Ich bin mir ziemlich sicher, das der Fehler irgendwo im Programm auf dem RP6 zu suchen ist, da der Server auf der Fonera eigentlich, meiner Meinung nach, alles richtig macht.

Es wäre toll, wenn ihr mal einen Blick darauf werfen könntet, vielleicht fällt jemanden etwas auf. Den Server habe ich angehängt.

MfG
Andieh



#include "RP6RobotBaseLib.h"


// returns max value from to integer
int max(int number1, int number2)
{
if ( number1 > number2) return number1;
else return number2;
}

/************************************************** ***************************/

// Main function - The program starts here:



int main(void)

{
int DIR_LEFT = 0; // 0 nothing, 1 FWD, -1 BWD
int DIR_RIGHT = 0; // 0 nothing, 1 FWD, -1 BWD
int M_SPEED_L = 0;
int M_SPEED_R = 0;
int SPEED_STEP = 10;


initRobotBase();


powerON();
setACSPwrHigh();
clearReceptionBuffer();

// ---------------------------------------

// Main loop:

uint8_t buffer_pos = 0;
int charsToReceive = 50;
char receiveBuffer[charsToReceive+1];
int send = 0;

while(true)

{
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]=='&') // End of line detected!
{

receiveBuffer[buffer_pos+1]='\0'; // Terminate String with a 0, so other routines can determine where it ends!

buffer_pos = -1;
clearReceptionBuffer();
}

else if(buffer_pos >= charsToReceive) // IMPORTANT: We can not receive more characters than "charsToReceive"
{
receiveBuffer[charsToReceive]='\0'; // So if we receive more characters, we just stop reception and terminate the String.
writeString_P("$You entered more characters than possible!%\n");
}

buffer_pos++;



}


// try to find something useful information in the
// received string

// TODO: check if string starts with $ and ends with &

// read all values
else if (strncmp("$Q|ALL",receiveBuffer,6) == 0) {
int BL = getBumperLeft();
int BR = getBumperRight();
int OL = isObstacleLeft();
int OR = isObstacleRight();
char sendValues[85];
memset(sendValues, '\0', sizeof(sendValues) );

sprintf(sendValues,"$M|BL:%d|BR:%d|LDRL:%d|LDRR:%d|UBAT:%d|OL:%d|OR:%d |ML:%d|MR:%d&",BL,BR,adcLSL,adcLSR,adcBat,OL,OR,M_SPEED_L,M_SPEE D_R);
writeString(sendValues);

send = 1;
}

// move forward
else if (strncmp("$D|FWD", receiveBuffer,6) == 0) {
if ( DIR_LEFT == -1 || DIR_RIGHT == -1 )
stop();

setMotorDir(FWD,FWD);
if ( M_SPEED_L != M_SPEED_R) {
M_SPEED_L = max(M_SPEED_L,M_SPEED_R);
M_SPEED_R = max(M_SPEED_L,M_SPEED_R);
}
moveAtSpeed(M_SPEED_L,M_SPEED_R);
DIR_LEFT = 1; DIR_RIGHT = 1;
writeString_P("$OK&");
send = 1;
}

// move backwards
else if (strncmp("$D|BWD", receiveBuffer,6) == 0) {
if ( DIR_LEFT == 1 || DIR_RIGHT == 1 )
stop();

setMotorDir(BWD,BWD);
if ( M_SPEED_L != M_SPEED_R) {
M_SPEED_L = max(M_SPEED_L,M_SPEED_R);
M_SPEED_R = max(M_SPEED_L,M_SPEED_R);
}
moveAtSpeed(M_SPEED_L,M_SPEED_R);
DIR_LEFT = -1; DIR_RIGHT = -1;
writeString_P("$OK&");
send = 1;
}

// turn left
else if (strncmp("$D|LEFT", receiveBuffer,7) == 0) {
if ( DIR_LEFT == 1 || DIR_RIGHT == -1 )
stop();
setMotorDir(BWD,FWD);
moveAtSpeed(60,60);
DIR_LEFT = -1; DIR_RIGHT = 1;
writeString_P("$OK&");
send = 1;
}

// turn right
else if (strncmp("$D|RIGHT", receiveBuffer,8) == 0) {
if ( DIR_LEFT == -1 || DIR_RIGHT == 1 )
stop();
setMotorDir(FWD,BWD);
moveAtSpeed(60,60);
DIR_LEFT = 1; DIR_RIGHT = -1;
writeString_P("$OK&");
send = 1;
}

// stop
else if (strncmp("$D|STOP", receiveBuffer,7) == 0) {
stop();
M_SPEED_L = 0;
M_SPEED_R = 0;
writeString_P("$OK&");
send = 1;
}

// increase motorspeed
else if (strncmp("$D|BU", receiveBuffer, 5) == 0) {
if (M_SPEED_L <= (200 - SPEED_STEP) && M_SPEED_R <= (200 - SPEED_STEP)) {
M_SPEED_L += SPEED_STEP;
M_SPEED_R += SPEED_STEP;
}
moveAtSpeed(M_SPEED_L,M_SPEED_R);
writeString_P("$OK&");
send = 1;
}

// decrease motorspeed
else if (strncmp("$D|BD", receiveBuffer, 5) == 0) {
if (M_SPEED_L >= SPEED_STEP && M_SPEED_R >= SPEED_STEP) {
M_SPEED_L -= SPEED_STEP;
M_SPEED_R -= SPEED_STEP;
}
moveAtSpeed(M_SPEED_L,M_SPEED_R);
writeString_P("$OK&");
send = 1;
}

// increase left motorspeed
else if (strncmp("$D|LU", receiveBuffer, 5) == 0) {
if (M_SPEED_L <= (200 - SPEED_STEP)) M_SPEED_L += SPEED_STEP;
moveAtSpeed(M_SPEED_L, M_SPEED_R);
writeString_P("$OK&");
send = 1;
}

// increase right motorspeed
else if (strncmp("$D|RU", receiveBuffer, 5) == 0) {
if (M_SPEED_R <= (200 - SPEED_STEP)) M_SPEED_R += SPEED_STEP;
moveAtSpeed(M_SPEED_L, M_SPEED_R);
writeString_P("$OK&");
send = 1;
}

// decrease left motorspeed
else if (strncmp("$D|LD", receiveBuffer, 5) == 0) {
if (M_SPEED_L >= SPEED_STEP) M_SPEED_L -= SPEED_STEP;
moveAtSpeed(M_SPEED_L, M_SPEED_R);
writeString_P("$OK&");
send = 1;
}

// decrease right motorspeed
else if (strncmp("$D|RD", receiveBuffer, 5) == 0) {
if (M_SPEED_R >= SPEED_STEP) M_SPEED_R -= SPEED_STEP;
moveAtSpeed(M_SPEED_L, M_SPEED_R);
writeString_P("$OK&");
send = 1;
}

// set motorspeed to default value
else if (strncmp("$D|DEFAULT", receiveBuffer, 10) == 0) {
M_SPEED_L = 80;
M_SPEED_R = 80;
writeString_P("$OK&");
send = 1;
}

// nothing detected, set send to 0
else send = 0;

// if something was send, clear receiveBuffer
if (send) {
memset(receiveBuffer, '\0', charsToReceive);
for(uint8_t cnt = 0; cnt < charsToReceive; cnt++)

receiveBuffer[cnt]=0;
}

task_RP6System();


}

// End of main loop!

// ---------------------------------------



return 0;

}

radbruch
25.01.2009, 13:57
Hallo,

vielleicht wird der Empfangsbuffer beim RP6 nicht richtig geleert/gelöscht:
https://www.roboternetz.de/phpBB2/viewtopic.php?t=43254

Bei Telegrammen die über ein Netzwerk laufen könnte sich deren Reihenfolge ändern weil sich die Datenpakete gegenseitig überholen können. Erkennen kann man das z.B. über eine fortlaufende Sequenznummer die von beiden Partnern im Wechsel hochgezählt wird. Zum Debuggen könnte der RP6 auch das jeweilige Komando an seine Antwort anhängen.

Gruß

mic

SlyD
25.01.2009, 14:02
Moin,

hab mir den Code nur ne halbe Minute lang angesehen - was mir aber zusätzlich zu dem was Radbruch sagt sofort ins Auge gefallen ist ist das hier:

char sendValues[85];
memset(sendValues, '\0', sizeof(sendValues) );
sprintf(sendValues,"$M|BL:%d|BR:%d|LDRL:%d|LDRR:%d|UBAT:%d|OL:%d|OR:%d |ML:%d|MR:%d&",BL,BR,adcLSL,adcLSR,adcBat,OL,OR,M_SPEED_L,M_SPEE D_R);
writeString(sendValues);

Könnte durchaus sein, das hier mal ein Pointer ausbüchst und Dir anderswo den Speicher überschreibt. Oder der Stack läuft über - der String da oben ist ja
schon recht komplex. Auf jeden Fall musst Du das weiter aufsplitten.

Versuchs am besten mal komplett ohne sprintf und memset.
Mach es genauso wie im RP6 Selftest Programm mit writeInteger usw.

MfG,
SlyD

andieh
25.01.2009, 14:22
Danke SylD und radbruch für die schnellen Antworten.

Ich habe den langen String einfach mal rausgenommen und einfach nur einen konstanten String zurückgeschickt, aber auch das ändert nichts. Also glaube ich nicht daran, dass es daran liegt. Ich hatte sogar am Anfang diese Sache so gelöst, dann sind aber voll oft bestimmte Teile gar nicht erst angekommen, das war keine gute Lösung.

Und zu deinen Tipps radbruch: Ich habe das ganze Prinzip von dem Buffer noch gar nicht so geblickt. Da muss ich mich wohl noch eine weile einlesen.

Aber danke schon mal, ich werde es weiter probieren!

andieh
25.01.2009, 17:19
So, wieder etwas weiter probiert.
Problem ist auf jeden Fall, das der Server auf der Fonera eine Anfrage an den RP6 schickt und sofort auf eine Antwort wartet. So schnell ist der RP6 aber gar nicht, und deshalb geht eine Anfrage quasi ins "leere" und erst beim nächsten Mal wird das richtige Ergebnis übermittelt.

Habe mit verschiedenen Wartezeiten zwischen Senden und Empfangen gespielt, 10 ms scheinen zu kurz, bei 20 ms klappen zumindest die Aknowledges der Richtungswechsel. Aber das Sammeln aller Messwerte auf dem RP6 scheint wohl noch länger zu dauern. Und allgemein scheint mir diese Möglichkeit als sehr stümperhaft.

Habt ihr da eine andere Idee, wie man das lösen könnte?

TobeFFM
28.01.2009, 11:00
Wir haben das Problem übrigens mittlerweile gelöst, es lag wohl daran, dass die übertragungsgeschwindigkeiten vom rp6 zum router ziemlich schwanken..
Haben es jetzt so gelöst, dass wir eine empfangsschleife auf dem router laufen lassen, die erst abbricht, wenn wir das Endzeichen von unserem Protokoll bekommen. Es fällt auf, dass der RP6 den langen String von oben manchmal komplett auf einmal schickt, jedoch meistens in zwei "Sendungen" aufteilt..
Naja, mittlerweile funktioniert alles, sogar in ausreichender Geschwindigkeit, um den noch ordentlich steuern zu können.

Siedler_03
27.04.2009, 15:10
Hallo
Ich habe ein Programm zum Linienfolgen geschrieben und irgendeinen Fehler gemacht,den ich aber nicht finde und ich wollte jetzt kein neues Thema aufmachen, da hab ich mal das hier genommen.


Hier der Code:

/************************************************** ***************************/
// Includes:

#include "RP6RobotBaseLib.h"

/************************************************** ***************************/
//Declarations

uint8_t x = 0;

/************************************************** ***************************/
//functions
void drive_FWD(void)
{
moveAtSpeed(50,50);
}

void drive_LEFT(void)
{
moveAtSpeed(40,60);
}

void drive_RIGHT(void)
{
moveAtSpeed(60,40);
}

int ADC(void)
{
if((adc0 >= 1000) && (adc1 >= 1000))
{
x = 1;
}
if((adc0 < 1000) && (adc1 >= 1000))
{
x = 2;
}
if((adc0 >= 1000) && (adc1 < 1000))
{
x = 3;
}
}

void ADC_Case(void)
{
switch(x)
{
case 1: drive_FWD(); break;
case 2: drive_RIGHT(); break;
case 3: drive_LEFT(); break;
}
}

/************************************************** ***************************/
// Main:

int main(void)
{
initRobotBase();

while(true)
{
ADC();
ADC_Case();
task_RP6System();
}
return 0;
}



und die Fehlermeldung:

> "D:\Florian\Roboter\RP6BASE_EXAMPLES\linie_test_02\ \make_all.bat"

D:\Florian\Roboter\RP6BASE_EXAMPLES\linie_test_02>set LANG=C

D:\Florian\Roboter\RP6BASE_EXAMPLES\linie_test_02>make all

-------- begin --------
avr-gcc (GCC) 4.1.1 (WinAVR 20070122)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


Compiling: RP6Base_Move_04_FSM.c
avr-gcc -c -mmcu=atmega32 -I. -gdwarf-2 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=RP6Base_Move_04_FSM.lst -I../../RP6Lib -I../../RP6Lib/RP6base -I../../RP6Lib/RP6common -std=gnu99 -MD -MP -MF .dep/RP6Base_Move_04_FSM.o.d RP6Base_Move_04_FSM.c -o RP6Base_Move_04_FSM.o
RP6Base_Move_04_FSM.c:29: error: expected identifier or '(' before 'volatile'
RP6Base_Move_04_FSM.c:29: error: expected ')' before '(' token
RP6Base_Move_04_FSM.c: In function 'main':
RP6Base_Move_04_FSM.c:64: error: called object '*36u' is not a function
make: *** [RP6Base_Move_04_FSM.o] Error 1

> Process Exit Code: 2

SlyD
27.04.2009, 15:16
Ich weiss zwar nicht wie der Compiler auf diese Fehlermeldung kommt, aber:
int ADC(void)

die Funktion gibt aber nichts zurück (kein return xyz; am Ende).
Also void davorschreiben anstatt int.

MfG,
SlyD

McJenso
27.04.2009, 15:32
Hallo,

das ist nicht der passende Code.

Gruß

Jens

Siedler_03
27.04.2009, 15:54
Nicht der passende Code?
naja egal...hab den fehler gefunden