Hallo Zusammen,
Ziel ist es einen Stepper mit beliebigen Profilen Schrittgenau
positionieren zu können. Dabei sollen sowohl die Profilparameter
(Vstart, Vstopp, Vmax, Beschleunigungen) als auch die Zielposition
jederzeit während der Laufzeit änderbar sein. (z.B. im
Joystick-Betrieb).
Idealerweise kann man auch noch einen Verschliff der Rampen einstellen
(S-Kurven / "Jerkfree").
Meine Hoffnung ist, dass es für diese Fragestellungen bereits
Open-Source Software gibt? An sich dürfte das in Zeiten der ganzen
3D-Drucker ja ein ziemliches 08/15 Problem sein.
Vielen Dank!
Für Arduino gibt es die "AccelStepper" lib. Das Zeug steckt im Grunde
auch in den Druckerfirmwares und GRBL drin.
http://www.airspayce.com/mikem/arduino/AccelStepper/
Das kann so vermutlich alles was du willst.
lion schrieb:> jederzeit während der Laufzeit änderbar sein. (z.B. im> Joystick-Betrieb).lion schrieb:> 3D-Drucker ja ein ziemliches 08/15 Problem sein
Weder 08/15 noch trivial. Es gibt Firmwares (mir fällt gerade nur die
von TinyG ein) die Jerk-free implementiert haben. Da reicht aber ein
Atmega für ausreichende Schrittraten nicht mehr aus.
Während der Laufzeit das dann noch zu ändern ist noch weniger trivial.
3D-Drucker bekommen GCode der nacheinander abgearbeitet wird. Dadurch
kann man Lookahead und Rampen genau (bzw. genau genug) bestimmen.
Am ehesten (aber ohne echtes Jerk-free) würde ich mich mit der
ACCELERATION_REPRAP in der Teacup-Firmware in dem von dir genannten
Bereich mit auseinander setzen. Bei anderen Firmwares kenne ich mich
nicht genügend aus, wie das dort umgesetzt wird, bzw. bei
Marlin-Firmware wüsste ich jetzt auch nicht, wie man den Joystick
implementieren sollte/könnte.
Die Mathematik dazu ist einfach. Die Umsetzung in die Schrittsteuerung
nicht.
lion schrieb:> Idealerweise kann man auch noch einen Verschliff der Rampen einstellen> (S-Kurven / "Jerkfree").
Es gibt auch ein deutsches Wort dafür, nämlich:
ruckfrei oder ruckelfrei. Versteht jeder.
Muss das sein ?
Marc V. schrieb:> ruckfrei oder ruckelfrei. Versteht jeder.
Mein ausländischer Kumpel versteht nur Jerkfree. Hier von jeder zu
sprechen...
Muss das sein?
Glaub ich nicht. schrieb:> Mein ausländischer Kumpel versteht nur Jerkfree. Hier von jeder zu> sprechen...
Dann benutze es in seinem Forum, meinetwegen in Indonesien.
Das hier ist aber ein deutsches Forum.
Ob stepper motor oder Schrittmotor ist egal, so etwas versteht jeder,
aber "Jerkfrei" und noch dazu mit "J" ist einfach zu viel.
Ausländer schrieb:> Die deutsche Sprache reicht nicht aus um komplexe Sachen in> naturwissenschaftlichen Bereichen zu beschreiben
An dem Punkt (evtl vorher schon) sind alle anderen Sprachen ebenfalls am
Ende und man verwendet die Sprache der Mathematik um Sachverhalte zu
beschreiben die man nicht mehr in Worte fassen kann.
Aber das Wort "Ruck" steht meines Wissens nach schon lange im Duden und
gehört auch zum alltäglichen Sprachschatz von jedermann, so komplex kann
das nicht sein.
Und wenn dann einer das erste mal im Source Code, tschuldige im
Quellcode, ähm Quelltext, nachguckt, findet er nix von Ruck sondern von
Jerk.
Muss man jetzt hier überall alles auf Deutsch beschreiben?
Nico W. schrieb:> Und wenn dann einer das erste mal im Source Code, tschuldige im> Quellcode, ähm Quelltext, nachguckt, findet er nix von Ruck sondern von> Jerk.
Nein, man findet "jerk" - die Sache mit Grossbuchstaben ist deutsche
Erfindung.
Und "jerk free" kann auch etwas ganz anderes bedeuten, z.B.:
"Von Idioten befreit", oder noch kürzer: "Idiotenfrei".
> Muss man jetzt hier überall alles auf Deutsch beschreiben?
Nein, aber "ruckfrei" beschreibt weitaus besser was gemeint ist als
"jerk free".
Hallo zusammen,
danke für eure Antworten.
Abgesehen von der sprachlichen Diskussion bin ich wirklich einigermaßen
überrascht, dass es hier noch keine Standardlösung gibt (eben wegen der
Verbreitung die Schrittmotoren aktuell erfahren).
Die Mathematik ist mir bewusst, dementsprechend auch, dass ich das
unmöglich in die Schrittgenerierung im kHz Bereich selbst mit einbauen
kann.
Was ich mir durchaus vorstellen kann ist die Schrittfrequenzen
niederfrequent (z.B. in 100 Hz) und mit niedriger Priorität basierend
auf aktueller Position und Geschwindigkeit zu ermitteln.
Was mir hier etwas Sorgen bereitet ist jedoch die Unschärfe der
aktuellen Position, da die Schrittgenerierung ja weiter läuft, während
der mutmaßlich langsame Algorithmus noch fröhlich vor sich hin rechnet.
Habt ihr Ideen wie man eine saubere Synchronisation von der
Echtzeit-Schrittgenerierung zu der langsameren
Geschwindigkeitsberechnung hinbekommen könnte?
Viele Grüße!
Du musst dir halt überlegen wie die Schritterzeugung auf deinen Joystick
reagieren soll. Z.B. könnte man sich ja vorstellen, dass der Motor beim
plötzlichen loslassen:
a) plötzlich stehen bleibt
b) mit einer Rampe (meinetwegen auch ruckfrei) zum stehen kommt.
Das sind alles Sachen die man sich halt selbst erarbeiten muss.
Das du nur mit 100Hz deine Schritte berechnen willst ist ja auch nicht
richtig. Wann soll denn deine Schrittlänge bei einer
Beschleunigungsphase ändern? Perfekt wäre es ja das bei jedem Schritt
die exakte Länge berechnet wird. Das kostet Zeit. Das ist das was teuer
ist. Hier gibt es auch unterschiedlichste Ansätze.
Einer berechnet alle 2ms die Taktfrequenz und lässt die Motoren
dazwischen einfach mit der gleichen Frequenz laufen. Der andere
berechnet mit nem Lookuptable bei jedem Schritt die neue Taktfrequenz.
lion schrieb:> Was mir hier etwas Sorgen bereitet ist jedoch die Unschärfe der> aktuellen Position, da die Schrittgenerierung ja weiter läuft, während> der mutmaßlich langsame Algorithmus noch fröhlich vor sich hin rechnet.
Schritt (oder step ?) bleibt immer Schritt.
Der Weg welcher dabei zurückgelegt wird, auch.
Bleiben also nur Schritte pro Zeiteinheit und wenn man nicht rechnen
will, legt man sich eine Tabelle an.
Joystick position ist dann ganz einfach ein Zeiger in diese Tabelle
(Endposition) z.B. JoyPtr.
Aktueller Zeiger (momentane Position) ist AktPtr.
Wenn die beiden gleich sind, braucht man ganz einfach nichts machen.
Falls nicht, wird die Tabelle von AktPtr bis JoyPtr Schritt für
Schritt abgefahren.
Dabei kann sich Joystick position jederzeit ändern - es wird ganz
einfach mit der AktPos nachgefahren.
Marc V. schrieb:> Joystick position ist dann ganz einfach ein Zeiger in diese Tabelle> (Endposition) z.B. JoyPtr.
Und hier erkennt man, dass viele Leute anders denken wie man etwas
umsetzen könnte. Der eine will die Position vom Joystick umsetzen. Der
andere sieht die Position vom Joystick eher als Geschwindigkeit und
Richtung. Gibt also sehr viele Wege dahin :)
Nico W. schrieb:> umsetzen könnte. Der eine will die Position vom Joystick umsetzen. Der> andere sieht die Position vom Joystick eher als Geschwindigkeit und> Richtung. Gibt also sehr viele Wege dahin :)
Tja, stimmt schon, nur interessiert Links und Rechts in diesem
Zusammenhang nicht, zumindest habe ich es so verstanden.
Wie man einen bestimmten Punkt anfährt, ist natürlich eine ganz
andere Sache.
Hallo Zusammen,
danke für eure Antworten.
Das mit denn 100 Hz für die Rampenberechnung wären ca. 10 ms die der
Motor mit der gleichen Frequenz bewegt würde, bevor er eine neue
Zielfrequenz bekommen würde. Das könnte in erster Näherung ausreichend
sein. Müsste man durch Versuche ggf. optimieren.
Also im Endeffekt wenn ich zwei Tasks hätte (ein Task Frequenz + ein IRQ
für die Schrittgenerierung). Der Task "Schritt" erzeugt zum einen den
Schritt selbst, zum anderen ändert er den Reload Wert des Timers wie
durch den "Frequenz" Task vorgegeben. Der Frequenz Task holt sich die
aktuelle Position des Steppers (Frequenz + Rampenparameter kennt er ja
ohnehin) und berechnet daraufhin die neue Zielfrequenz. Der Schritt Task
stoppt dann Schritte zu erzeugen, wenn er bei der Zielposition
(Ziel-Zahl-Schritte) ist.
Task Schritt: . . . . . . . . . .......... . . . . . . . . .
Task Frequenz: . . . .
Das mit der LookUpTable (LUT) verstehe ich weder beim Beschleunigen und
noch weniger beim Bremsen :) auch wenn das durchaus eine interessante
Lösung sein könnte.
Sagen wir einfach mal der Motor bewegt sich aktuell mit 500 Hz (16/tel
Schritt, also gar nicht mal so schnell). Wie kann ich eine LUT
generieren, welche für jeden Schritt einen neuen Frequenzwert
beinhaltet? Oder macht man hier für alle N Schritte einen neuen
Frequenzwert? Aber wann wird die LUT berechnet? Vor allem wenn sich
während der Bewegung die Bewegungsparmeter / Ziel ändert?
Beim Bremsen wird es aber noch komplizierter, wie kann ich ermitteln, ab
wann ich in die Brems LUT einsteigen muss um beim Zielpunkt X genau die
geüwnschte Frequenz zu haben?
Viele Grüße
lion schrieb:> Das mit der LookUpTable (LUT) verstehe ich weder beim Beschleunigen und> noch weniger beim Bremsen :) auch wenn das durchaus eine interessante> Lösung sein könnte.
Beispiel:
Angenommen, dein Joystick steht auf 1m/s, du bewegst den Knüppel
auf 2m/s.
In der Tabelle steht für 1m/s 100 Impulse pro 10ms, für 2m/s
stehen 200 Impulse. Dazwischen z.B. 20 Schritte.
Dass du nicht gleich auf 200 Impulse umschalten kannst ist klar.
Also, werden diese 20 Schritte abgefahren, AktPtr wird alle 10ms um
eins erhöht, mit JoyPtr verglichen und nach 200ms fährt dein stepper
mit 2m/s.
Danach ist Ruhe, es wird nur dieser eine Wert genommen, auf den AktPtr
zeigt.
lion schrieb:> ie Mathematik ist mir bewusst, dementsprechend auch, dass ich das> unmöglich in die Schrittgenerierung im kHz Bereich selbst mit einbauen> kann.
So?
Du solltest hier mal klar sagen, ob du das saubere Verfahren eines
einzelnen Schrittmotors anzielst oder ob du echte Bahnkurven mit 2, 3
oder mehreren Schrittmotoren vorhast. Das ist ein Riesen-Unterschied und
solange das nicht geklärt ist, kommt nur Mißverständnis auf.
Ich mache das so, daß vor Beginn einer Bewegung der Endpunkt (in
Schritten) errechnet wird und dann der Motor per chipinternem Timer mit
einer recht niedrigen Anfangsfrequenz gestartet wird. Pro Motortakt gibt
es einen Interrupt, wo die Taktfrequenz neu gesetzt wird und obendrein
der Weg gezählt wird. Das braucht man dann, um zum richtigen Zeitpunkt
mit dem Abrampen zu beginnen. Startfrequenz und Endfrequenz werden vor
dem Start der Bewegung festgelegt, die Auf- und Abramp-Funktion hingegen
in der Interrupt-Routine.
Normalerweise haben die üblichen SM-Treiber Schaltfrequenzen von 8 bis
höchstens 30 kHz bei ihren Schaltreglern. Schnellere Motottakte als
dieses sind also im Allgemeinen nicht sinnvoll. Also braucht der
verwendete µC auch nur Interrupt-frequenzen in diesem Rahmen zu
verkraften.
W.S.
lion schrieb:> Das mit denn 100 Hz für die Rampenberechnung wären ca. 10 ms die der> Motor mit der gleichen Frequenz bewegt würde, bevor er eine neue> Zielfrequenz bekommen würde. Das könnte in erster Näherung ausreichend> sein. Müsste man durch Versuche ggf. optimieren.
Sauberer wärs, nach jedem schritt die dauer des nächsten Intervalls
auszurechnen. Motoren beschleunigen dann auch mit großen Lasten sauber
und bleiben nicht (so leicht) unvermittelt stecken. Geräuschentwicklung
ist m.E. auch angenehmer, Ruckler gibts dabei natürlich auch nicht.
ARM Cortex sind schnell genug dafür. Braucht pro Schrittmotor einen
Timer mit einem PWM-Kanal. PWM setzt man fix auf z.B. 5 Takte 1, Rest 0
(nach Anforderungen des Schrittmotortreibers), und variiert die Periode,
bei Periodenende löst man Interrupt aus, in der ISR berechnet man das
nächste Schrittintervall (so man in einer Beschleunigungs/Bremsphase
ist). Sollte in Fixkomma mit ein paar Int Multiplikationen, ein paar
Additionen und evt. 1-2 Divisionen recht schnell sein. Ich hab auf einem
Cortex-M3 (120MHz) schon 3 Achsen mit >30kHz Schrittfrequenz auf die Art
gesteuert.
Hilfreich: Atmel AVR446 appnote, http://hwml.com/LeibRamp.pdf,
http://www.embedded.com/design/mcus-processors-and-socs/4006438/Generate-stepper-motor-speed-profiles-in-real-time
Das "optional enhancement" funktioniert ausgezeichnet.
Ausländer schrieb:> Die deutsche Sprache reicht nicht aus um komplexe Sachen in> naturwissenschaftlichen Bereichen zu beschreiben. Finde Dich damit ab.
Das halte ich für grandiosen Unfug.
Gruß,
Holm
W.S. schrieb:> Normalerweise haben die üblichen SM-Treiber Schaltfrequenzen von 8 bis> höchstens 30 kHz bei ihren Schaltreglern. Schnellere Motottakte als> dieses sind also im Allgemeinen nicht sinnvoll.
Das ist so schon nicht falsch. Aber neuere Treiber können durchaus
deutlich mehr verkraften. Ich arbeite aktuell mit TMC2130 die mit
1/256tel µ-Schritten bis zu 4MHz können.
Mein STM steuert die aktuell mit bis zu 500kHz und wenn ich mal Zeit für
finde, dann gibt es auch einen Port auf nen F446 und dann sollten die
mit 1MHz getaktet werden können. Mit Rampen, mit Lookahead, mit bis zu
4-Achsen (3D-Drucker).
rmu schrieb:> Hilfreich: Atmel AVR446 appnote, http://hwml.com/LeibRamp.pdf,> http://www.embedded.com/design/mcus-processors-and-socs/4006438/Generate-stepper-motor-speed-profiles-in-real-time
Den zweiten Link nutze ich für die Schrittgenerierung. Und das seit
gestern sogar ohne Bresenham.
Nico W. schrieb:> Und hier erkennt man, dass viele Leute anders denken wie man etwas> umsetzen könnte.Marc V. schrieb:> zumindest habe ich es so verstanden.
Jeder versteht es halt anders. Nicht mehr und nicht weniger wollte ich
damit sagen. Was nun richtig ist weiß wohl nur der TO.
Marc V. schrieb:> Beispiel:> Angenommen, dein Joystick steht auf 1m/s, du bewegst den Knüppel> auf 2m/s.> In der Tabelle steht für 1m/s 100 Impulse pro 10ms, für 2m/s> stehen 200 Impulse. Dazwischen z.B. 20 Schritte.> Dass du nicht gleich auf 200 Impulse umschalten kannst ist klar.> Also, werden diese 20 Schritte abgefahren, AktPtr wird alle 10ms um> eins erhöht, mit JoyPtr verglichen und nach 200ms fährt dein stepper> mit 2m/s.> Danach ist Ruhe, es wird nur dieser eine Wert genommen, auf den AktPtr> zeigt.
Das was du hier beschreibst ist auf jeden Fall nicht ruckfrei. Nur
wenn die Änderung der Beschleunigung endlich ist, ist auch der Ruck
endlich (da er ja genau die Änderung der Beschleunigung ist). Sogesehen
ist "ruckfrei" sowieso unmöglich, da der Ruck nie Null sein kann, so
lange die Beschleunigung nicht Null ist. Was Niko meint ist, dass die
Änderung der Beschleunigung endlich ist. Endlich ist sie (in der
Realität) sowieso immer, nur in der Software kann man halt andere Dinge
programmieren.
Wie Nico schon sagte ist das Problem alles andere als 08/15, vor allem
wenn sich der Zielwert ständig (in Echtzeit) ändern kann. Eine
3D-Drucker Firmware (oder sollte ich besser den deutschen Begriff
verwenden?), die etwas derartiges implementiert ist mir nicht bekannt.
Für eine Achse sollte sich das aber "relativ" einfach implementieren
lassen, vorrausgesetzt die Angestrebten Taktraten sind nicht zu hoch und
der verwendete Prozessor hat genügend Dampf. Richtig kompliziert wird es
erst wenn man mehrere Achsen synchronisieren will bzw. muss.
Ab hier OT wegen der Begrifflichkeiten:
Marc V. schrieb:> Ob stepper motor oder Schrittmotor ist egal, so etwas versteht jeder,> aber "Jerkfrei" und noch dazu mit "J" ist einfach zu viel.
Nico hatte nicht "Jerkfrei" sondern "Jerkfree" geschrieben.
Bernd K. schrieb:> Aber das Wort "Ruck" steht meines Wissens nach schon lange im Duden und> gehört auch zum alltäglichen Sprachschatz von jedermann, so komplex kann> das nicht sein.
Spätestens bei der Ableitung des Rucks steigt die deutsche Wikipedia
aus. Im englischen gibt es das Wort "jounce". Mir ist kein
entsprechender Begriff in der deutschen Sprache bekannt.
> Den zweiten Link nutze ich für die Schrittgenerierung. Und das seit> gestern sogar ohne Bresenham.
Hm, ich habe mir die Formel 12 mal in eine Tabellenkalkulation
übertragen.
Die Beschleunigung ist nachvollziehbar, aber nicht mehr "variabel".
Welcher Faktor drückt denn jetzt die Beschleunigung aus und in welcher
Einheit?
-Full 6 axis motion control - XYX linear axes and ABC rotary axes
-Step outputs available for 6 motors (motors are mappable to axes)
-Jerk controlled motion for acceleration planning (S curve 3rd order
motion planning)
-Extremely stable and jitter-free 200 kHz step generation
-RESTful interface using JSON over USB
-USB is native on the ARM chip and runs 12 Mbps or 480 Mbps
-Complete status and system state displays
-Advanced hardware abstraction layer for easy port to multiple ARM and
non-ARM processing environments
https://github.com/synthetos/g2/wiki/What-is-g2core
Wenn du also die Beschleunigung ändern willst, und z.B. der Einfachheit
halber am Anfang 'beschleunigung = 1' setzt, musst du c0 mit
1/wurzel(beschleunigung) ändern.
Juckbegrenzte Rampen (jerk limited) sind schon für Servoantriebe nicht
ganz ohne. Ein Kollege am Institut hatte das seinerzeit als Block für
Simulink implementiert, dass war für Antriebssimulationen sehr
hilfreich.
Bei Schrittmotoren kommt erschwerend hinzu, dass man nicht mit einem
konstanten zeitlichen Raster arbeiten kann, sondern mit konstanten
Wegabschnitten (Schritten) rechnen muss.
Es gibt eine schöne Application Note von Silicon Labs ("STEPPER MOTOR
REFERENCE DESIGN", App note 155), da ist ein einfaches Verfahren mit
einer vorberechneten Tabelle beschrieben. Das Paper hatte ich hier
schonmal in einem Betreitag verlinkt [1]. Das ist aber auch nur eine
Implementierung mit konstanter Beschleunigung. Ruckbegrenzung braucht
man bei Schrittmotoren aber meiner Meinung nach ohnehin nicht. Durch den
(Mikro)-Schritt als kleinste steuerbare Schrittweite kann man den
auftretenden Ruck nur bedingt beeinflussen. Größere Effekte erreicht man
da durch den Einsatz von feineren Mikroschritten.
Ich habe den Algoritmus aus der o.g. Application Note schon 2005 (also
lange vor Smoothstepper, grbl und co) auf mehrere Achsen erweitert und
auf einem Atmega128 realisiert. Timer0 (8-bit) ist der Systemtimer, von
dem auch die Rampen gesteuert werden, Timer1 und Timer3 (16-bit) werden
für die Schrittausgabe auf 2 Achsen verwendet. Für zwei weitere Achsen
war ein Coprozessor vorgesehen, aber da für die meisten Anwender 2
Achsen synchron ausreichend waren, haben wir das nicht mehr umgesetzt.
Mit der Lösung haben wir bis zu 50kHz auf 2 Achsen erreichen können,
wärend parallel ein Grafik-LCD angesteuert und per USB mit dem PC
kommuniziert wurde. Heute würde ich einen Cortex-M dafür nehmen mit
entsprechend vielen Timern, dann wären auch 4 Achsen und mehr synchron
kein Problem mehr.
Mit freundlichen Grüßen
Thorsten Ostermann
[1] Beitrag "Rampenberechnung Schrittmotor"
[2] http://www.mechapro.de/schrittmotorensteuerung.html
Thorsten O. schrieb:> Das Paper hatte ich hier> schonmal in einem Betreitag verlinkt [1]. Das ist aber auch nur eine> Implementierung mit konstanter Beschleunigung. Ruckbegrenzung braucht> man bei Schrittmotoren aber meiner Meinung nach ohnehin nicht.
Wenn man dann noch überlegt, dass man die Beschleunigung eh nicht jeden
Schritt neu berechnen muss, da die Physik mit der Trägheit da ja auch
mitspielt, kann man die Berechnung auch einfach alle 1 bis 2ms
durchführen.
Jetzt berechnet man:
Hi,
ich habe mal eben eine Tabelle aufgesetzt.
Kann das hinkommen?
Bei 200MHz Timerfrequenz gibt es nur 17 Beschleunigungsstufen zwischen 0
und Vmax?
Vmax mit 200kHz angesetzt (Grenzwert Hobby-Schrittmotor-Endstufen)
> Irgendwas hast du verkehrt gemacht.
Ich habe dann wohl die Beschleunigung umgerechnet in Schritte/s²
... dachte, wenn alles in Schritten ist, dann sollte es die
Beschleunigung auch sein.
> Ich bekomme bei 204MHz, 1000mm/s^2 und 1600steps/mm ein c_0 von 228.078> raus.
Yo, der Wert wäre mir auch viel sympathischer ;)
Irgendwie komme ich mit den Formeln noch nicht ganz klar.
Habe jetzt mal die Beschleunigung in mm/s² genommen.
OK, c0 ist 228.079 - die Verkürzung von cn sieht erstmal nicht schlecht
aus.
Allerdings passt die Rampe nicht.
Die Zeit einer Rampe ist doch Vmax / a
bei Vmax von 200.000 Schritten/s oder 0,125m/s bekomme ich eine
Rampenzeit von 0,125s
Umgerechnet in Schritte (s = 0,5 x a x t²) erhalte ich 12.500 Schritte.
Wenn ich in der Tabelle nachschaue, dann ist bei diesem Schritt die
Geschwindigkeit aber erst 135.000 Schritte/s
... woraus ich schließe, dass die Beschleunigung zu langsam gerechnet
wurde.
> P.S: Sorry, musste mich mal wieder mit Latex austoben :D
alles gut ;)
Ist nur schwer zu lesen, wenn man den Browser mit noscript betreibt ;)
> Wenn du dir das Paper[1] nochmal zur Hand nimmst und die Formel (15),> dann sollte das am Ende wieder passen.
Yeah! Danke! :D
Die Formel ist mir raus. Habe bei 12 aufgehört mit lesen :O