Tutoriel · Débutant · 18 min de lecture
Comment régler un contrôleur PID : guide pratique
Réglez un PID étape par étape : d'abord le gain proportionnel, puis la dérivée contre le dépassement, l'intégrale en dernier, et évitez l'emballement intégral.
Un contrôleur PID transforme l’erreur entre où un système est et où vous voulez qu’il soit en correction. Il a trois termes — proportionnel, intégral et dérivé — et régler est le processus de choisir l’intensité d’action de chacun. La façon fiable est un terme à la fois, dans un ordre fixe, en regardant la réponse après chaque changement. Vous pouvez suivre dans le simulateur de contrôleur PID.
Commencez par le gain proportionnel
Mettez les gains intégral et dérivé à zéro. Montez le gain proportionnel (Kp) jusqu’à ce que le système réponde vite à un changement de consigne. Trop peu et il réagit mollement ; trop et il dépasse et oscille. Arrêtez quand la réponse est rapide mais à peine oscillante — c’est votre point de travail pour ajouter les autres termes.
Une règle utile : P donne la vitesse. Il réagit à l’erreur de maintenant, et à rien d’autre.
Ajoutez la dérivée pour dompter le dépassement
Montez désormais le gain dérivé (Kd). L’action dérivée répond à la vitesse de changement de l’erreur, donc elle freine à l’approche de la consigne. C’est ce qui retire le dépassement et la sonnerie que la commande proportionnelle pure laisse.
Ajoutez juste assez de dérivée pour stabiliser l’oscillation. Trop rend le contrôleur nerveux, parce que le terme dérivé amplifie tout bruit de la mesure. Si votre signal est bruyant, filtrez-le avant de dériver, ou appuyez-vous sur le proportionnel et l’intégral à la place.
Ajoutez l’intégrale en dernier
Le proportionnel et la dérivée ensemble peuvent encore laisser un petit décalage constant — le système se gare juste avant la consigne. Le terme intégral (Ki) corrige cela : il accumule l’erreur dans le temps et pousse jusqu’à effacer le décalage.
Ajoutez le gain intégral lentement et seulement si une erreur permanente répétable subsiste. L’intégrale est le terme le plus lent et le plus facile à exagérer, donc peu va loin.
Surveillez l’emballement intégral
L’emballement intégral est la panne PID classique. Quand l’actionneur sature — un moteur déjà à pleine vitesse, une vanne grande ouverte — le système ne peut répondre, mais le terme intégral continue d’accumuler l’erreur. Quand l’erreur s’inverse enfin, toute cette action stockée se déroule d’un coup et le système dépasse fortement.
Prévenez-le en bornant l’intégrale (cessez d’y ajouter pendant que la sortie est saturée) ou par rétro-calcul (purgez l’intégrale en utilisant l’écart entre la sortie demandée et délivrée). Un simple bornage :
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
Gardez la temporisation de boucle honnête
Les trois termes dépendent d’un pas de temps cohérent. Sur un microcontrôleur, un long delay() dans la boucle ajoute un temps mort qui rend le terme dérivé inutile si haut que vous le mettiez, et il déforme l’intégrale. Faites tourner la boucle vite et à intervalle régulier, et passez le vrai temps écoulé dans le calcul.
Aller vite au but : le point de départ Ziegler–Nichols
Monter P jusqu’à trouver l’oscillation n’est pas juste un contrôle de bon sens — cela donne un nombre dont vous pouvez calculer tout le réglage. Mettez I et D à zéro, montez P jusqu’à ce que la sortie oscille régulièrement sans croître ni décroître, et notez deux choses :
Ku— le gain proportionnel où cela arrive (le gain ultime)Tu— la période de l’oscillation, en secondes
Puis :
| Contrôleur | Kp |
Ki |
Kd |
|---|---|---|---|
| P seul | 0.5 Ku |
— | — |
| PI | 0.45 Ku |
0.54 Ku / Tu |
— |
| PID (classique) | 0.6 Ku |
1.2 Ku / Tu |
0.075 Ku Tu |
| PID (sans dépassement) | 0.2 Ku |
0.4 Ku / Tu |
0.066 Ku Tu |
Ce sont un point de départ, pas une réponse. La ligne classique est délibérément agressive et dépasse typiquement de 20–40 %, ce qui va bien pour un moteur et est inacceptable pour un bras robotique près d’une table. La dernière ligne échange la vitesse de réponse contre l’atterrissage sans dépassement.
La valeur de la méthode est qu’elle remplace trois inconnues par deux mesures. Vingt minutes à trouver Ku et Tu mènent plus près qu’un après-midi à deviner, et vous pouvez ensuite régler à l’intuition à partir d’une bonne base.
Prenez la dérivée de la mesure, pas de l’erreur
C’est un changement d’une ligne qui corrige la plainte la plus courante sur D.
Quand la consigne fait un échelon, l’erreur fait un échelon avec elle. La dérivée d’un échelon est brièvement énorme, donc le contrôleur commande une correction violente pour une raison sans rapport avec la physique — rien n’a bougé, vous avez juste demandé quelque chose d’autre. Sur un robot c’est une secousse dure à chaque changement de cible.
// 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;
Le signe s’inverse parce que l’erreur est consigne − mesure : dériver la mesure à la place impose donc d’inverser le signe. Quand la consigne est constante, les deux formes sont mathématiquement identiques ; quand elle change, seule la seconde se comporte.
Utilisez la dérivée sur la mesure sauf raison précise de ne pas le faire. Il n’y a presque aucun cas où le pic est voulu.
Filtrez la dérivée, ou D amplifiera votre bruit
La dérivation amplifie le contenu haute fréquence, et le bruit de capteur est haute fréquence par définition. Un signal avec ±2 points de gigue échantillonné toutes les 10 ms produit une estimée de dérivée oscillant de ±200 points par seconde — que D transforme ensuite en commandes moteur.
Le résultat usuel est qu’on conclut que D est inutile et on le met à zéro. Le vrai problème est en amont :
// 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);
Choisir tau est un compromis : trop petit et le bruit survit, trop grand et D agit sur de l’information déjà périmée, ce que D existe justement à éviter. Commencez à trois à cinq fois votre période de boucle et augmentez seulement jusqu’à ce que les soubresauts cessent.
Un contrôleur complet
Tout ce qui précède, au même endroit :
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;
}
Trois choses là-dedans sont la différence entre un contrôleur qui marche sur un robot et un qui marche dans un manuel : la dérivée sur la mesure, une dérivée filtrée, et l’intégration conditionnelle pour que l’intégrale ne puisse s’emballer pendant que l’actionneur est saturé.
Diagnostiquer depuis la forme de la réponse
Vous pouvez nommer presque chaque faute de réglage depuis la seule courbe de réponse :
| Ce que vous voyez | Ce que cela signifie | Quoi changer |
|---|---|---|
| Monte lentement, n’arrive jamais | P trop bas, pas de I | Montez P ; ajoutez I s’il reste un décalage |
| Se stabilise avant la cible, en permanence | Pas de terme intégral | Ajoutez I, lentement |
| Dépasse une fois, puis se stabilise | P légèrement haut, pas de D | Ajoutez D |
| Dépasse à répétition, en s’amortissant | P trop haut | Baissez P, ou ajoutez D |
| Oscille indéfiniment à amplitude constante | P au gain ultime | Vous avez trouvé Ku — divisez par deux |
| L’oscillation croît | P au-dessus de Ku |
Réduisez aussitôt |
| Sortie rapide, hachée, nerveuse | D agissant sur du bruit | Filtrez la dérivée, ou filtrez le capteur |
| Secousse dure à chaque changement de consigne | Pic de dérivée | Dérivée sur la mesure |
| File loin passé après un grand déplacement | Emballement intégral | Intégration conditionnelle ou bornage |
| Allait bien hier, mou aujourd’hui | Système changé — d’ordinaire la batterie | Les gains sont des propriétés du système, pas du code |
Cette dernière ligne mérite l’emphase parce que ce n’est pas un bogue. Les gains décrivent un système précis, et le système inclut charge de batterie, masse du châssis, surface et température du réducteur. Un réglage parfait sur cellules fraîches sera mou sur cellules plates, parce que le même rapport cyclique produit désormais moins de couple. Les réponses professionnelles sont une boucle de vitesse dessous (pour que le contrôleur commande une vitesse, pas un rapport) ou une sélection de gains (plusieurs réglages, choisis selon la condition de fonctionnement).
Temporisation de boucle, quantifiée
I et D sont tous deux calculés par rapport au temps écoulé : une boucle qui tourne à un rythme irrégulier fausse donc les deux calculs.
| Comportement de boucle | Effet sur le contrôleur |
|---|---|
| Intervalle fixe | Tout marche comme conçu |
Variable, mais dt mesuré et passé |
Aussi correct — c’est la réponse pratique |
Variable, dt supposé constant |
I accumule faux ; D est du bruit |
Contient un delay() |
Temps mort — aucun D ne compense |
Mesurez dt avec micros() et passez-le. Cela ne coûte rien, cela survit à une boucle dont la durée change à mesure que des fonctions s’ajoutent, et cela retire une classe entière de mystère du réglage.
Si vous pouvez aussi rendre la boucle rapide, faites — un contrôleur échantillonnant à 20 Hz agit sur de l’information vieille jusqu’à 50 ms, et aucun gain ne corrige de l’information périmée. Retirer les appels delay() fait typiquement passer un premier robot de 20 Hz à plusieurs centaines, et le suivi s’améliore sans toucher un gain.
Essayez vous-même
Ouvrez le simulateur de contrôleur PID, mettez les gains I et D à zéro, et parcourez cet ordre. Regardez comment dépassement, temps de stabilisation et erreur permanente répondent chacun à un seul terme. Une fois la forme comprise ici, la même intuition se transfère à un vrai moteur, un chauffage, ou la boucle de braquage dans le simulateur de suiveur de ligne.
Explorer le graphe
Fait partie de ces réalisations
Les projets et parcours d'apprentissage qui incluent ce tutoriel.
Pour aller plus loin