Tutorial · Mittelstufe · 40 Min.
Bewegungsprofile: Trapez- und S-Kurven-Beschleunigung
Warum ein Positionsbefehl Motoren springen und Maschinen schlagen lässt, wie ein Trapezprofil das behebt und was eine ruckbegrenzte S-Kurve an Zeit kostet.
Einführung
Einen Motor auf eine Position zu befehlen und er versucht, sofort dorthin zu kommen. Nicht schnell – sofort. Der Befehl enthält keine Information über Tempo – die einzige verfügbare Deutung lautet also „so schnell wie möglich“: und was danach geschieht, entscheidet, was zuerst ausgeht: Drehmoment, Stromgrenze, Traktion oder die Fähigkeit des Schrittmotors mitzuhalten.
Ein Bewegungsprofil ist die fehlende Information. Es verwandelt „fahr auf 100 mm“ in einen Fahrplan – wo die Achse zu jedem Augenblick zwischen jetzt und Ankunft sein soll –, und übergibt dem Regler ein Ziel, das sich mit Tempo bewegt, das die Maschine wirklich liefern kann.
Das ist der Unterschied zwischen einem Roboterarm, der ankommt, und einem, der ankommt und aufhört zu wackeln.
Was ein nackter Positionsbefehl wirklich verlangt
Einen Sprung betrachten: Bei t = 0 springt das Ziel von 0 mm auf 100 mm.
Um dem exakt zu folgen, bräuchte die Achse unendliche Geschwindigkeit, was unendliche Beschleunigung erfordert, was unendliche Kraft erfordert. Kann sie nicht – also gibt etwas nach:
- Ein Schrittmotor wird mit Schrittrate befohlen, die sein Drehmoment bei dieser Drehzahl nicht erzeugen kann, verliert Schritte – und merkt es ungeregelt nicht. Position ist nun dauerhaft falsch. Warum das geschieht, und warum es immer vier Schritte auf einmal sind.
- Ein DC-Motor mit PID-Schleife sieht einen riesigen Momentanfehler, sättigt seinen Ausgang, wickelt seinen Integralanteil auf und schwingt über.
- Ein Servo knallt auf seine Maximalrate und kommt mit noch bewegtem Gesamtmechanismus an.
Keines davon sind Abstimmungsprobleme. Alle sind dasselbe Problem: Der Befehl war physisch unmöglich.
Das Trapezprofil
Die Lösung: Geschwindigkeit befehlen, und Geschwindigkeit mit Rate ändern, die der Motor durchhält. Mit konstanter Rate auf Marschtempo beschleunigen, halten, dann mit derselben Rate bremsen. Geschwindigkeit gegen Zeit geplottet ist ein Trapez – woher der Name kommt.
Drei Zahlen definieren es: die Strecke d, ein Toptempo v_max und eine Beschleunigung a.
t_accel = v_max / a time spent ramping
d_accel = v_max² / (2a) distance used by one ramp
t_total = v_max / a + d / v_max whole move, if it reaches v_max
Für 100 mm Fahrt bei 100 mm/s mit a = 500 mm/s²: Jede Rampe dauert 0,2 s und deckt 10 mm ab, 80 mm Marsch bleiben übrig – gesamt 1,2 s.
Hier das Ganze als Zeitfunktion – die Position, der deine Regelschleife zum Augenblick t folgen sollte:
// Target position t seconds into a trapezoidal move of `d` mm.
float profilePosition(float t, float d, float vMax, float a) {
float tAcc = vMax / a;
float dAcc = vMax * vMax / (2 * a);
if (2 * dAcc > d) { // too short to reach vMax
float tPeak = sqrtf(d / a); // triangular profile
if (t >= 2 * tPeak) return d;
if (t < tPeak) return 0.5f * a * t * t;
float left = 2 * tPeak - t;
return d - 0.5f * a * left * left;
}
float tCruise = (d - 2 * dAcc) / vMax;
float tTotal = 2 * tAcc + tCruise;
if (t >= tTotal) return d;
if (t < tAcc) return 0.5f * a * t * t;
if (t < tAcc + tCruise) return dAcc + vMax * (t - tAcc);
float left = tTotal - t;
return d - 0.5f * a * left * left;
}
Beachte, was diese Funktion nicht ist: kein Regler. Sie erzeugt einen Sollwert. Was du hattest – Schrittmotor-Schrittplaner, PID-Schleife, Servoschreiben – folgt weiter. Das Profil ändert nur, wem gefolgt wird.
Die verlangte Bewegung ist nicht immer die bekommene
Dieser 2 * dAcc > d-Ast ist der Fall, den Leute zuerst treffen und fehldiagnostizieren.
Ist die Bewegung kürzer als die Strecke, die zum Hoch- und wieder Herunterbeschleunigen nötig ist, erreicht die Achse nie das konfigurierte Tempo. Sie rampt hoch, trifft die Halbzeit und rampt sofort herunter – ein Dreieck, kein Trapez.
Die Schwelle lautet d < v_max² / a. Für die Zahlen oben sind das 20 mm – jede Bewegung kürzer als 20 mm deckelt also unter 100 mm/s, egal was man setzt.
Darum ändert v_max zu erhöhen an einer Maschine mit vielen kurzen Bewegungen nichts Messbares. Die Bewegungen waren nie tempobegrenzt; sie waren beschleunigungsbegrenzt. Ein 3D-Drucker mit dichtem Infill ist das Alltagsbeispiel.
Die Ecken sind weiter unstetig
Das Trapezprofil behebte Geschwindigkeit. Beschleunigung ansehen und das Problem ist nur gewandert.
Bei t = 0 springt Beschleunigung instant von 0 auf 500 mm/s². Oben auf der Rampe fällt sie instant auf 0 zurück. Jedes davon ist ein Sprung in Beschleunigung – und die Änderungsrate von Beschleunigung ist Ruck: Ein Sprung in Beschleunigung ist also ein unendlicher Ruckimpuls.
Unendlich ist keine Zahl, die eine Maschine erzeugen kann. Was sie stattdessen erzeugt:
- Einen hörbaren Schlag zu Beginn und Ende jeder Rampe.
- Klingeln – Riemen dehnen sich, Kupplungen winden sich auf, und die Struktur hat Nachgiebigkeit: Eine plötzliche Kraftänderung regt sie also an und sie schwingt danach. Auf einem Drucker ist das das Ghosting neben scharfen Merkmalen.
- Drehmomentspitzen, die Stromgrenzen auslösen, die die Durchschnittszahl für in Ordnung erklärte.
Die S-Kurve
Ein S-Kurven-Profil begrenzt Ruck wie Beschleunigung. Statt auf volle Beschleunigung zu springen, rampt es hinein über eine Ruckzeit t_j = a_max / j_max, hält, rampt dann hinaus. Die Geschwindigkeitskurve bekommt abgerundete Ecken – woher der Name –, und Beschleunigung wird ein eigenes Trapez.
Eine volle S-Kurven-Bewegung hat sieben Phasen: Ruck hoch, Beschleunigung halten, Ruck herunter, Marsch, und das Spiegelbild zum Stoppen.
Was es kostet: exakt ein t_j
Das lohnt Auswendiglernen – denn es macht den Tausch konkret.
Wenn beide Profile dasselbe v_max und dasselbe a_max erreichen, dauert die S-Kurven-Bewegung um exakt t_j länger – eine Ruckzeit, nicht zwei, und egal wie weit die Bewegung ist:
trapezoidal T = v_max/a + d/v_max
S-curve T = v_max/a + d/v_max + t_j where t_j = a_max / j_max
Für die durchgerechnete Bewegung: Aus 1,2 s werden 1,3 s. 8 % Aufschlag auf diese Bewegung, und ein kleinerer Prozentsatz auf längere – im Tausch gegen begrenzten Ruck.
Der Grund, warum es eine und nicht zwei sind: Das Beschleunigungssegment der S-Kurve ist länger, deckt also vor Marsch mehr Strecke ab – die Marschphase schrumpft also und gibt den Großteil der Zeit zurück. Nur die Ruckzeit selbst ist uneinbringlich.
Darin versteckt sich eine Zwangsbedingung. Die Beschleunigung erreicht a_max nur, wenn v_max ≥ a_max² / j_max. Darunter erreicht die Bewegung volle Beschleunigung ebenfalls nie – und man bekommt ein Dreiecksbeschleunigungsprofil: dieselbe „Strecke ausgegangen“-Geschichte, eine Ableitung höher.
„Ruck“ in Druckerfirmware ist kein Ruck
Wissenswert, bevor man irgendetwas abstimmt – denn das Vokabular täuscht aktiv.
Klassisches Marlins DEFAULT_XJERK ist nicht die Ableitung von Beschleunigung. Es ist die maximale instantane Geschwindigkeitsänderung, die an einer Stoßstelle zweier Bewegungen erlaubt ist, in mm/s – eine Kurvengenehmigung, die den Planer eine Ecke nehmen lässt, ohne auf null zu bremsen. Nützlich, aber eine andere Größe mit falschem Namen und falschen Einheiten.
Neueres Marlin nutzt stattdessen standardmäßig Junction Deviation – was die Ecke als Kreisbogen gegebener Abweichung in mm modelliert. Klipper nutzt square_corner_velocity – das Tempo, mit dem eine 90°-Ecke genommen wird. Alle drei sind Antworten auf „wie stoppe ich nicht an jeder Ecke?“, und keine ist eine Ruckgrenze im physikalischen Sinn.
Sagt ein Forenbeitrag also, deinen Ruck zu senken, um Klingeln zu stoppen, prüfen, welche Größe gemeint ist. Kurventempo zu senken verringert Kurvenschock; es begrenzt kein da/dt in einer einzelnen Bewegung.
Dein PID ist wahrscheinlich in Ordnung
Hat man eine geregelte Achse, die bei jeder Bewegung überschwingt und schwingt, lautet der Instinkt: verstimmen – Kp senken, D dazu, dem Überschwingen kämpfen.
Erst den Sollwert profilieren versuchen.
Ein Sprungeingang verlangt von einem PID-Regler unendlichen Ausgang. Sein Fehlerterm startet bei voller Bewegungsstrecke, der D-Term sieht einen instantanen Sprung, und der I-Term summiert auf, während der Ausgang sättigt und die Achse nicht antworten kann. Verstimmen macht den Regler überall träge, um einen unmöglichen Augenblick zu überleben.
Mit Profil bleibt der Fehler die ganze Bewegung klein – denn das Ziel liegt dort, wo die Achse wirklich sein kann. Dieselben Verstärkungen, die gegen einen Sprung unbrauchbar waren, sind gegen eine Rampe oft wohlgesittet – und nun korrigiert der Regler nur noch Last und Reibung, wofür er da ist. Den Unterschied kann man im PID-Simulator beobachten, indem man einen Sprungsollwert gegen einen graduellen vergleicht.
Wo du dem auf einem echten Roboter begegnest
- Schrittmotoren. AccelSteppers
setMaxSpeed()undsetAcceleration()liefern ein Trapezprofil und sonst nichts. Keine S-Kurven-Option; dafür erzeugt man den Sollwert selbst. - Hobbyservos. Ein SG90 hat einen internen Regler, den man weder sieht noch abstimmt – Profilieren heißt also, den befohlenen Winkel graduell zu schreiten statt das Ziel in einem Aufruf zu schreiben: dieselbe Idee von außen angewandt.
- DC-Motoren mit Encodern. Den Positionssollwert profilieren und die Encoder-PID folgen lassen. Das ist die Anordnung, wo Profilieren am besten zahlt.
- Mobile Roboter. Dieselbe Grenze gilt für
linear.xauf einer cmd_vel-Brücke: Ein Geschwindigkeitsstufensprung lässt die Räder rutschen, was Odometrie korrumpiert. Den Twist ratenbegrenzen. - Drucker und CNC. Marlin, Klipper und GRBL planen alle Trapezbewegungen mit Kurvenregel dazwischen.
Wenn es schiefgeht
| Symptom | Meist |
|---|---|
| Schrittmotor verliert unter Last lautlos Position | Kein Profil – Befehlsrate übersteigt Anzugsdrehmoment |
| Maschine schlägt zu Bewegungsbeginn und -ende | Trapezruckimpuls; braucht S-Kurve oder niedrigere Beschleunigung |
| Klingeln neben scharfen Merkmalen | Strukturresonanz, von Beschleunigungssprüngen angeregt |
| Kurze Bewegungen ignorieren die Tempoeinstellung | Dreiecksprofil – beschleunigungsbegrenzt, nicht tempobegrenzt |
| Überschwingen und Schwingen bei jeder Bewegung | Sprungsollwert in geschlossene Schleife; vor Verstimmen profilieren |
| Beschleunigung zu erhöhen hilft, dann plötzlich nicht | Nun drehmomentbegrenzt statt profilbegrenzt |
| Odometrie driftet bei Starts stark | Radschlupf aus Geschwindigkeitssprung; Befehl ratenbegrenzen |
Profilieren ist die billigste große Verbesserung, die den meisten Hobbybewegungssystemen offensteht – denn es kostet eine Funktion und keine Hardware. Der Roboterarmsimulator ist ein guter Ort zu sehen, warum es am Ende eines langen Glieds zählt, wo ein kleiner Beschleunigungsschritt an der Basis zum sichtbaren Wackeln am Greifer wird. Am mobilen Roboter ist dasselbe Profil das, was einen Pfadfolger für eine Ecke schärfer als sein Wenderadius langsamer werden lässt, statt ihr nicht zu folgen.
Den Graphen erkunden
Teil dieser Bauprojekte
Projekte und Lernpfade, die dieses Tutorial enthalten.
- ProjektEinen Stiftplotter bauen: Zwei Schrittmotorachsen, die ankommen
- ProjektPick-and-Place-Roboter: Der Fehlgriffe erkennt
- LernpfadGreifen und Endeffektoren: Wirklich aufnehmen
- LernpfadHolonomer Antrieb: Seitwärts fahren ohne Drehen
- LernpfadMotorsteuerung für Roboter: Ein Lernpfad
- LernpfadPfadfolge für Roboter: Ein Lernpfad
- LernpfadPräzisionsbewegung mit Schrittmotoren: Ein Lernpfad
Weiterführende Literatur