Danke inka, Dir auch gutes neues Jahr!
Es tut mir leid, ich war so fixiert darauf Deine if's ein bischen zu vereinfachen, dass ich einen Seiteneffekt nicht gesehen habe:
Du triffst die Entscheidungen was als nächstes kommt in den if's, die sich jetzt gegenseitig nicht mehr ausschliessen.
Das klar aus dieser Ausgabe ablesbar
Code:
Ping: 71 cm
loop - rotiere_links - if-abfrage_2
loop - rotiere_rechts - if-abfrage_4
loop - alle_stepper_vorwärts - if-abfrage_5
Ping: 82 cm
das Programm springt ins zweite if, ändert die Variablen und eigentlich müßte hier jetzt die Fahrt ausgeführt werden, bevor es weiter zu den folgenden if's geht.
Oder die if's müssten prüfen ob vorangegangene if's ein neues Fahrkommando angewiesen haben, dass noch nicht ausgeführt wurde.
Im Beispiel muss im 4. if geprüft werden ob alle stepper.isDone() eben gegeben ist oder nicht.
Ich hatte ein andere Auswahlmethode im Hinterkopf, deswegen hatte das übersehen das diese Prüfung doch immer gemacht werden muss.
Wie lässt sich's ändern?
Zuerst einmal ein Wort zu den for(idx...)-Schleifen mit denen Du über die Stepper iterierst: In Anweisungen ist das praktisch, in logischen Aussagen wie
Code:
while ( ! (stepper[stepper_VL].isDone() && stepper[stepper_HL].isDone()
&& stepper[stepper_VR].isDone() && stepper[stepper_HR].isDone() ) )
leider nicht. Das wir diese Bedingung mehrfach brauchen lässt sich das in eine Funktion lesbarer zusammenfassen
Code:
boolean fahrt_fertig() {
return stepper[stepper_VL].isDone() && stepper[stepper_HL].isDone()
&& stepper[stepper_VR].isDone() && stepper[stepper_HR].isDone();
}
Ausserdem bietet es sich an, noch eine Funktion zu schreiben:
Code:
void fahrt_ausfuehren() {
while ( ! fahrt_fertig() )
{
for (idx = stepper_VL; idx < stepper_MAX; idx++)
{
stepper[idx].run();
// delay(1);
}
}
}
damit ändert sich Dein letztes loop-Beispiel so ab:
Code:
void loop()
{
hindernis_vorh();
/****************************************/
if(fahrt_fertig()) {
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();
}
}
/*************************************/
if (fahrt_fertig())
{
if (rueckwaerts == false && rotate_li == false)
{
Serial.println("loop - rotiere_links - if-abfrage_2");
rotieren_links();
}
}
if (fahrt_fertig())
{
if (rotate_li == true && vorwaerts == false)
{
Serial.println("loop - alle_stepper_vorwärts - if-abfrage_3");
alle_stepper_vorwaerts();
}
}
if (fahrt_fertig())
{
if (vorwaerts == true && rotate_re == false)
{
Serial.println("loop - rotiere_rechts - if-abfrage_4");
rotieren_rechts();
}
}
if (fahrt_fertig())
{
if (rotate_re == true && vorwaerts == true)
{
Serial.println("loop - alle_stepper_vorwärts - if-abfrage_5");
alle_stepper_vorwaerts();
}
}
/*****************************************/
fahrt_ausfuehren();
}
ich kann das gerade hier gerade leider nicht durchcompilieren doch ich hoffe das Schema ist klar.
Die Äusseren if(fahrt_fertig()) sorgen jetzt dafür das nur etwas geändert wird, wenn noch kein neues Fahrtkommando gesetzt wurde.
Natürlich könntest Du Deine if's auch so
Code:
if (fahrt_fertig() && vorwaerts == true && rotate_re == false)
{
Serial.println("loop - rotiere_rechts - if-abfrage_4");
rotieren_rechts();
}
schreiben, das ist Geschmackssache.
Dadurch das es jetzt "fahrt_ausfuehren()" gibt kannst Du die Stepper auch einfach an anderen Stellen ein vorgegebenen Kommando ausführen lassen. Damit lassen sich dann Sequenzen wie
Code:
alle_stepper_vorwaert();
fahrt_ausfuehren();
rotieren_rechts();
fahrt_ausfuehren();
usw...
schreiben.
Noch ein ganz anderer Gedanke.
In allen deinen Kommandofunktionen hast Du "setSPR()" "setRPM()" mit immer wieder den gleichen Werten drin. Du könntest _einmal_ das in die "setup()" Funktion schreiben und das sonst überall löschen. Dazu dann aber
Code:
void alle_stepper_stop()
{
stepper_stop = true;
for (idx = stepper_VL; idx < stepper_MAX; idx++)
{
stepper[idx].setDirection(STOP);
}
fahrt_ausfuehren();
}
abändern.
"setDirection(STOP)" hält die Stepper erst an, wenn "run()" einen internen Step ausführt (die CostumStepper-Lib implementiert das so).
Wenn Du die mehrfachen "setSPR", setRPM" dann löschen kannst, wird Dein Sketch kürzer und dadurch etwas übersichtlicher.
Gruss
Chris
Lesezeichen