Tutorial · Beginner · 18 min lezen
Een PID-regelaar afstellen: een praktische gids
PID-regelaar stap voor stap afstellen: eerst de proportionele versterking, dan differentiaal tegen overschrijding, als laatste integraal, en voorkom windup.
Een PID-regelaar maakt van de regelfout tussen waar een systeem is en waar je het wilt hebben een correctie. Hij heeft drie termen — proportioneel, integraal en differentiaal — en afstemmen is het proces van kiezen hoe sterk elk daarvan werkt. De betrouwbare manier is één term tegelijk, in een vaste volgorde, waarbij je na elke wijziging naar de respons kijkt. Je kunt meedoen in de PID Controller Simulator.
Begin met de proportionele versterking
Zet de integrale en differentiale versterking op nul. Verhoog de proportionele versterking (Kp) tot het systeem snel reageert op een wijziging van de setpoint. Te weinig en het reageert traag; te veel en het schiet door en trilt. Stop wanneer de respons snel is maar alleen licht oscilleert — dat is je werkpunt om de andere termen aan toe te voegen.
Een nuttige vuistregel: P geeft je snelheid. Het reageert op de regelfout van nu, en op niets anders.
Voeg differentiaal toe om overschrijding te temmen
Verhoog nu de differentiale versterking (Kd). Differentiaalwerking reageert op hoe snel de regelfout verandert, en het trekt aan de handrem terwijl het systeem de setpoint nadert. Dat is wat de overschrijding en de oscillatie verwijdert die zuivere proportionele regeling achterlaat.
Voeg precies genoeg differentiaal toe om de oscillatie te laten bezinken. Te veel maakt de regelaar schokkerig, omdat de differentiaalterm ruis in de meting versterkt. Is je signaal ruisvol, filter het dan voordat je differentieert, of leun in plaats daarvan op proportioneel en integraal.
Voeg als laatste integraal toe
Proportioneel en differentiaal samen kunnen nog steeds een kleine, blijvende afwijking achterlaten — het systeem parkeert netjes voor de setpoint. De integrale term (Ki) verhelpt dat: hij stapelt de fout over de tijd op en duwt tot de afwijking verdwenen is.
Voeg de integrale versterking langzaam toe, en alleen als er een herhaalbare blijvende fout overblijft. Integraal is de traagste term en de gemakkelijkst om over te doseren, dus een beetje doet al veel.
Let op integrale windup
Integrale windup is de klassieke PID-storing. Als de actuator verzadigd — een motor die al op volle snelheid draait, een klep die helemaal open staat — kan het systeem niet reageren, maar blijft de integrale term de fout opstapelen. Als de fout eindelijk omkeert, ontrolt al die opgespaarde actie in één keer en schiet het systeem flink door.
Voorkom dat door de integraal te begrenzen (stoppen met optellen zolang de uitvoer verzadigd is) of met terugberekening (de integraal laten weglopen met het verschil tussen de gevraagde en de geleverde uitvoer). Een eenvoudige begrenzing:
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
Houd de lustiming eerlijk
Alle drie de termen hangen af van een consistente tijdstap. Op een microcontroller voegt een lange delay() in de lus dode tijd toe die de differentiaalterm onbruikbaar maakt hoe hoog je hem ook instelt, en die vervormt de integraal. Voer de lus snel en op een vast interval uit, en geef de werkelijk verstreken tijd door aan de berekening.
Snel dichtbij komen: het Ziegler–Nichols-startpunt
P verhogen tot je de oscillatie vindt is niet alleen een gezondheidscontrole — het levert je een getal waaruit je de hele afstelling kunt berekenen. Zet I en D op nul, verhoog P tot de uitvoer gestaag oscilleert zonder te groeien of te vervallen, en leg twee dingen vast:
Ku— de proportionele versterking waarbij dat gebeurt (de uiteindelijke versterking)Tu— de periode van de oscillatie, in seconden
Dan:
| Regelaar | Kp |
Ki |
Kd |
|---|---|---|---|
| Alleen P | 0.5 Ku |
— | — |
| PI | 0.45 Ku |
0.54 Ku / Tu |
— |
| PID (klassiek) | 0.6 Ku |
1.2 Ku / Tu |
0.075 Ku Tu |
| PID (zonder overschrijding) | 0.2 Ku |
0.4 Ku / Tu |
0.066 Ku Tu |
Dit is een startpunt, geen antwoord. De klassieke rij is bewust agressief en schiet doorgaans 20–40% door, wat prima is voor een motor en onaanvaardbaar voor een robotarm vlak bij een tafel. De laatste rij ruilt reactsnelheid in voor aankomen zonder overschrijding.
De waarde van de methode is dat ze drie onbekenden vervangt door twee metingen. Twintig minuten zoeken naar Ku en Tu brengt je dichterbij dan een middag gokken, en daarna kun je vanuit een verstandig punt op gevoel verder afstellen.
Neem de afgeleide van de meting, niet van de fout
Dit is een wijziging van één regel die de meest voorkomende klacht over D oplost.
Als de setpoint een stap maakt, maakt de fout daarmee mee. De afgeleide van een stap is kort even enorm, dus de regelaar geeft een geweldige correctie om een reden die niets met natuurkunde te maken heeft — er is niets bewogen, je vroeg alleen om iets anders. Op een robot is dat elke keer dat je de bestemming verandert een harde schok.
// 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;
Het teken keert om omdat de fout gelijk is aan setpoint − measurement, dus differentiëren van de meting betekent ontkennen. Als de setpoint constant is, zijn de twee vormen wiskundig identiek; als hij verandert, gedraagt alleen de tweede zich goed.
Gebruik differentiaal op de meting tenzij je een specifieke reden hebt om dat niet te doen. Er is vrijwel geen geval waarin je de schok wilt.
Filter de afgeleide, anders versterkt D je ruis
Differentiëren versterkt hoogfrequente inhoud, en sensorruis is per definitie hoogfrequent. Een signaal met ±2 counts jitter, elke 10 ms bemonsterd, levert een schatting van de afgeleide die rondzwiert met ±200 counts per seconde — en D maakt daarvan motorcommando’s.
Het gebruikelijke gevolg is dat mensen concluderen dat D nutteloos is en het op nul zetten. Het echte probleem ligt stroomopwaarts:
// 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 kiezen is een afweging: te klein en de ruis blijft over, te groot en D werkt op informatie die al verouderd is, en dat is precies wat D moet vermijden. Begin op drie tot vijf keer je lusperiode en verhoog alleen tot het schokkeren stopt.
Een complete regelaar
Alles hierboven op één plek:
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;
}
Drie dingen daarin maken het verschil tussen een regelaar die op een robot werkt en een die in een leerboek werkt: differentiaal op de meting, een gefilterde afgeleide en voorwaardelijke integratie, zodat de integraal niet kan opwinden terwijl de actuator verzadigd is.
Diagnosticeren op basis van de vorm van de respons
Je kunt bijna elke afstellfout noemen op basis van alleen de responskromme:
| Wat je ziet | Wat het betekent | Wat je verandert |
|---|---|---|
| Stijgt langzaam, komt nooit aan | P te laag, geen I | Verhoog P; voeg I toe als er een afwijking overblijft |
| Komt blijvend voor de bestemming tot rust | Geen integrale term | Voeg I toe, langzaam |
| Schiet een keer door en komt tot rust | P iets te hoog, geen D | Voeg D toe |
| Schiet herhaaldelijk door, in dalende mate | P te hoog | Verlaag P, of voeg D toe |
| Trilt eeuwig op constante amplitude | P op de uiteindelijke versterking | Je hebt Ku gevonden — halveer hem |
| De trilling groeit | P boven Ku |
Verminder onmiddellijk |
| Snelle, ruwe, schokkerige uitvoer | D werkt op ruis | Filter de afgeleide, of filter de sensor |
| Schokt hard bij elke wijziging van de setpoint | Derivatieve schok | Differentiaal op de meting |
| Zeilt ver voorbij na een grote beweging | Integrale windup | Voorwaardelijke integratie of een begrenzing |
| Gisteren prima, vandaag traag | Het proces is veranderd — meestal de batterij | Versterkingen zijn eigenschappen van het proces, niet van de code |
Die laatste rij verdient nadruk omdat het geen bug is. Versterkingen beschrijven een specifiek proces, en dat proces omvat lading, chassismassa, ondergrond en temperatuur van de overbrenging. Een afstelling die perfect was op verse cellen traagt op bijna lege, want dezelfde inschakelduur levert nu minder koppelmoment. De professionele antwoorden zijn een snelheidslus eronder (zodat de regelaar snelheid aanstuurt in plaats van inschakelduur) of gainschema’s (meerdere afstellingen, gekozen op basis van de bedrijfstoestand).
Lustiming, gekwantificeerd
Zowel I als D worden berekend tegen de verstreken tijd, dus een lus die draait wanneer hij toevallig klaar is berekent beide tegen een leugen.
| Gedrag van de lus | Effect op de regelaar |
|---|---|
| Vast interval | Alles werkt zoals ontworpen |
Variabel, maar dt gemeten en doorgegeven |
Ook correct — dit is het praktische antwoord |
Variabel, dt constant verondersteld |
I telt verkeerd op; D is ruis |
Bevat een delay() |
Dode tijd — geen hoeveelheid D compenseert dat |
Meet dt met micros() en geef het door. Het kost niets, het overleeft een lus waarvan de duur verandert als er functies bij komen, en het haalt een hele klasse mysteries uit het afstellen.
Kun je de lus ook nog snel maken, doe dat dan — een regelaar die op 20 Hz bemonstert werkt met informatie tot 50 ms oud, en geen versterking repareert verouderde informatie. delay()-aanroepen verwijderen tilt doorgaans een eerste robot van 20 Hz naar enkele honderd, en het volgen wordt beter zonder één versterking aan te raken.
Probeer het zelf
Open de PID Controller Simulator, zet de I- en D-versterkingen op nul en loop deze volgorde door. Kijk hoe overschrijding, bezinktijd en blijvende fout elk op één term reageren. Zodra de vorm hier begint te schuren, draagt hetzelfde inzicht over naar een echte motor, een verwarming of de besturingslus in de Line Follower Simulator.
Verken de graaf
Onderdeel van deze bouwprojecten
Projecten en leerroutes waarin deze tutorial voorkomt.
Verder lezen