Einfacher ist es natürlich ohne for Schleife. Wofür hat man denn loop().
Die zwei delayMicroseconds(800);
stellen allerdings kein Problem dar. Etwas schnelleres als einen Stepper-Schritt sehe ich nicht.
Der Loop allein begrenzt nicht auf die, im Startpost Beispielhaften, 180 Schritte.
Natürlich kann man das auf If und Counter umbauen. Auch wenn man es selber schreibt, ganz anders aufsetzen.
Um das bestehende „einfach“ zu ändern, reicht ein hinzufügen der Abfrage des Tasters in die For-Schleife.
Und wie von anderen schon erwähnt, wenn Interrupt, dann lieber den Motor darüber steuern, und nicht den Taster.
Richtig. Genauso wie man delay()
nicht durch millis()
ersetzt, ist das Wesentliche, nach Weglassen der for-Schleife, die Zustandsvariable in der die Schrittzahl von einem loop-Durchlauf zum nächsten gemerkt und hochgezählt wird.
Die Grundstruktur von loop() ist nach der Änderung eine völlig andere, das stimmt. Aber nach der Änderung ist sie einfacher, meiner Meinung nach.
So macht jeder Versuch, der zu komplizierten Struktur noch etwas hinzuzufügen, alles nur noch schlimmer.
Ist halt die Frage, wie weit man abstrahieren will.
Wenn man weiß, dass im Hintergrund kein Betriebssystem werkelt, das mehrere Tasks parallel abhandelt, macht man es sich am einfachsten, wenn man die loop() so schreibt, wie sie auch am besten abläuft:
Als Definition, was in einem Augenblick gemacht werden soll. Und das halt für jeden Augenblick.
Ob "ein Augenblick" dann weniger oder mehr als eine Millisekunde dauert, ist nebensächlich. Wenn innerhalb eines loop()-Durchlaufs mehrfach nach einem Tasterzustand gefragt werden muss, ist es allerdings unnötig kompliziert.
Tendenziell halte ich es für völlig ok eine Schleife zu schreiben, wenn man eine Schleife braucht.
Klar, wenn man gleichzeitig mehrere Objekte gleich behandeln will, und diese in iterativer Form zur Verfügung stehen, ist eine Schleife ideal.
Konsequent (?) zu Ende gedacht:
Im verfügbaren Umfang in der Arduino-Umgebung gehört (u.a.) loop()
abgeschafft, stattdessen sollte der geneigte Nutzer nur task
s mit run()
-Methoden erstellen. Im Hintergrund läuft ein Minimal-Scheduler (loop - die runs aufrufend), die wait
-Implementierung würde dann die Hantierei mit millis()
kapseln.
Dann würden wir in der Tat nie wieder über delay()
und Nebenläufigkeiten diskutieren müssen :).
Das wäre aber nicht mehr "Arduino", sondern ein layer obendrüber (oder alternativ) Und wir würden uns über andere Nickeligkeiten unterhalten, was man nicht machen darf, weil sonst das Multitasking durcheinander kommt.
Sehe ich anders
loop beschreibt in meiner Philosophie einen Augenblick, also ist alles was in einem loop Durchlauf passiert, für mich so gut wie gleichzeitig.
Man kann natürlich im Extremfall mal ausnutzen, dass C++ definiert, welche Anweisungen in welcher Reihenfolge ausgeführt werden, und dass bei einem Arduino mit 1 Kern mehrere Nanosekunden zwischen zwei Maschinenbefehlen vergehen, aber hier geht es ja um "einfach" und Zeiten in der Größenordnung, die ein Stepper für einen Schritt braucht.
Ich kann durchaus verstehen, dass jeder, der Software schreibt, aufgrund persönlicher Erfahrungen eine Art "Best Practice" entwickelt, die für sie/ihn mit dem geringsten Risiko zum Erfolg führt.
Im Gegensatz dazu gibt es natürlich auch regelwidrige oder höchst unpraktikable Anwendungen.
Leider wird z.T. zwischen beidem nicht oder mindestens zu wenig differenziert:
- Nicht alles, was man selbst vermeidet, ist zwangsläufig unsinnig oder fehlerhaft.
- Nicht alles, was in vielen Fällen hilft, trifft auf alle anderen Fälle auch zu.
- Nicht alles, was unter bestimmten Umständen Probleme bereitet, ist grundsätzlich unbenutzbar.
Wie bei vielem im Leben, kommt es häufig darauf an, welche Randbedingungen vorliegen.
So liest man häufig, dass millis() in einem Interrupt zu Problemen führen und in keinem Fall zu verwenden sind. Das trifft m.E. so nicht zu. Um einmal bei diesem Beispiel zu bleiben, halte ich folgende Aussagen für korrekt:
- millis() werden während eines Interrupts nicht hochgezählt.
- Interrupt-Routinen sollten möglichst (zeitlich) nur kurz den Prozessor belasten, wenn man andere Interrupt-getriebene Funktionen nicht beeinflussen will bzw. darf.
- Hardware-getriggerte Interrupts können einen Prozessor unter ungünstigen Umständen komplett oder nahezu komplett auslasten und damit die übrigen Funktionen beeinträchtigen und bis zum Erliegen bringen.
Alle [ergänzt: diesbezüglichen] generellen Aussagen "Das darf man auf keinen Fall tun", dienen in der Regel dem Vermeiden solcher Zustände.
Soweit (außer persönlichem Frust über eine nicht funktionierende Anwendung) kein besonderer Schaden daraus erwächst, darf m.E. jeder gerne die Erfahrung machen, was ein prellender Taster so alles mit sich bringen kann ... Das lehrt häufig mehr, als das unreflektierte Kopieren vorgekauter Funktionen.
Es spricht - um recht verstanden zu werden - nichts dagegen, die möglichen Risiken eines Vorgehens aufzuzeigen; das geht aber auch mit Information und braucht nicht immer eine belehrende Intonation. Letzteres halte ich dort für gerechtfertigt, wo Leib und Leben gefährdet sind (z.B. das Schalten von Netzspannung, Augensicherheit bei Laseranwendungen, Brandgefahren durch Kurzschlüsse).
Wie man eben auf Neudeutsch sagt: "it depends" ...
Was z.B. "in Echtzeit" bedeutet, hängt in der Regel von der Anwendung ab. Manches braucht "echt Zeit" und darf das auch, anderes muss ein wenig schneller sein, damit andere Funktionen (z.B. eine erwartete Rückkoppelung) "zeitgerecht" an-/drankommen ...
Hi Peeps.
Can you all stay closer to the actual topic.
Thanks.
Bob.
This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.