PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Motorgeschwindigkeitssynchronisation für ASURO



julien
18.05.2005, 21:15
Hallo! Ich möchte nun endlich mal meinem ASURO beibringen, geradeaus zu fahren, da er das nicht tut. Ich habe hier ein Programm entworfen, dass eigendlich die Motoren Synchronisieren soll (was es nicht tut). Bitte gebt hier eure Verbesserungsvorschläge ab.


#include "asuro.h"
int main(void){
int a;
int b;
int s;
unsigned int data[2];
Init();
a=0;
b=0;
s=100;
MotorDir(FWD,FWD);
while(1){
OdometrieData(data);
if (data[0] < 412){a++; BackLED(ON,OFF);}
if (data[1] < 412){b++; BackLED(OFF,ON);}
if (a<b){s++; StatusLED(RED);}
if (a>b){s--; StatusLED(YELLOW);}
if (a==b){StatusLED(GREEN);}
MotorSpeed(s,120);
}
return 0;
}

Habe ich vielleicht bloß einen Widerstand falsch eingelötet, der für die Geschwindigkeit der Motoren zuständig ist, oder ist das bei euch auch das selbe Problem?

Arexx-Henk
18.05.2005, 22:09
Hallo Julien,

ist mir auch immer noch nicht gelungen,

die 'OdometrieData()' function gibt die momentane helligkeit des reflectierten InfraRot (IR) licht. Beim linker/rechter rad gibts ein separaten IR sender und separaten IR empfanger.

Wenn Asuro fahrt drehen sich die odometrie schwarz/wiess scheiben unabhangig von der zeit dass deine 'while()' schleiffe lauft.

Ich meine, immer wenn die function 'OdometrieData()' ausgelesen wird gibts ein willkurlichen wert zwischen 0 und 255 abhangig ob ein weisen/schwarzen teil (oder ubergang) vom odometrierad gerade auf diesen moment an die IR detector vorbei geht.

Oder hab ich deine frage vielleicht falsch verstanden?
Kannst du mahl genauer sagen wie du die synchronisierung gemeint hast?

gruss

Henk

julien
19.05.2005, 06:34
Hallo!
Kann sein, dass ich mich falsch ausgedrückt habe.
Meine Frage war, wie man ein Programm entwerfen kann, damit beide Räder mit gleicher Geschwindigkeit laufen. Dazu werden die Gesamtdrehzahlen des linken und des rechten Rades ausgelesen (durch die Odometrie an den jeweils 1. großen Zahnrädern) und in zwei Zählervariablen (jeweils für das linke und rechte Rad) gespeichert. Da das rechte Rad immer mit konstanter Geschwindigkeit läuft, muss sich das linke Rad nach der Geschwindigkeit des rechten richten. Dafür werden die Variablen verglichen, um so den Unterschied festzustellen. Ist die Zahl der Variable des linken Rades größer als die des rechten, muss die Drehzahl des linken Rades verringert werden ansonsten vergrößert werden.
Mir scheint es so, als wenn du die Funktion OdometrieData() nicht ganz richtig verstanden hast, weil in der Anleitung steht, dass data[0] und data[1] einen Wert von minimal 0 (sehr dunkel) bis maximal 1023 (sehr hell) von der Odometriescheibe (die mit dem schwarz-weiß dreiecken im Kreis) rausschmeisst.
Außerdem habe ich einen Fehler bei den Zählervariablen gemacht, weil, wenn sich die Räder drehen, werden die Zählervariablen um 1 erhöht, und wenn man den Roboter lange genug laufen lässt, könnten die Zählervariablen zu groß werden. D.h. dass die Zählervariablen bloß bis zu einem bestimmten Wert gehen dürfen. Dazu darf eigendlich die Zählervariable der Drehzahl des rechten Rades bloß z.B. bis 10 gehen und dann müssen beide Zählervariablen (des linken und des rechten Rades) wieder bei 0 anfangen. So könnte man jetzt immer weiter rumexperimentieren...
Ich experimentier jetzt mal ein bisschen.
MfG julien

PicNick
19.05.2005, 07:47
Jetzt red' ich als Blinder von der Farbe, da ich den Asuro nicht näher kenne:
Die Odometrie scheinen zwei opt.Sensoren zu sein, deren Zustand dur abfragen kannst.
Du brauchst aber nicht den Zustand, sondern den Wechsel (hell/dunkel)
und immer bei einem Übergang zählst du.
Damit der Zähler nicht überlaufen kann, isses besser, bei einem Rad addierst du, beim anderen subtrahierst du, dann bleibt dir nur die Differenz über. Und je nach Vorzeichen reagierst du.

Arexx-Henk
19.05.2005, 08:09
Hallo,

da mit die 0-255 bin ich falsch, du hast recht, ist 0-1023.

Ich hatte mich schon mit dieses synchronisierung beschaftigt (nicht gelungen) und hatte dazu folgendes gemessen:

Bei speed = 0x70 fahrt Asuro 7 cm pro sekunde. (nachgemessen)
Bei eine umdrehung vom Aussenrad fahrt Asuro 12,3cm weit.
Dass sind 7/12,3 = 0,57 = ungefahr 0,5 Aussenrad umdrehungen pro Sekunde
Dass Odometrierad dreht zich 5 mal schneller als dass Aussenrad.
Es dreht sich 5 * 0,5 = 2,5 mal pro secunde.
Mit 4 schwarz/weiss dreiecken macht dass 4 * 2,5 = 10 schwarz/weiss ubergange pro Sekunde.

Ein einzigen while() Schleiffe daurt vielleicht nur 100us. Dass heist dass die while() Schleiffe 10.000 mal pro Sekunde oder 1.000 mal pro schwarz/weiss dreieck ausgefuhrt wird.

So lange die lichtwert kleiner ist als 412 werden die variabelen 'a' und 'b' erhoht. Damit werden die variabelen doch mit eine 'geschwindigkeit' von 10.000 mahl pro Sekunde erhoht.

Mann sollte sich doch die schwarz/weiss ubergange-pro-sekunde zahlen und nicht die Zeit zahlen wie lange ein reflectionswert unter zB 412 ist?

Irgendwo fasse ich's nicht. (ist vielleicht mijn fehler... O:) )

Aber lass es sein, ich bin gespannt, wenn Du es fertig bringst mochte ich auch mal dein program ausprobieren.

gruss

Henk

PicNick
19.05.2005, 08:51
Es gibt mehrere Möglichkeiten, das Odometrische Zeugs auszuwerten. Eine davon ist eben, die Anzahl der Übergänge links mit denen von rechts zu vergleichen.
Als Erstes machst du aus 0-1023 einen Nuller oder Einser
if (data[0] > 412) Lnow = 1; else Lnow = 0;
if (data[1] > 412) Rnow = 1; else Rnow = 0;
Um einen Übergang zu erkennen, brauchst du den Werte von jetzt und den von vorher (Lold , Rold),vergleichst auf Wechsel und zählst
if (Lnow ^ Lold) Count++; // links
if (Rnow ^ Rold) Count--; // rechts
Lold = Lnow; // merken
Rold = Rnow; // merken
// ---------------------------Vergleich:
If (Count > 0) { rechts -zu- langsam }
If (Count < 0) { rechts -zu- schnell }

Anm: Im Beispiel wird sowohl hell / dunkel als auch dunkel /hell gezählt. geht auch anders, is aber mal egal.

julien
19.05.2005, 12:37
Joa, danke! Werd's gleich mal damit ausprobieren.

julien
19.05.2005, 13:36
So sieht das jetzige Programm aus:


#include "asuro.h"
int main(void){
int Lnow;
int Rnow;
int Rold;
int Lold;
int Count;
int sl;
int sr;
unsigned int data[2];
unsigned char taste;
Init();
while(1){
Count=0;
sl=120;
sr=120;
MotorDir(FWD,FWD);
MotorSpeed(sr,sl);
OdometrieData(data);
if (data[0] > 412) Lnow = 1; else Lnow = 0;
if (data[1] > 412) Rnow = 1; else Rnow = 0;
if (Lnow ^ Lold) Count++;
if (Rnow ^ Rold) Count--;
Lold=Lnow;
Rold=Rnow;
if (Count>0) {sr++; BackLED(OFF,ON);}
if (Count<0) {sr--; BackLED(ON,OFF);}
if (sr>254){sr=255; sl--;}
if (sr<61){sr=60; sl++;}
}
return 0;
}

So müsste es gehn. Wenn nicht, gebt hier eure Verbesserungsvorschläge.

PicNick
19.05.2005, 13:50
Hopperla, das Count = 0 , sl = 120 etc. muß VOR der Schleife sein.
(Sonst ändert sich nie was )
Grundsätzlich sollt es so gehen.
Feinheiten kommen dann. Das Regelsystem darf sich nicht aufschaukeln können.
Je kleiner die Differenz, desto kleiner sollte auch die Reaktion sein, und vice versa. Vielleicht sollte man eine Differenz vom +/-1 überhaupt tolerieren, weil taktsynchron wird das wohl nie.
if (abs(Count) < 1)

Und wenn du mit der Speed oben oder unten anstehst, mußt du wohl auch ein Wort mit dem anderen Motor wechseln, sonst bricht Verzweiflung aus.

Let 'em Robbies roll !

rman
19.05.2005, 20:05
Hallo,

ich habe mir auch den Asuro zugelegt und wollte einen kleinen Tipp abgeben.
Passt bitte auf mit Odometrie und BackLED.
Schaut euch mal den Schaltplan auf Seite 74 an.
Dort sieht man dass die Fototransistoren T11 und T12 gekoppelt sind mit den BackLED D15 und D16. So wie ich das verstehe ist entweder Odometrie oder BackLED.
Beides gleichzeitig geht nicht. Wie ist eure Meinung?

Gruss
Robert

PicNick
20.05.2005, 06:27
Na dann hoff' ich, daß der Juilien das ev. berücksichtigt. Ich kann nix sagen dazu, keinerlei Unterlagen.

MSSputnik
20.05.2005, 17:45
Hi,

das mit den Back LED's ist korrekt. Beides geht nicht.
Wenn man sich den Sourcecode von OdometrieData ansieht, werden da auch die Back LED's explizit ausgeschaltet.
Wenn man beides verwendet bekommt man Phantasiewerte für die Odometrie :-(

PicNick
20.05.2005, 18:06
Oh je. Na, wenn er richtig fährt, isses ja nicht so schlimm, wenn nix leuchtet

julien
21.05.2005, 08:09
Jo, danke für eure Tipps. Ich werde dann wohl das mit den Back-LED's weglassen. Jetzt funktionierts!
@PicNick:
sagte: "Und wenn du mit der Speed oben oder unten anstehst, musst du wohl auch ein Wort mit dem anderen Motor wechseln, sonst bricht Verzweiflung aus."
Das habe ich ja beachtet siehe:
...
if (sr>254){sr=255; sl--;}
if (sr<61){sr=60; sl++;}
...
sr=Speed Rechts
sl=Speed Links

GE-RO
10.06.2005, 18:01
hallo, ich habe mir vor kurzem den asuro zusammen gebraten, und mit hilfe des oben geposteten codes selber mal was versucht, gebt mir bitte verbesserungs vorschläge und tipps^^


#include "asuro.h"

int main(void)
{

int Lnow;
int Rnow;
int Rold;
int Lold;
int Count1=0;
int Count2=0;
int sl=180;
int sr=180;
unsigned int data[2];
unsigned char taste;

Init();

while(1)
{
MotorDir(FWD,FWD);
MotorSpeed(sr,sl);

OdometrieData(data);

if (data[0] > 312) Lnow = 1; else Lnow = 0;

if (data[1] > 312) Rnow = 1; else Rnow = 0;

if (Lnow ^ Lold) Count1++;
if (Rnow ^ Rold) Count2++;

Lold=Lnow;
Rold=Rnow;

if (Count1>80 && Count2<80)
{
sr=180;
sl=sl+5;
Count1=0;
Count2=0;
}

else if (Count2==80 && Count1<80)
{
sl=180;
sr=sr+5;
Count1=0;
Count2=0;
}
}
return 0;
}

gruß
GE-RO

MSSputnik
10.06.2005, 21:27
Hi,

wie kommst du auf den Grenzwert 80? Ist das einfach eine experimentell ermittelte Zahl oder hat das eine Bedeutung?

Bei der 2. Bedinung prüft du: else if (Count2==80 && Count1<80) sollte es nicht heissen Count2>80 so wie in der ersten Bedingung?

Ansonsten: Fährt dein Asuro damit gerade aus oder nicht?

GE-RO
11.06.2005, 09:28
stimmt, das muss nicht == sondern > al 80 sein... 80 hab ich nur zufällig gewählt, da ich denke das der wert nicht zu groß und icht zu klein ist..

gruß
GE-RO

waste
11.06.2005, 10:38
Hallo GE-RO,

es ist immer schwer, sich in anderen Programmen zurecht zu finden. Irgendwie hast du auch links und rechts verwechselt.
Der Einfachheit halber hab ich mal meine Geradeaus-Routine in dein Programm eingebaut. Zuerst lief es auch nicht. Dann habe ich bemerkt, daß du in MotorSpeed() rechts und links vertauscht hattest. Nach Korrektur laufen die Räder mit meiner Routine jetzt synchron. siehe Code

Gruß waste



#include "asuro.h"

int main(void)
{

int Lnow;
int Rnow;
int Rold;
int Lold;
int Count1=0;
int Count2=0;
int diff;
int sl=180;
int sr=180;
unsigned int data[2];

Init();

while(1)
{
MotorDir(FWD,FWD);
MotorSpeed(sl,sr);

OdometrieData(data);

if (data[0] > 600) Lnow = 1; else Lnow = 0;

if (data[1] > 600) Rnow = 1; else Rnow = 0;

if (Lnow ^ Lold) Count1++;
if (Rnow ^ Rold) Count2++;

Lold=Lnow;
Rold=Rnow;

diff=Count2-Count1;
if (diff>0) sr--;
else if (diff<0) sl--;
else {sr=180; sl=180;}
if (sr<0) {sr=0;}
if (sl<0) {sl=0;}
}
return 0;
}

GE-RO
11.06.2005, 11:03
stimmt.. ich hab das verwechselt, hier nochmal komplett überarbeitet.. jetzt klappst ich habs selber gad ausprobiert.. ;)



#include "asuro.h"

int main(void)
{

int Lnow;
int Rnow;
int Rold;
int Lold;
int Count1=0;
int Count2=0;
int sl=180;
int sr=180;
unsigned int data[2];
unsigned char taste;

Init();

while(1)
{
MotorDir(FWD,FWD);
MotorSpeed(sr,sl);

OdometrieData(data);

if (data[0] > 312) Lnow = 1; else Lnow = 0;

if (data[1] > 312) Rnow = 1; else Rnow = 0;

if (Lnow != Lold) Count1++;
if (Rnow != Rold) Count2++;

Lold=Lnow;
Rold=Rnow;

if (Count2==80 && Count2<80)
{
sl=180;
sr=sr+5;
Count1=0;
Count2=0;
}

else if (Count1==80 && Count1<80)
{
sr=180;
sl=sl+5;
Count1=0;
Count2=0;
}
}
return 0;
}


gruß
GE-RO

julien
06.03.2007, 13:38
Hallo!
Danke! Ich werds mal testen.

MfG
Julien