Tutorial · Einsteiger · 18 Min. Lesezeit
Einen PID-Regler abstimmen: Eine praktische Anleitung
Einen PID-Regler Schritt für Schritt abstimmen: erst Proportionalverstärkung setzen, D gegen Überschwingen dazu, I zuletzt – und Integral-Windup vermeiden.
Ein PID-Regler verwandelt den Fehler zwischen dem, wo ein System ist, und dem, wo du es haben willst, in eine Korrektur. Er hat drei Anteile – proportional, integral und differenziell –, und Abstimmen heißt entscheiden, wie stark jeder wirkt. Der verlässliche Weg tut das Anteil für Anteil, in fester Reihenfolge, mit Blick auf die Antwort nach jeder Änderung. Man kann im PID-Regler-Simulator mitgehen.
Mit Proportionalverstärkung anfangen
Integral- und Differenzialverstärkung auf null setzen. Die Proportionalverstärkung (Kp) erhöhen, bis das System schnell auf eine Sollwertänderung antwortet. Zu wenig und es reagiert träge; zu viel und es schwingt über und oszilliert. Stoppen, wenn die Antwort schnell, aber nur leicht schwingend ist – das ist der Arbeitspunkt, um die anderen Anteile hinzuzufügen.
Eine nützliche Regel: P bringt Tempo. Es reagiert auf den Fehler genau jetzt, sonst nichts.
D gegen Überschwingen hinzufügen
Nun die Differenzialverstärkung (Kd) erhöhen. Der D-Anteil antwortet darauf, wie schnell sich der Fehler ändert – bremst also, während sich das System dem Sollwert nähert. Das beseitigt Überschwingen und Klingeln, die reine Proportionalregelung hinterlässt.
Gerade genug D hinzufügen, um die Schwingung zu beruhigen. Zu viel macht den Regler nervös – denn der D-Anteil verstärkt jedes Rauschen in der Messung. Bei verrauschtem Signal erst filtern, dann differenzieren – oder sich auf proportional und integral stützen.
Integral zuletzt hinzufügen
Proportional plus differenziell zusammen können einen kleinen, stabilen Versatz lassen – das System parkt knapp vor dem Sollwert. Der Integralanteil (Ki) behebt das: Er summiert Fehler über Zeit auf und drückt, bis der Versatz weg ist.
Integralverstärkung langsam hinzufügen und nur, wenn ein wiederholbarer bleibender Fehler übrig bleibt. Integral ist der langsamste Anteil und am leichtesten zu übertreiben – wenig bringt viel.
Auf Integral-Windup achten
Integral-Windup ist der klassische PID-Fehler. Wenn der Aktor sättigt – ein Motor bereits auf Vollgas, ein Ventil voll offen –, kann das System nicht antworten, aber der Integralanteil sammelt weiter Fehler auf. Wenn sich der Fehler endlich umkehrt, entlädt sich all die gespeicherte Wirkung auf einmal und das System schwingt heftig über.
Verhindern durch Begrenzen des Integrals (nichts mehr aufsummieren, solange der Ausgang sättigt) oder per Rückrechnung (das Integral über die Lücke zwischen angefordertem und geliefertem Ausgang abschmelzen). Eine einfache Begrenzung:
float candidateIntegral = integral + error * dt;
float raw = kp * error + ki * candidateIntegral + kd * derivative;
float output = constrain(raw, outputMin, outputMax);
if (raw == output) integral = candidateIntegral; // only accumulate when not saturated
Das Schleifentiming ehrlich halten
Alle drei Anteile hängen an einem konsistenten Zeitschritt. Auf einem Mikrocontroller fügt ein langes delay() in der Schleife Totzeit hinzu, die den D-Anteil nutzlos macht – egal wie hoch man ihn setzt –, und verzerrt das Integral. Die Schleife schnell und mit stabilem Intervall fahren und die echte vergangene Zeit in die Rechnung geben.
Schnell nahe heran: der Ziegler-Nichols-Startpunkt
P hochzufahren, bis man die Schwingung findet, ist nicht nur eine Plausibilitätsprüfung – es liefert eine Zahl, aus der sich die ganze Abstimmung rechnen lässt. I und D auf null setzen, P erhöhen, bis der Ausgang gleichmäßig schwingt, ohne zu wachsen oder abzuklingen, und zwei Dinge notieren:
Ku– die Proportionalverstärkung, bei der das geschieht (die kritische Verstärkung)Tu– die Periode der Schwingung, in Sekunden
Dann:
| Regler | Kp |
Ki |
Kd |
|---|---|---|---|
| Nur P | 0,5 Ku |
— | — |
| PI | 0,45 Ku |
0,54 Ku / Tu |
— |
| PID (klassisch) | 0,6 Ku |
1,2 Ku / Tu |
0,075 Ku Tu |
| PID (ohne Überschwingen) | 0,2 Ku |
0,4 Ku / Tu |
0,066 Ku Tu |
Das ist ein Startpunkt, keine Antwort. Die klassische Zeile ist absichtlich aggressiv und schwingt typisch 20–40 % über – in Ordnung für einen Motor und inakzeptabel für einen Roboterarm nahe einem Tisch. Die letzte Zeile tauscht Ansprechtempo gegen überschwingfreies Landen.
Der Wert der Methode: Sie ersetzt drei Unbekannte durch zwei Messungen. Zwanzig Minuten für Ku und Tu bringen näher als ein Nachmittag Raten – und danach stimmt man von einem vernünftigen Ort aus nach Gefühl ab.
Die Ableitung der Messung nehmen, nicht des Fehlers
Das ist eine Ein-Zeilen-Änderung, die die häufigste Beschwerde über D behebt.
Wenn der Sollwert springt, springt der Fehler mit. Die Ableitung eines Sprungs ist kurzzeitig riesig – der Regler befiehlt also eine heftige Korrektur aus einem Grund, der nichts mit Physik zu tun hat: Nichts bewegte sich, man verlangte nur etwas anderes. Am Roboter ist das ein harter Ruck bei jeder Zieländerung.
// Derivative kick: the setpoint step goes straight into the output.
float derivative = (error - lastError) / dt;
// Derivative on measurement: the setpoint contributes nothing at all.
float derivative = -(measurement - lastMeasurement) / dt;
Das Vorzeichen dreht, weil Fehler Sollwert − Messung ist – die Messung statt zu differenzieren heißt also negieren. Bei konstantem Sollwert sind beide Formen mathematisch identisch; wenn er sich ändert, benimmt sich nur die zweite.
Ableitung der Messung verwenden, wenn man keinen bestimmten Grund dagegen hat. Es gibt fast keinen Fall, wo der Ruck gewollt ist.
Die Ableitung filtern, sonst verstärkt D dein Rauschen
Differenzieren verstärkt hochfrequente Anteile – und Sensorrauschen ist definitionsgemäß hochfrequent. Ein Signal mit ±2 Zähleinheiten Zittern, alle 10 ms abgetastet, erzeugt eine Ableitungsschätzung, die um ±200 Zähleinheiten pro Sekunde schwankt – was D dann in Motorbefehle verwandelt.
Das übliche Ergebnis: Leute schließen, D sei nutzlos, und setzen es auf null. Das echte Problem liegt davor:
// A first-order filter on the derivative term only.
// alpha = dt / (tau + dt); tau is the filter time constant in seconds.
const float tau = 0.05f; // 50 ms
const float alpha = dt / (tau + dt);
dFiltered += alpha * (dRaw - dFiltered);
tau zu wählen ist ein Zielkonflikt: zu klein und das Rauschen überlebt, zu groß und D wirkt auf Information, die bereits alt ist – genau das, wogegen D existiert. Bei drei- bis fünffacher Schleifenperiode anfangen und nur erhöhen, bis das Zucken stoppt.
Ein vollständiger Regler
Alles oben, an einem Ort:
struct Pid {
float kp, ki, kd;
float outMin, outMax;
float tau; // derivative filter time constant
float integral = 0;
float lastMeasurement = 0;
float dFiltered = 0;
bool primed = false;
};
float pidUpdate(Pid &c, float setpoint, float measurement, float dt) {
if (dt <= 0) return 0;
const float error = setpoint - measurement;
// Derivative on measurement, low-pass filtered.
if (!c.primed) { c.lastMeasurement = measurement; c.primed = true; }
const float dRaw = -(measurement - c.lastMeasurement) / dt;
const float alpha = dt / (c.tau + dt);
c.dFiltered += alpha * (dRaw - c.dFiltered);
c.lastMeasurement = measurement;
// Provisional integral, committed only if the output does not saturate.
const float candidate = c.integral + error * dt;
const float raw = c.kp * error + c.ki * candidate + c.kd * c.dFiltered;
const float out = constrain(raw, c.outMin, c.outMax);
if (raw == out) c.integral = candidate; // conditional integration
return out;
}
Drei Dinge darin sind der Unterschied zwischen einem Regler, der an einem Roboter arbeitet, und einem, der im Lehrbuch arbeitet: Ableitung der Messung, eine gefilterte Ableitung und bedingte Integration, damit das Integral nicht aufwickeln kann, während der Aktor sättigt.
Aus der Antwortkurvenform diagnostizieren
Fast jeden Abstimmungsfehler kann man allein an der Antwortkurve benennen:
| Was du siehst | Was es heißt | Was zu ändern ist |
|---|---|---|
| Steigt langsam, kommt nie an | P zu niedrig, kein I | P erhöhen; I dazu, wenn ein Versatz bleibt |
| Pendelt sich dauerhaft vor dem Ziel ein | Kein Integralanteil | I langsam hinzufügen |
| Schwingt einmal über, pendelt sich dann ein | Leicht hohes P, kein D | D hinzufügen |
| Schwingt wiederholt über, abklingend | P zu hoch | P senken oder D hinzufügen |
| Schwingt ewig mit konstanter Amplitude | P an der kritischen Verstärkung | Du hast Ku gefunden – halbieren |
| Schwingung wächst | P über Ku |
Sofort verringern |
| Schneller, zackiger, zittriger Ausgang | D wirkt auf Rauschen | Ableitung filtern oder Sensor filtern |
| Ruckt hart bei jeder Sollwertänderung | Ableitungsstoß | Ableitung der Messung |
| Segelt nach großer Bewegung weit darüber | Integral-Windup | Bedingte Integration oder Begrenzung |
| Gestern in Ordnung, heute träge | Strecke änderte sich – meist der Akku | Verstärkungen sind Eigenschaften der Strecke, nicht des Codes |
Die letzte Zeile verdient Betonung, weil sie kein Fehler ist. Verstärkungen beschreiben eine bestimmte Strecke – und zur Strecke gehören Akkuladung, Chassismasse, Untergrund und Getriebetemperatur. Eine Abstimmung, die mit frischen Zellen perfekt war, wirkt mit leeren träge – denn dasselbe Tastverhältnis erzeugt nun weniger Drehmoment. Die professionellen Antworten sind eine Drehzahlschleife darunter (damit der Regler Drehzahl befiehlt, nicht Tastverhältnis) oder Gain-Scheduling (mehrere Abstimmungen, nach Betriebsbedingung gewählt).
Schleifentiming in Zahlen
I wie D werden gegen vergangene Zeit gerechnet – eine Schleife, die läuft, wann immer sie gerade fertig wird, rechnet also beide gegen eine Lüge.
| Schleifenverhalten | Wirkung auf den Regler |
|---|---|
| Festes Intervall | Alles arbeitet wie entworfen |
Variabel, aber dt gemessen und übergeben |
Ebenfalls korrekt – die praktische Antwort |
Variabel, dt konstant angenommen |
I summiert falsch auf; D ist Rauschen |
Enthält ein delay() |
Totzeit – kein D der Welt gleicht aus |
dt mit micros() messen und übergeben. Es kostet nichts, überlebt eine Schleife, deren Dauer mit neuen Features wächst, und beseitigt eine ganze Mysterienklasse aus dem Abstimmen.
Wenn die Schleife außerdem schnell sein kann: tun – ein Regler, der mit 20 Hz abtastet, handelt auf bis zu 50 ms alte Information, und keine Verstärkung behebt alte Information. delay()-Aufrufe zu entfernen bringt einen ersten Roboter typisch von 20 Hz auf mehrere hundert – und die Folgegenauigkeit steigt, ohne eine Verstärkung anzufassen.
Selbst ausprobieren
Den PID-Regler-Simulator öffnen, I- und D-Verstärkungen nullen und diese Reihenfolge durchgehen. Beobachten, wie Überschwingen, Einschwingzeit und bleibende Regelabweichung jeweils auf einen einzelnen Anteil antworten. Sobald die Form hier Sinn ergibt, überträgt sich dieselbe Intuition auf einen echten Motor, eine Heizung oder die Lenkschleife im Linienfolger-Simulator.
Den Graphen erkunden
Teil dieser Bauprojekte
Projekte und Lernpfade, die dieses Tutorial enthalten.
Weiterführende Literatur