Forum: Mikrocontroller und Digitale Elektronik Schrittmotorrampe für Konstante Beschleunigung


von Peter (Gast)


Angehängte Dateien:

Lesenswert?

Moin zusammen,

ich würde gerne einen Schrittmotor mit einer Konstanten Beschleunigung 
auf eine gewünschte Geschwindigkeit beschleunigen.
Da der zurückgelegte Weg aber leider nicht Linear zu Geschwindigkeit 
steigt, würde ich hierfür gerne für jeden Schritt das Delay neu 
berechnen.
Hier mal ein schneller Versuch.
Durch die Steps weiß ich, welchen Weg ich zurück gelegt habe. Da ich die 
Beschleunigung kenne, kann ich mir die Zeit ausrechnen, welche ich für 
die Strecke bei der konstanten Beschleunigung benötigt habe.
Über die Zeit kann ich mir dann die Geschwindigkeit ausrechnen, mit 
welcher sich der Schrittmotor drehen muss.
Prinzipiell funktioniert die Routine. Aber die ist sehr rechenintensiv 
(8289 Zyklen war ca. 518us entspricht).
Gibt es da eine schönere Lösung?
Die Beschleunigung und Geschwindigkeit will ich Variabel halten. Zwar 
jetzt nicht während einer Positionierung ändern, aber eventuell zwischen 
zwei Positionierungen.
1
volatile uint32_t   steps        =0;
2
volatile float     Frequenz      =0;    // Herz
3
volatile float     Geschwindigkeit    =40.0;  // mm/s
4
volatile float     Beschleunigung    =40.0;  // mm/s²
5
volatile float     Steps_pro_mm    =160;  // Schritte Pro Millimeter
6
7
int main(void)
8
{
9
  while(1)
10
  {
11
    Frequenz=sqrt((steps/Steps_pro_mm)/0.5/Beschleunigung)*Geschwindigkeit*Steps_pro_mm;
12
  }
13
}

von Michael B. (laberkopp)


Lesenswert?

Peter schrieb:
> Gibt es da eine schönere Lösung?

Vermutlich (hab ich mir nicht angeguckt)

https://www.embedded.com/generate-stepper-motor-speed-profiles-in-real-time/

: Bearbeitet durch User
von Johannes S. (Gast)


Lesenswert?

0.5 ist eine double Konstante und führt eventuell zu unnötig aufwändiger 
Berechnung.
Ein CM4 mit FPU rechnet das in 1-2 μs.

von Spess53 (Gast)


Lesenswert?

Hi

>Hier mal ein schneller Versuch.

AVR446: Linear speed control of stepper motor

MfG Spess

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Johannes S. schrieb:
> 0.5 ist eine double Konstante und führt eventuell zu unnötig aufwändiger
> Berechnung.
Alle Berechnungen werden mit float ausgeführt. Und das evtl. auf einem 
8-Bit-Rechner ohne FPU. Das geht niemals anders als 
laaaaannngssssaaaaammmm.

Peter schrieb:
> Gibt es da eine schönere Lösung?
"Schön" ist sie doch schon.
Nur halt nicht "schön schnell". Wenn man das will, dann gibt es 2 
Lösungen:
1. man rechnet die Sachen möglichst "binär" mit Integern in 
2er-Potenzen. Also auch nicht mit Integern im Dezimalsystem und schon 
überhaupt gar niemals nicht mit float
2. man nimmt einen µC, der das auch mit float schnell genug rechnen kann

: Bearbeitet durch Moderator
von Johannes S. (Gast)


Lesenswert?

Lothar M. schrieb:
> Alle Berechnungen werden mit float ausgeführt.

nö, durch die Konstante 0.5 wird mit double gerechnet. Auf einem 
Cortex-M0 macht das zu '0.5f' einen Unterschied von 4984 Byte (!, mit 
gcc).
Um welche Architektur es geht hat der TO ja nicht verraten. Das der 
avr-gcc die double auch als float behandelt ist mir bekannt, beim 
portieren auf andere Architekturen sieht man aber welche Auswirkung die 
Schluderei mit den Datentypen hat.
Und ich bin froh das die CM4/CM7 schon erfunden wurden und es die auch 
für kleines Geld gibt.

von Thorsten O. (Firma: mechapro GmbH) (ostermann) Benutzerseite


Angehängte Dateien:

Lesenswert?

Das geht sehr elegant über eine vorberechnete Tabelle, die dann zur 
Laufzeit nur noch skaliert werden muss. In der AN von Silicon Labs von 
2004 ist das beschrieben. Auf der Basis habe ich das um 2006 auf einem 
8-bit AVR für 2+2 Achsen umgesetzt.

Ansonsten schau doch mal in die gbrl-Sourcen, wie das dort gelöst wurde.

Mit freundlichen Grüßen
Thorsten Ostermann

: Bearbeitet durch User
von Georg (Gast)


Lesenswert?

Peter schrieb:
> Da der zurückgelegte Weg aber leider nicht Linear zu Geschwindigkeit
> steigt

Aber die Geschwindigkeit steigt linear mit der Zeit - ich gebe daher 
alle x msec einen neuen Geschwindigkeitswert vor, da ist so gut wie 
nichts zu rechnen (nur Addition).

Beschleunigen ist trivial, wenn auf der gewünschten Strecke überhaupt 
die Endgeschwindigkeit erreicht werden kann, muss man prüfen, zum 
Bremsen muss man vorher ausrechnen wann man damit beginnen muss, aber 
beides nur einmal.

Georg

von Peter (Gast)


Lesenswert?

Johannes S. schrieb:
> Um welche Architektur es geht hat der TO ja nicht verraten

Es handelt sich um einen Atmega328p 16 MHz.

Lothar M. schrieb:
> man rechnet die Sachen möglichst "binär" mit Integern in 2er-Potenzen.

Mit 2er Potenzen kann ich da ja nicht wirklich viel rechnen ausser das 
ich statt durch 2 einfach nach links Shifte.

Spess53 schrieb:
> AVR446: Linear speed control of stepper motor

Das hab ich auch noch auf dem plan da mal komplett durch zu steigen. Hab 
auch mal paar sachen davon angeschaut.

Georg schrieb:
> Aber die Geschwindigkeit steigt linear mit der Zeit - ich gebe daher
> alle x msec einen neuen Geschwindigkeitswert vor, da ist so gut wie
> nichts zu rechnen (nur Addition).

Das hat ich auch schon auf dem Plan. Dachte aber dann, das ich durch die 
Berechnung von jedem Schritt mir den zweiten Timer sparen könnte.
Geplant ist auch sowieso die Gesamte Strecke vorher zu berechnen.
Da könnte man sich Natürlich auch eine Array berechnen.

von NichtWichtig (Gast)


Lesenswert?

Thorsten O. schrieb:
> Das geht sehr elegant über eine vorberechnete Tabelle, die dann zur
> Laufzeit nur noch skaliert werden muss. In der AN von Silicon Labs von
> 2004 ist das beschrieben. Auf der Basis habe ich das um 2006 auf einem
> 8-bit AVR für 2+2 Achsen umgesetzt.
>
> Ansonsten schau doch mal in die gbrl-Sourcen, wie das dort gelöst wurde.
>
> Mit freundlichen Grüßen
> Thorsten Ostermann

Jupp, sowas habe ich damals mit einem 8052 in Assembler realisiert.
Die Rampe wurde wie mit dem Lineal gezogen bis zur Zielgeschwindigkeit 
abgefahren.

Der Trick dabei ist dabei das Gemisch aus aktueller Frequenz und das 
ermitteln des nächsten Timer Interrupt.
In der langsamen Hälfte braucht es mehr als einen TimerInterrupt bevor 
der nächste Step erfogt und in der oberen Hälfte nur noch einen wobei 
sich dort die zeiten dann verkürzen.

Je nach Motor, Last und Drehzahl müssen auch die Übergänge 
Rampe/Zieldrehzahl "abgerundet" werden weil ein "Knick" den Motor 
verwirren kann.

Anbei eine Messung der Rampe: 
Beitrag "Re: Rampe Atmega32"

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Peter schrieb:
> Lothar M. schrieb:
>> man rechnet die Sachen möglichst "binär" mit Integern in 2er-Potenzen.
> Mit 2er Potenzen kann ich da ja nicht wirklich viel rechnen ausser das
> ich statt durch 2 einfach nach links Shifte.
Wenn du ein wenig mehr drüber nachdenkst, dann schon. Nämlich immer an 
den Stellen, wo du jetzt mit irgendwelchen 10er Potenzen herumhantierst.

> Mit 2er Potenzen kann ich da ja nicht wirklich viel rechnen ausser das
> ich statt durch 2 einfach nach links Shifte.
Oder mit 2 multiplizierst. Oder mit 16er Faktoren rechnest. Oder mit 128 
als Faktor. Allemal besser als mit 10ern und 100ern herumzuskalieren...

von A. S. (Gast)


Lesenswert?

Peter schrieb:
> Mit 2er Potenzen kann ich da ja nicht wirklich viel rechnen ausser das
> ich statt durch 2 einfach nach links Shifte

Da Stichwort ist fixed-point.

Wenn die Geschwindigkeit z.b. nur 0...100 mit einer Nachkommastelle ist, 
dann gibt sie halt in 16tel oder 32tel an.

von Thorsten O. (Firma: mechapro GmbH) (ostermann) Benutzerseite


Lesenswert?

Hallo Georg,

Georg schrieb:
> Peter schrieb:
>> Da der zurückgelegte Weg aber leider nicht Linear zu Geschwindigkeit
>> steigt
>
> Aber die Geschwindigkeit steigt linear mit der Zeit - ich gebe daher
> alle x msec einen neuen Geschwindigkeitswert vor, da ist so gut wie
> nichts zu rechnen (nur Addition).

Im Prinzip ja. Wenn die Änderung der Geschwindigkeit asynchron zur 
Schrittausgabe erfolgt muss man allerdings aufpassen, dass keine 
"Zwischenschritte" mit ungewollt hohen oder niedrigen Freqenzen erzeugt 
werden. Sonst kommt der Motor schnell aus dem Tritt.

Eine kontinuierliche Anpassung der Geschwindigkeit von Schritt zu 
Schritt gibt übrigens einen sehr ruhigen, ruckarmen Lauf des Motors. 
Außerdem ist eine Schritt genaue Synchronisation mehrerer Achsen so 
einfacher.

Mit freundlichen Grüßen
Thorsten Ostermann

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.