Grüß Dich inka,
ich fange mal Hinten an.
"ping()" würde "run()" blockieren, nicht umgekehrt. die "run()" Funktionen müssen nachdem die Stepper konfiguriert sind immer wieder aufgerufen werden und das so schnell wie möglich, sonst hakt es.
Sowie Du Dein Programm aufgebaut hast, gibt's zwei kritische Dinge zu beachten:
Nachdem Du "gepingt" hast, fährst Du los. Wenn jetzt plötzlich etwas vor dem Roboter auftaucht - Eure Katze, Deine Füße oder die Schienbeine Deiner Liebsten - bekommt das das System nicht mit, sondern fährt einfach weiter - schlimmstenfalls "Aua"
.
Das andere Problem hast Du schon richtig erkannt, die gemessene Distanz vom Sensor muss größer sein als der Fahrweg.
Du legst im Moment bei gerade Fahren immer eine Umdrehung zwischen den "pings" zurück. Dein Grenzwert zum potentiellen Hinderniss sind aktuell 10cm. Das ist zu wenig, denn ich schätze Dein Raddurchmesser wird größer als 10cm/pi sein, oder?
Rechne mal nach Raddurchmesser * pi - dann muss "hindernis_vorh()" so aussehen:
Code:
{
if (start_ping == false) ping_distanz();
if(uS != NO_ECHO)
{
/* richtige Werte einsetzen */
if (((uS / US_ROUNDTRIP_CM) <= (Raddurchmesser * M_PI))
hindernis = true;
} else {
hindernis = false;
}
}
eine weitere Möglichkeit wäre statt "rotate(1)" "rotateDegrees(180)" oder mit anderen Werten kleinere Schritte zu machen. Das könnte dann zum Stottern führen. Momentan, vermute ich, bewegt die Trägheit den Robbi während des "pings" weiter, so das man das mit bloßem Auge nicht wahr nimmt. Einfach mal kleinere Werte mit "rotateDegrees()" ausprobieren.
Zum Thema "do{...}while()" und "doppelt gemoppelt":
Deine "loop()" sah auszugsweise so aus:
Code:
void loop() {
if (stepper[idx].isDone() && rueckwaerts == false && hindernis == true)
{
Serial.println("start - Stepper rückwärts- if-abfrage_1");
alle_stepper_rueckwaerts();
}
else if (stepper[idx].isDone() && vorwaerts == false && hindernis == false)
{
Serial.println("start - Stepper vorwärts- else-abfrage_1");
alle_stepper_vorwaerts();
}
// andere if's
for (idx = stepper_VL; idx < stepper_MAX; idx++)
{
stepper[idx].run();
}
}
Du testes zwangsweise am Anfang immer ab, ob die Stepper schon das letzte Kommando ausgeführt haben oder nicht.
Dadurch mischt Du inhaltlich "Sind die Stepper fertig?" mit "Wie wähle ich das nächste Kommando aus?".
Führst Du jetzt die innere Schleife ein egal ob "while(){}" oder "do{...}while()":
Code:
void loop() {
// Kommando Auswahl treffen
if (rueckwaerts == false && hindernis == true)
{
Serial.println("start - Stepper rückwärts- if-abfrage_1");
alle_stepper_rueckwaerts();
}
else if (vorwaerts == false && hindernis == false)
{
Serial.println("start - Stepper vorwärts- else-abfrage_1");
alle_stepper_vorwaerts();
}
// andere if's
// Stepper ausführen lassen
// Es muessen alle Stepper gleichzeitig getestet werden, sonst ist's falsch!
while( ! (stepper[stepper_VL].isDone() && stepper[stepper_HL].isDone()
&& stepper[stepper_VR].isDone() && stepper[stepper_HR].isDone() ) )
{
for (idx = stepper_VL; idx < stepper_MAX; idx++)
{
stepper[idx].run();
}
}
}
dann ist nach der inneren Schleife und vor dem nächsten "loop()" Ablauf absolut sicher, dass die Stepper ihre angewiesene Arbeit getan haben.
Dadurch reduzieren sich Deine "if()" Ausdrücke, die sich nur noch mit der Auswahl beschäftigen und sind meiner Meinung nach einfacher lesbar.
Das Konzept der CustomStepper-Lib basiert darauf 1) die Stepper zu konfigurieren was sie tun sollen "rotate()", "setDirection()" etc. und dann 2) sie solange mit "run()" in Schwung zu halten, bis "isDone()" wahr wird. Genau das spiegelt sich in letzterem Aufbau wieder.
Ich hoffe ich hab's verständlich erklärt?
Gruß
Chris
Lesezeichen