Hallo,
ich versuche mich seit längerem an der Beschleunigung von
Schrittmotoren. Dabei will ich ganz allgemein belieben so dass die
daraus entstehende Lib auf möglichst vielen Arduinos läuft. Heißt also
keine Timer etc. benutzen sondern wenn möglich alles in einer Schleife.
Das Ganze funktioniert ohne Beschleunigung soweit auch ganz gut. Nur
lässt sich die maximal Geschwindigkeit nicht erreichen weshalb ich nun
eben eine Rampe einbauen möchte. Die Stepper selbst hängen an einem
A4988 Treiber dem man nur noch den Steppimpuls geben muss.
Generelle funktionsweise:
Ohne Beschleundigung:
1.) Jeder Stepper bekommt eine run() methode die inn der Loop()
aufgerufen wird. Ich arbeite mit Wartezeiten zwischen den Schritten und
nicht mit einer Frequenz Wobei sich das leicht umrehcnen lassen dürfte.
2.) Jeder Stepper zählt die µSek. bis er wieder einen Schritt machen
darf
3.) Nach jedem Schritt wird die Zeit bis zum nächsten Schritt um einen
festen Wert (davor berechneten erhöht
4.) Code run():
1 | if (stepsToDo > 0 && currentMicros >= nextUpdate) {
|
2 | nextUpdate += stepDelay_uSec;
|
3 | digitalWriteFast(stepPin_, HIGH); //digtial write is very slow using variables. Using literals for pins is much faster!!! digitalWriteFast(stepPin_, LOW); //ggf über Bitmask arbeiten da schneller?
|
4 | digitalWriteFast(stepPin_, LOW); //delaymicros() pause between digitalWrite() seems not needed…
|
5 | stepsToDo--;
|
6 | }
|
Meine Idee mit Beschleunigung:
1.) Es bleibt alles gleich wie ohne Beschleunigung. Allerdings soll er
zuvor die Wartezeit zwischen den Schritten etwas höher ansetzen als die
Wartezeit für V_Max (="finalStepDelay_uSec") diese pro festen Tick (hier
alle 100µS) um einen bestimmten Wert kleiner werden lassen so dass die
Wartezeit linear kleiner wird bis sie V_Max erreicht hat.
2.) Code run():
1 | if (currentMicros >= nextAccTick) {
|
2 | if (stepDelay_uSec > finalStepDelay_uSec) {
|
3 | stepDelay_uSec -= 1; //decrement the stepDelay_uSec until the finalStepDelay_uSec (V_Max) is reached. finalStepDelay_uSec is for ex. 30µS
|
4 | }
|
5 | nextAccTick += AccTickTime; //here for ex. 100 uSec -> must be bigger then finalStepDelay_uSec!
|
6 | }
|
7 | if (stepsToDo > 0 && currentMicros >= nextUpdate) {
|
8 | nextUpdate += stepDelay_uSec;
|
9 | digitalWriteFast(stepPin_, HIGH); //digtial write is very slow using variables. Using literals for pins is much faster!!! digitalWriteFast(stepPin_, LOW); //ggf über Bitmask arbeiten da schneller?
|
10 | digitalWriteFast(stepPin_, LOW); //delaymicros() pause between digitalWrite() seems not needed…
|
11 | stepsToDo--;
|
12 | }
|
Eigentlich hatte ich erhofft dass diese einfache Beschleunigung
problemlos für die meisten Fälle funktionieren wird.
Leider ist dem nicht so und es ist oft der Fall, dass der Stepper sobald
er eine hohe Geschwindigkeit erreicht einfach aus dem Takt kommt und
vibrierend stehen bleibt. Ein Erhöhen der AccTickTime hat manchmal etwas
gebracht und ich konnte eine noch höhere Geschwindigkeit erreichen, war
aber fummelig und musste jedes Mal durch ausprobieren ermittelt werden
was eben nicht sein sollte. Die Max. Geschwindigkeit war also definitiv
noch nicht erreicht.
Weiß jemand was an dieser einfachen linearen Rampe falsch ist? Oder
kennt jemand eine super einfache Rampe die ohne Timer etc. auskommt und
mit einfachen Schleifen realisiert werden kann?
Es soll so einfach und kompatibel wie möglich sein ohne dass man davor
irgendwelche Timer am Arduino einstellen muss. Auch sollte die
Berechnung nicht während der Beschleunigung durchgeführt werden um die
Lib auf schwächeren µC (16MHz, keine FPU etc.) laufen lassen zu können.
Es soll außerdem eine andere Lib sein wie die schon existierenden. Die
habe ich mittlerweile auch soweit erstellt nur dass noch die
Beschleunigung fehlt.
Also keine AccelStepper Lib Lösungen etc.