PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Asuro steigt nicht aus while schleife aus



kmikesch
19.06.2011, 14:25
Hallo,
Ich habe ein kurzes Programm geschrieben, mir dem der Asuro einer Linie folgen soll und bei Kollision stoppen. Das mit dem Linie verfolgen klappt Prima nur nicht mit dem stoppen und anschließendem BackLed aufleuchten. Hier ist mein Programm:


#include "asuro.h"
#include "myasuro.h"

int main(void)
{
unsigned int ldata[2];
Init();
int a;
FrontLED(ON);
MotorDir(FWD,FWD);
a=1;
while(a)
{
LineData(ldata);
if (ldata [0] > ldata [1])
{
MotorSpeed(200,100);
}
else if (PollSwitch()>0)
{
a=0;
}
else
{
MotorSpeed(100,200);
}
}
return(0);
BackLED(ON,ON);
}


Hier noch ein paar Daten: Ich programiere mit AVR_Studio mit der AsuroLib-v280rc1 auf C für einen Atmega 8
Also wie schon gesagt das mit der Linienverfolgung klappt nur er hält nicht an bei kollosion, while(a=1) wird also nicht a=0.
Weiß irgendwer was ich ändern muss, dass er stehen bleibt?
Vielen Dank

PicNick
19.06.2011, 14:38
Nun, wenn Pollswitch > 0, dann wird zwar a=0 gesetzt aber motormässig passiert nix.
Wegen A=0 wird while() unterbrochen.

das nächste hinter while() ist ein return, damit ist das Programm zu ende,


BacKled() steht HINTER dem Return, kommt also niemals dran.

kmikesch
19.06.2011, 14:45
Was meinst du damit, das verstehe ich nicht, wie muss das Programm nun aussehen? Wo muss ich was ändern?? Vielen Dank

markusj
19.06.2011, 15:00
a) Du hältst den Motor nie an.
b) Nach return ist dein Programm zuende, was auch immer du danach schreibst, wird NIEMALS ausgeführt werden.

mfG
Markus

radbruch
19.06.2011, 15:10
In C wird die Hauptfunktion main() normalerweise von einem übergeordneten Betriebssystem aufgerufen und über return springt das Programm zum aufrufenden Punkt zurück. Dieser Rücksprungpunkt ist bei AVR-GCC (http://www.rn-wissen.de/index.php/Avr-gcc) aber nicht defininiert, deshalb springt das Programm ins Nirwanwa, wenn es mit return beendet wird.

Ein Programm könnte etwa so aussehen:


#include "asuro.h"
#include "myasuro.h"

int main(void)
{
unsigned int ldata[2];

Init();
FrontLED(ON);
Sleep(255); // warten bis FrontLED leuchtet
LineData(ldata); // ADC auf Betriebstemperatur bringen
// MotorDir(FWD,FWD); // Init() setzt MotorDir schon auf FWD,FWD
MotorSpeed(150,150); // losfahren
while(1)
{
LineData(ldata); // Liniensensoren einlesen

if (ldata [0] > ldata [1]) // links heller, nach rechts fahren
{
MotorSpeed(200,100);
StatusLED(RED);
}
else
{
MotorSpeed(100,200); // rechts heller (oder gleich), nach links fahren
StatusLED(YELLOW);
}

if (PollSwitch()>0) // Taster betätigt?
{
MotorSpeed(0,0); // wenn ja, dann stop
StatusLED(GREEN);
BackLED(ON,ON);
while(1); //Stop und Ende
}
}
return(0); // darf nie ausgeführt werden!
}(ungetestet)

Das funktioniert aber nur, wenn PollSwitch() richtig arbeitet.

kmikesch
19.06.2011, 15:30
19081

ok gut, aber wie müsste es denn aussehen, wenn ich a beibehalten soll also a schon auf 0 gesetzt werden muss?? Denn mei eigentliches Programm sieht so aus: Er soll einer Linie folgen, bei Kollision einen Becher (Servo über Backled angeschlossen) heben, ich untersuchen ob schwarz oder weiß (Odometiesensor nach vorn gelegt) nach links oder Rechts fahren je nachdem welche Farbe, linie Folgen bis Kollision nochmals drehen und auf ursprüngliche Linie fahren.


#include "asuro.h"
#include "myasuro.h"

int main(void)
{
unsigned int odata[2];
unsigned int ldata[2];
Init();
int a;
int b;
int c;
int d;
int e;
int f;
FrontLED(ON);
while(1)
{
MotorDir(FWD,FWD);
a=1;
c=1;
d=1;
while(a)
{
LineData(ldata);
if (ldata [0] > ldata [1])
{
MotorSpeed(200,100);
}
else if (PollSwitch()>0)
{
a=0;
}
else
{
MotorSpeed(100,200);
}
}
return(0);
for (b=0; b<40; b++)
{
BackLED(OFF,ON);
Msleep(1);
BackLED(OFF,OFF);
Msleep(19);
}
}
{
OdometrieData(odata);
if (odata[0] > 500)
{
{
MotorSpeed(0,200);
Msleep(1000);
MotorSpeed(200,200);
}
while(c)
{
LineData(ldata);
if (ldata [0] > ldata [1])
{
MotorSpeed(200,100);
}
else if (PollSwitch()>0)
{
c=0;
for (f=0; f<40; f++)
{
BackLED(OFF,ON);
Msleep(2);
BackLED(OFF,OFF);
Msleep(18);
}
}
else
{
MotorSpeed(100,200);
}
}
return(0);
}
{
MotorSpeed(100,200);
Msleep(1000);
MotorSpeed(200,200);
}
OdometrieData(odata);
if (odata[0] < 500)
{
{
MotorSpeed(200,0);
Msleep(1000);
MotorSpeed(200,200);
}
while(d)
{
LineData(ldata);
if (ldata [0] > ldata [1])
{
MotorSpeed(200,100);
}
else if (PollSwitch()>0)
{
d=0;
for (e=0; e<40; e++)
{
BackLED(OFF,ON);
Msleep(2);
BackLED(OFF,OFF);
Msleep(18);
}
}
else
{
MotorSpeed(100,200);
}
}
return(0);
}
{
MotorSpeed(100,200);
Msleep(1000);
MotorSpeed(200,200);
}
}
return(0);
}

kmikesch
19.06.2011, 15:33
Dazu benötige ich Variablen ich habe die einzelnen Programmteile getestet und sie funktionieren aber eben nicht das mit den Tastern die Variablen werden nicht auf 0 gesetzt die whileschleifen werden nicht verlassen

radbruch
19.06.2011, 17:00
Hallo

Großes Lob, weil dein Programm fehler- und warnungsfrei übersetzt werden kann. Großer Tadel: Wo sind die Kommentare?

Ich habe dein Programm nochmals umformatiert:

#include "asuro.h"
#include "myasuro.h"

int main(void)
{
unsigned int odata[2];
unsigned int ldata[2];
int a;
int b;
int c;
int d;
int e;
int f;

Init();
FrontLED(ON);
while(1)
{
MotorDir(FWD,FWD);
a=1;
c=1;
d=1;
while(a)
{
LineData(ldata);
if (ldata [0] > ldata [1])
{
MotorSpeed(200,100);
}
else if (PollSwitch()>0)
{
a=0;
}
else
{
MotorSpeed(100,200);
}
}
return(0);
for (b=0; b<40; b++)
{
BackLED(OFF,ON);
Msleep(1);
BackLED(OFF,OFF);
Msleep(19);
}
}
{
OdometrieData(odata);
if (odata[0] > 500)
{
{
MotorSpeed(0,200);
Msleep(1000);
MotorSpeed(200,200);
}
while(c)
{
LineData(ldata);
if (ldata [0] > ldata [1])
{
MotorSpeed(200,100);
}
else if (PollSwitch()>0)
{
c=0;
for (f=0; f<40; f++)
{
BackLED(OFF,ON);
Msleep(2);
BackLED(OFF,OFF);
Msleep(18);
}
}
else
{
MotorSpeed(100,200);
}
}
return(0);
}
{
MotorSpeed(100,200);
Msleep(1000);
MotorSpeed(200,200);
}
OdometrieData(odata);
if (odata[0] < 500)
{
{
MotorSpeed(200,0);
Msleep(1000);
MotorSpeed(200,200);
}
while(d)
{
LineData(ldata);
if (ldata [0] > ldata [1])
{
MotorSpeed(200,100);
}
else if (PollSwitch()>0)
{
d=0;
for (e=0; e<40; e++)
{
BackLED(OFF,ON);
Msleep(2);
BackLED(OFF,OFF);
Msleep(18);
}
}
else
{
MotorSpeed(100,200);
}
}
return(0);
}
{
MotorSpeed(100,200);
Msleep(1000);
MotorSpeed(200,200);
}
}
return(0);
}Man sieht nun deutlich die extreme Verschachtelung und die Wiederholungen der einzelnen Programmteile. Vielleicht solltest du mal den Ablauf analysieren:

Folge_Line_bis_Becher_erkannt_wird();
Schliesse_Greifer();
Links_oder_Rechts_abbiegen();
Folge_Line_bis_Becher_erkannt_wird();
Öffne_Greifer();

Das sollte es im Wesentlichen sein. Es soll wohl sowas werden:


http://www.youtube.com/watch?v=RBySxcFqP4o

btw: return in main() beendet das Programm sofort!!!

Gruß

mic

kmikesch
19.06.2011, 18:28
Ja sowas in der Art soll es werden, wusste ich gar nicht das es den Film auch gibt... Hab aber nicht abgekupfert... Was kann ich jetzt machen, dass es was wird? was könnte es verbessern? denn das ist ja genau das gleiche Programm oder? soll ich wie du gesagt hast die Kommentare hinzufügen oder was genau? Aber das ändert ja nichts an der Funktionsweiße...

kmikesch
19.06.2011, 18:46
Hier noch ein paar Bilder, ich entschuldige mich gleich für die Qualität, aber bei meiner Internetverbindung muss ich es soweit runterrechnen wie es geht.190861908719088

kmikesch
19.06.2011, 18:48
Wie schon zu sehen: der Greifer bewegt durch den Servo und das schwarze Kästchen vorne, indem der Sensor und eine blaue Led zur Helligkeitsmessung drin sind, dank diesem Kästchen werden fast immer richtige Messergebnisse egal bei welcher Umgebungshelligkeit gemessen.

radbruch
19.06.2011, 19:08
Ne, Kommentare ändern natürlich nichts an der Funktionsweise, aber sie helfen auch dir selbst dein eigenes Programm zu verstehen. Ich hab' mal versucht deine Gedanken in ein Programm zu packen:


#include "asuro.h"
#include "myasuro.h"

int main(void)
{
unsigned int data[2]; // Speicherplatz für Odo- und Linedaten
int i; // Integervariable zur freien Verwendung

Init();
FrontLED(ON); // Linienbeleuchtung einschalten
Sleep(255); // warten bis LED volle Helligkeit erreicht hat
LineData(data); // ADC anwärmen
while(1)
{
MotorSpeed(200,200); // und losfahren

while(PollSwitch() == 0) // folge der Linie bis zum ersten Hinderniss
{
LineData(data);
if (data [0] > data [1])
MotorSpeed(200,100);
else
MotorSpeed(100,200);
Sleep(100); // Regelung etwas dämpfen
}

MotorSpeed(0,0); // anhalten weil Hinderniss erkannt wurde
Msleep(500);

for (i=0; i<40; i++) // Becher aufnehmen (Servoimpuls 40x senden)
{
BackLED(OFF,ON);
Msleep(1); // Impulslänge 1ms
BackLED(OFF,OFF);
Msleep(19); // Impulspause 19ms
}

OdometrieData(data); // Becherfarbe ermitteln
if (data[0] > 500)
{
MotorSpeed(0,200); // hell bedeutet nach links abbiegen
StatusLED(YELLOW);
}
else
{
MotorSpeed(200,0); // dunkel bedeutet nach rechts abbiegen
StatusLED(RED);
}

Msleep(1000); // eine Sekunde drehen
StatusLED(GREEN); //fertig
MotorSpeed(200,200); // weiterfahren (und hoffen, dass die Linie noch da ist ;)

while(PollSwitch() == 0) // folge der Linie bis zum zweiten Hinderniss
{
LineData(data);
if (data [0] > data [1])
MotorSpeed(200,100);
else
MotorSpeed(100,200);
Sleep(100);
}

MotorSpeed(0,0); // nochmals anhalten
Msleep(500);

for (i=0; i<40; i++) // und Becher wieder ablegen
{
BackLED(OFF,ON);
Msleep(2); // Impulslänge 2ms
BackLED(OFF,OFF);
Msleep(18); // Prima!
}

// Vermutlich sollten wir jetzt nochmals drehen. Da wir aber vergessen haben,
// welche Farbe der Becher hatte, wissen wir nicht, wohin wir drehen sollen ;)
}
return(0);
}Allerdings kann ich nicht sagen, ob das so funktioniert.

Schicker Greifer. Irgendwo habe ich den auch schon mal gesehen ;)

Gruß

mic

Edit: Ich vermute, hell und dunkel für die Becherfarbe sind vertauscht...

kmikesch
19.06.2011, 20:21
Hallo, also vielen Dank das funktioniert schon ganz gut, nur am ende fährt der Asuro wild durch die gegend und betätigt die ganze Zeit den Greifer, aber soweit ist das ganz gut, ich mache jetzt einfach wieder Odata und Ldata daraus.. Noch eine Frage an der Stelle, kann ich die Odata später nochmal aufrufen oder soll ich einfach neu messen lassen??
Vielen Dank

radbruch
19.06.2011, 20:35
Also ich finde es echt bemerkenswert, wie du die Gedanken aufgreifst und weiterdenkst. Selbstverständlich wäre das Ergebniss der letzten Lesung immer noch in odata gespeichert und könnte ohne erneute Lesung verwendet werden. An dieser Stelle habe ich wohl etwas überoptimiert ;)


..nur am ende fährt der Asuro wild durch die gegend und betätigt die ganze Zeit den Greifer,..Seltsam, vielleicht stimmt an dieser Stelle irgendetwas mit der Tastererkennung nicht. Ein Video wäre prima.

Noch ein Hinweis zu deinem Ansatz mit den vielen Variablen, was ja eigentlich der Ansatz einer StateMachine ist:

http://www.rn-wissen.de/index.php/Sourcevergleich#State_Machine
http://www.google.de/search?q=c+state+machine

Ach ja, und das habe ich ganz vergessen:

Willkommen im RN-Forum und Glückwunsch zum asuro.

Gruß

mic

kmikesch
19.06.2011, 20:45
Also ich habe jetzt das Programm mal so umgeschrieben als wüsste er es nicht mehr, wie findest du das Programm so?


#include "asuro.h"
#include "myasuro.h"

int main(void)
{
unsigned int odata[2];
unsigned int ldata[2]; // Speicherplatz für Odo- und Linedaten
int i; // Integervariable zur freien Verwendung

Init();
FrontLED(ON); // Linienbeleuchtung einschalten
Sleep(255); // warten bis LED volle Helligkeit erreicht hat
LineData(ldata); // ADC anwärmen
while(1)
{
MotorSpeed(200,200); // und losfahren

while(PollSwitch() == 0) // folge der Linie bis zum ersten Hinderniss
{
LineData(ldata);
if (ldata [0] > ldata [1])
{
MotorSpeed(200,100);
}
else
{
MotorSpeed(100,200);
}
Sleep(100); // Regelung etwas dämpfen
}
MotorSpeed(0,0); // anhalten weil Hinderniss erkannt wurde
Msleep(500);

OdometrieData(odata); // Becherfarbe ermitteln
if (odata[0] > 950)
{
for (i=0; i<20; i++) // Becher aufnehmen (Servoimpuls 20x senden)
{
BackLED(OFF,ON);
Msleep(1); // Impulslänge 1ms
BackLED(OFF,OFF);
Msleep(19); // Impulspause 19
}
MotorSpeed(0,200); // hell bedeutet nach links abbiegen
StatusLED(YELLOW);
}
else
{
for (i=0; i<20; i++) // Becher aufnehmen (Servoimpuls 20x senden)
{
BackLED(OFF,ON);
Msleep(1); // Impulslänge 1ms
BackLED(OFF,OFF);
Msleep(19); // Impulspause 19ms
}
MotorSpeed(200,0); // dunkel bedeutet nach rechts abbiegen
StatusLED(RED);
}

Msleep(1000); // eine Sekunde drehen
StatusLED(GREEN); //fertig
MotorSpeed(200,200); // weiterfahren (und hoffen, dass die Linie noch da ist ;)

while(PollSwitch() == 0) // folge der Linie bis zum zweiten Hinderniss
{
LineData(ldata);
if (ldata [0] > ldata [1])
{
MotorSpeed(200,100);
}
else
{
MotorSpeed(100,200);
}
Sleep(100);
}

MotorSpeed(0,0); // nochmals anhalten
Msleep(500);

for (i=0; i<20; i++) // und Becher wieder ablegen
{
BackLED(OFF,ON);
Msleep(2); // Impulslänge 2ms
BackLED(OFF,OFF);
Msleep(18); // Prima!
}

OdometrieData(odata); // Becherfarbe ermitteln
if (odata[0] > 950)
{
MotorSpeed(0,200); // hell bedeutet nach links abbiegen
StatusLED(YELLOW);
}
else
{
MotorSpeed(200,0); // dunkel bedeutet nach rechts abbiegen
StatusLED(RED);
}
Msleep(1000); // eine Sekunde drehen
StatusLED(GREEN); //fertig
MotorSpeed(200,200);
}
return(0);
}

kmikesch
19.06.2011, 21:02
Noch eine Sache zu der State Machine, ich verstehe nicht so ganz was ich damit machen soll was meinst du damit?

radbruch
19.06.2011, 21:03
Jetzt ist es doppelt gemoppelt. Wenn du ldata und odata getrennt verwendest, steht der letzte Wert (vom Aufnehmen des Bechers) noch in odata[0]. Aber prinzipiell sollte es auch so funtionieren, wenn der Becher nach dem Abstellen noch die selben ODO-Werte erzeugt. Funktioniert es denn nun mit deiner Änderung zufriedenstellend?

Eine Statemachine beschreibt ein Programm das in mehreren aufeinanderfolgenden Schritten ausgeführt wird. Wenn ein Schritt erledigt ist wird der nächste Schritt ausgeführt. Das war wohl im Ansatz auch der Sinn von deinem while(a)...

kmikesch
19.06.2011, 21:36
Hier noch ein kurzes Filmchen was der Asuro jetzt macht:
Igendwie unerklärlich, ich greife einmal kurz ein, damit die Sensoren sicher auf der Linie sind.

http://www.facebook.com/?ref=home#!/video/video.php?v=107369102690419&comments

kmikesch
19.06.2011, 21:50
kannst du mir vielleicht erklären warum der sowas macht??

radbruch
19.06.2011, 21:57
Blöderweise habe ich keinen Facebook-Acount...

kmikesch
19.06.2011, 22:01
Wie kann ich dann einen Film hier reinstellen

kmikesch
19.06.2011, 22:04
Ich hab nochwas mit dem Programm gemacht, das ist jetzt aber nur so zum Testen, ob die Motoren und taster richtig funktionieren und nein sie tun es nicht, aber hier das testprogramm:

#include "asuro.h"
#include "myasuro.h"

int main(void)
{
unsigned int ldata[2]; // Speicherplatz für Odo- und Linedaten
int i; // Integervariable zur freien Verwendung

Init();
FrontLED(ON); // Linienbeleuchtung einschalten
Sleep(255); // warten bis LED volle Helligkeit erreicht hat
LineData(ldata); // ADC anwärmen
while(1)
{
MotorSpeed(200,200); // und losfahren

while(PollSwitch() == 0) // folge der Linie bis zum ersten Hinderniss
{
LineData(ldata);
if (ldata [0] > ldata [1])
{
MotorSpeed(200,100);
}
else
{
MotorSpeed(100,200);
}
Sleep(100); // Regelung etwas dämpfen
}
StatusLED(RED);
MotorSpeed(0,0); // anhalten weil Hinderniss erkannt wurde
Msleep(2500);
StatusLED(GREEN); //fertig
}
return(0);
}

Was meinst du?

kmikesch
19.06.2011, 22:10
Ok ich habe den kaputten taster gefunden und schlicht entfernt, jetzt schaue ich noch nach den Motoren

Valen
20.06.2011, 11:41
Wie kann ich dann einen Film hier reinstellenHochladen zu zbs, Youtube? Kein Profil benötigt für schauen.

kmikesch
26.06.2011, 20:34
Hallo,
Ich möchte hier nur noch kurz auf mein neues Thema hinweißen, auf das ich in diesem Thema hinweißen möchte es gent darum, wie man auf ein schon gemessenes Odometrieergebniss nochmals zugereifen kann.
Bitte entweder hier oder im anderen Thema antworten.
Vielen dank
Hier das andere Thema: https://www.roboternetz.de/community/showthread.php?53763-Odometrie-Daten-2x-abrufen