PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : fehlerhafte kommunikation mit Rp6



amin105
05.01.2008, 13:17
hallo zusammen,
das ist mein erster Beitrag. ich hoffe, mir geling´s das Fehler gut zu beschreiben.
folgendes klein programm habe ich geschrieben:

while(true)
{
writeString_P("\n please Target position: ");
receiveBytesToBuffer(bytesToReceive,&receiveBuffer[0]);
TargetPosition=(uint8_t)receiveBuffer[0];

writeString_P("\n Target position is: ");

writeInteger(TargetPosition,DEC);

}

ich nutze den Terminal vom Rp6 loader für die Ein/Ausgabe.
Wenn ich .n10 als integer eingebe, wird im Terminal TX: -> 10 gezeigt. O:)
aber irgendwie wird nicht die 10 als dezimalzahl zum rp6 weitergeleitet, sondern, vermute ich, nur die '1' als character. Das merke ich an der Ausgabe meines Programms:
Target position is: 49

dh. egal ob ich 10, 11, bis 19 eingebe, bekomme ich immer die 49 raus, weil immer das erste char 1 interpretiert wird.

mache ich da ein Fehler oder habe ich die funktionsweise vom Terminal nicht verstanden !!!
danke für eure Hilfe
---------------------------
amin

radbruch
05.01.2008, 14:01
Hallo amin

Nein, du machst eigentlich nicht wirklich einen Fehler und du hast das Problem auch schon selbst erkannt: Der ASCII-Code für "1" ist 49, deshalb wird dein Target auch als 49 erkannt.

Einfach Lösung wäre vielleicht:

receiveBytesToBuffer(bytesToReceive,&receiveBuffer[0]);
Temp=(uint8_t)receiveBuffer[0]-48;
receiveBytesToBuffer(bytesToReceive,&receiveBuffer[0]);
TargetPosition=(uint8_t)receiveBuffer[0]-48;
TargetPosition+=temp*10;

Temp speichert die Zehner, 48 ist der Code für "0" und dient der Umrechnung von ascii zu Wert. Allerdings must du nun führende Nullen mit eingeben.

Das geht sicher viel eleganter wenn man gleich zwei Zeichen einliest (über bytesToReceive=2 und receiveBuffer[1]?) und einem Timeout für einstellige Zahlen, aber mit der seriellen Kommunikation habe ich mich bisher noch nicht beschäftigt.

Gruß

mic

amin105
05.01.2008, 15:34
danke radbruch für deinen Vorschlag,
daran habe ich auch schon gedacht (eine 2 stellige Zahl über zwei Byte zu schicken). Aber ich will mit solche Lösungen erst anfangen, wenn ich weiss, dass das Terminal so programmiert ist (was ich aber bezweifle).

in der Hilfe vom Terminal steht das man eine Zahl (1 Byte) in 3 formen schicken kann: hexadecimal, decimal oder octal. Ich habe allen probiert , es kommt immer das gleiche raus, dh. auch mit 0x01 bekomme ich nicht die 1 als Ausgabe sondern die 49.
hat jemand so ein problem schon gehabt?

SlyD
05.01.2008, 16:06
Hallo amin,

erstmal arbeitest Du anscheinend noch mit einer alten RP6Lib Version. In der neuen ist der Empfang von Daten über die serielle Schnittstelle etwas anders gelöst. Die neue Version gibts hier: http://www.arexx.com/rp6


Poste auch mal Dein komplettes Programm. Wenn immer 49 rauskommt, ist irgendwo anders was nicht richtig....
Ich hab das hier gerade selbst getestet (allerdings mit den neuesten Versionen) und eigentlich keine Probleme gehabt.


------------------------------

Die Auswertung von normalen Text Eingaben ist auch nicht so schwierig - hier ein paar Auszüge aus einem Beispielprogramm (neue Versionen von der RP6 Homepage!):



char receiveBuffer[charsToReceive+1]; // <<-- da kommt der Text rein

clearReceptionBuffer(); // Empfangspuffer leeren

uint8_t buffer_pos = 0;
while(true)
{
if(getBufferLength()) // Sind neue Zeichen da?
{
receiveBuffer[buffer_pos] = readChar(); // Ein Zeichen lesen
if(receiveBuffer[buffer_pos]=='\n' || buffer_pos >= charsToReceive) // Ende?
{
receiveBuffer[buffer_pos]='\0';
buffer_pos = 0;

break; // Schleife beenden! // ***1 s. unten
}
buffer_pos++;
}
}


Dieser Code empfängt eine komplette Eingabezeile (also bis zum Zeilenumbruch) bzw. bricht bei der maximalen Länge ab.


Danach kann man optional noch überprüfen ob es sich auch um einen Zahlenwert handelt:



uint8_t cnt;
uint8_t is_a_number = 1;
for(cnt = 0;cnt < 3 && receiveBuffer[cnt] != '\0'; cnt++)
{
if(!(receiveBuffer[cnt] >= '0' && receiveBuffer[cnt] <= '9'))
{
is_a_number = 0;
break;
}
}


Kann man aber komplett weglassen wenn man sicher ist, dass immer eine Zahl eingegeben wird.

Wenn es eine Zahl ist, dann kann per "atoi" (array-to-integer) Funktion aus der AVR Libc der Zahlenwert in eine Variable geschrieben werden.



if(is_a_number)
{
uint16_t value = atoi(receiveBuffer);
// ... mach was damit ...
}
else
// Keine Zahl...



So kann man wie z.B. beim Testprogramm einfach die Zahl eingeben ohne .n davor...

MfG,
SlyD

PS:

Bei
// ***1
könnte man auch den empfangenen Text verarbeiten und die Schleife nicht verlassen (Dann muss man hier nochmal clearReceptionBuffer usw. aufrufen)
So könnte man innerhalb der while(true) Schleife noch andere Sachen nebenbei machen - z.B. die Motoren regeln etc..

amin105
05.01.2008, 17:37
hallo SlyD,
es kommt nicht immer nur die 49 raus. Ich wollte nur bei dem Beispiel bleiben. Beim eingeben von 21 oder 22 ...29 kommt die 50 raus. und genaus so für die 3x kommt die 51 raus.
hier ist das komplete code


#include "RP6RobotBaseLib.h"
#define bytesToReceive 1

char receiveBuffer[bytesToReceive];
uint8_t TargetPosition;

int main(void)
{
initRobotBase(); // Always call this first! The Processor will not work
// correctly otherwise.

setLEDs(0b111111); // Turn all LEDs on
mSleep(500); // delay 500ms
setLEDs(0b000000); // All LEDs off

while(true)
{
writeString_P("\n please Target position: ");
receiveBytesToBuffer(bytesToReceive,&receiveBuffer[0]);
TargetPosition=(uint8_t)receiveBuffer[0];

writeString_P("\n Target position is: ");

writeInteger(TargetPosition,DEC);

}

return 0;
}


ich werde aber die neue Lib runterladen und testen. Danke.

SlyD
05.01.2008, 17:45
Hmm was mir gerade schonmal direkt auffällt:
char receiveBuffer[bytesToReceive];

sollte immer _mindestens_ 1 Zeichen größer sein --> also bytesToReceive+1.
Daran könnte es schon liegen.

MfG,
SlyD

PS:
Zur neuen Lib brauchst Du auch eine neue Version vom RP6Loader, da die erste noch nicht am Ende jeder Eingabe einen Zeilenumbruch gesendet hat.
(das kann man jetzt in den Optionen einstellen)

PPS:
Habs gerade mit Deinem Code und aktueller RP6Loader Version probiert - damit klappt es problemlos.

amin105
05.01.2008, 21:22
hallo SlyD,
ich teste nun mit der neuen Lib und auch die beta version vom RP6Loader 1.4.
1) der Loader startet sofort das Programm auf Rp6 auch wenn ich nur Upload aktiviere!!!
2) Ich habe das gleiche problem wie vorher. Die Komm. beim Hinweg ist falch, ich gebe eine 1, es wird aber eine 49 zur rp6 geschickt.

Es liegt mit sicherheit nicht an das C-Programm, aber auch nicht am Terminal selber, weil du das getestet hast bei dir.
kann das irgend eine falche Konfiguration bei mir sein??
hier ist das neue code falls jemand das auch testen möchte um zu sehen ob es wo anders gut klappt:




#include "RP6RobotBaseLib.h"
#define charsToReceive 5

uint8_t TargetPosition;

int main(void)
{
initRobotBase(); // Always call this first! The Processor will not work
// correctly otherwise.

setLEDs(0b111111); // Turn all LEDs on
mSleep(500); // delay 500ms
setLEDs(0b000000); // All LEDs off

while(true)
{

char receiveBuffer[charsToReceive+1]; // <<-- da kommt der Text rein
clearReceptionBuffer(); // Empfangspuffer leeren
writeString_P("\n Zielposition eingeben: \n");
uint8_t buffer_pos = 0;
while(true)
{
if(getBufferLength()) // Sind neue Zeichen da?
{
writeString_P("\n bin im ersten If drin \n");
receiveBuffer[buffer_pos] = readChar(); // Ein Zeichen lesen

if(receiveBuffer[buffer_pos]=='\n' || buffer_pos >= charsToReceive) // Ende?
{
writeString_P("\n bin im zweiten If drin \n");
receiveBuffer[buffer_pos]='\0';
buffer_pos = 0;

break; // Schleife beenden! // ***1 s. unten
}
buffer_pos++;
}
}
writeChar('\n');
writeStringLength(receiveBuffer,charsToReceive,0);

TargetPosition=(uint8_t) receiveBuffer[0];
writeString_P("\n Target position is: \n");
writeInteger(TargetPosition,DEC);

}

return 0;
}

amin105
05.01.2008, 21:32
hallo,
vergisst mal den 2ten punkt von meinem Beitrag, es funktioniert doch jetzt mit der neuen Lib und neue Loader. Danke SlyD für deiner Hilfe.

SlyD
05.01.2008, 21:38
Hallo,

OK gut - hatte das gerade schon bei mir getestet und hier hats auch funktioniert...

Noch zu Punkt 1:



1) der Loader startet sofort das Programm auf Rp6 auch wenn ich nur Upload aktiviere!


Es gibt nun zwei verschiedene Upload Buttons - einer der nur das Programm in den Roboter lädt und einer der es danach sofort startet.
Falls man verhindern will das man versehentlich auf "Upload+Start" klickt gibt es in den Einstellungen eine Option "Software Start erlauben".

Man kann das übrigens auch im Terminal über die Tastatur steuern:
STRG+Y = "Upload+Start"
STRG+D = "Upload"
STRG+S = "Start"
STRG+R = "Reset / Stop"
...


MfG,
SlyD

amin105
05.01.2008, 21:58
hallo SlyD,
jetzt nachdem ich das Loader neu starte merke ich dass das Button Upload allein das Programm nicht startet. Also es ist alles Ok
Warum habe ich vorher was anders festgestellt, weisse ich nicht. Villeicht bin ich jetzt einfach müde und brache eine Pause. Also Tschüß und danke.
--------
MfG, Amin