Irgendwie 'verarscht' ihr die AccelStepper auch mit dem ständigen move(1)
- so kann die nicht vernünftig arbeiten.
Man muss vielleicht erstmal ein bisschen die Intuition hinter AccelStepper bzw. Steppern allgemein verstehen.
Schrittmotore sind primär nicht einfach zum Drehen da, sondern zum Positionieren. Z.B. einen Schlitten per Spindel hin- und herbewegen und zu bestimmten Positionen fahren. Typischen Anwendungsbeispiel sind auch die 3D-Drucker, wo die Düse kontrolliert bewegt und positioniert werden muss.
Daran sind auch die wesentlichen Funktionen der AccelStepper ausgerichtet: Ich gebe ( mit 'moveTo(x)' ) eine Zielposition vor und AccelStepper rechnet anhand der momentanen Position und des Referenzpunktes ( das ist 'Position 0' ) aus, wieviele Steps es bis dahin sind. Mit Hilfe der run() Anweisung fährt der Stepper dann in die entsprechende Position in dem die erforderlichen Stepimpulse ausgegeben werden ( aber immer nur maximal einer pro run()-Aufruf ). Ein weiterer Parameter ist dann noch, wie schnell diese Pulse ausgegeben werden. Das hängt von 'maxSpeed' und der Acceleration ab. Der Aufruf von run() muss auf jeden Fall häufiger erfolgen, als es der maximalen Steprate entspricht. Ist beim Aufruf von run() die Zeit für den nächsten Stepimpuls noch nicht erreicht, macht es einfach nichts. Wird run() zu selten aufgerufen, stimmen Beschleunigung und max. Geschwindigkeit nicht. Der Zielpunkt wird aber trotzdem erreicht ( solange run() überhaut aufgerufen wird ).
Auch der 'move(x)' Befehl ist al Poaitionieranweisung ausgelegt, nur das als Referenz für die Zielposition nicht der Referenzpunkt ( Position 0) verwendet wird, sondern die aktuelle Position. D.h. erst wird die absolute Zielposition berechnet, indem zur aktuellen Position die in der move(x)-Anweisung angegebenen Steps addiert werden, und dann wird wieder genauso verfahren, wie bei der absoluten Positionierung ( mit 'moveTo(x) ). Solange sich also an der aktuellen Position nichts ändert, kann ich eine move(x) Anweisung sooft aufrufen wie ich will, das Ergebnis ( die absolute Zielposition) ist immer dieselbe.
Damit Beschleunigung und Bremsen korrekt berechnet werden kann, muss die Lib den gesamten Weg zum Zielpunkt kennen. Wenn man nun als neuen Zielpunkt immer nur die nächste Stepposition angibt, und - sobald die erreicht wird - den Zielpunkt wieder eins weiterschiebt, kann die AccelStepper nicht wirklich funktionieren. Es wird immer der entsprechen maxSpeed und Acceleration berechnete längste Anfangsschritt ausgeführt, aber weder gibt es eine Beschleunigung, noch wird jemals maxSpeed erreicht.
Vielleicht noch ein Wort zu runSpeed, weil das auch angesprochen wurde und oftmals falsch eingesetzt wird.
runSpeed() und setSpeed(speed) sind zunächst mal Unterfunktionen von run(), die verwendet werden, um die entsprechend der Beschleunigung/Bremsen aktuell berechnete Geschwindigkeit vorzugeben, und dementsprechend einen Schritt auszuführen.
Man kann diese Funktionen auch dazu verwenden, den Motor mit konstanter Geschwindigkeit drehen zu lassen. Eine Zielposition wird dabei aber nicht beachtet ( der interne Positionszähler wird aber aktualisiert - die Lib weis also schon noch, wo der Motor gerade ist ).
Eine gemischte Verwendung der 'normalen' Positionsfunktionen ( set Acceleration, move, moveTo, run ... ) mit setSpeed und runSpeed führt aber zu unvorhergesehenen Ergebnissen, da die Positionsfunktionen diese eben auch aufrufen und die entsprechenden internen Werte (z.B. die 'speed' ) verändern.
Puhh - das war jetzt viel Text, und wahrscheinlich habe ich jetzt sämtliche Klarheiten beseitigt ....
P.S. Um die Abläufe zu visualisieren, habe ich das auch mal in einem Logikanalysator aufgenommen. Da sieht man genau wann was aufgerufen wird, das kann ich nachher auch nochmal posten ( wenn von Interesse ).