← Volver al blog

Qué es un control PID y cómo implementarlo en firmwareWhat a PID controller is and how to implement it in firmwareQuè és un control PID i com implementar-lo en firmwareQu'est-ce qu'un régulateur PID et comment l'implémenter dans le firmware

Si tu producto tiene que mantener una variable en un valor objetivo —la velocidad de un motor, la temperatura de un horno, la posición de un brazo, la presión de una bomba— tarde o temprano te toparás con el control PID. Es el algoritmo de control más usado de la industria, y entenderlo bien marca la diferencia entre un producto que responde con suavidad y otro que oscila, se pasa de largo o reacciona tarde.

Qué es un control PID

Un controlador PID (Proporcional-Integral-Derivativo) es un algoritmo que ajusta de forma continua una salida para que una medida real se acerque a un valor deseado, llamado referencia o setpoint. Lo hace calculando el error (la diferencia entre lo que quieres y lo que hay) y corrigiéndolo a partir de tres componentes que trabajan juntas.

Referencia Σ + error e(t) Controlador P · I · D u(t) Proceso / Planta salida y(t) Sensor
Lazo de control en bucle cerrado: el sensor mide la salida real, se compara con la referencia y el PID corrige el error.

Las tres componentes: P, I y D

  • Proporcional (P): reacciona al error actual. Cuanto más lejos estás del objetivo, más fuerte corrige. Sube la velocidad de respuesta, pero por sí sola deja un pequeño error permanente y, si es muy alta, provoca oscilaciones.
  • Integral (I): acumula el error pasado. Es la que elimina ese error permanente: mientras quede diferencia, sigue empujando hasta clavar el valor. A cambio, si te pasas, ralentiza y puede provocar sobreoscilación (overshoot).
  • Derivativa (D): anticipa el error futuro mirando lo rápido que cambia. Actúa como un freno que suaviza la respuesta y reduce el overshoot, pero amplifica el ruido del sensor, así que hay que usarla con cuidado.

La salida del controlador es la suma de las tres: u(t) = Kp·e + Ki·∫e·dt + Kd·de/dt. Ajustar las ganancias Kp, Ki y Kd es lo que define el carácter del sistema.

Un ejemplo sencillo: la velocidad de un motor

Imagina un motor que debe girar a 1.000 rpm. Mides las rpm reales con un encoder, las restas a las 1.000 deseadas y obtienes el error. El PID convierte ese error en una señal PWM que alimenta el motor: si va lento, sube el PWM; si se pasa, lo baja. El encoder vuelve a medir y el ciclo se repite decenas o cientos de veces por segundo. El resultado es un motor que mantiene la velocidad aunque cambie la carga —exactamente lo mismo que hace el control de crucero de un coche en una cuesta—.

Cómo se implementa en firmware

En un microcontrolador, el PID se calcula en un bucle a intervalo fijo (por ejemplo, cada 10 ms desde una interrupción de temporizador). Una implementación discreta básica en C es así:

typedef struct {
    float kp, ki, kd;
    float integral, prev_error;
    float out_min, out_max;   // límites de la salida
} pid_t;

float pid_update(pid_t *pid, float setpoint, float measured, float dt) {
    float error = setpoint - measured;
    pid->integral += error * dt;
    float derivative = (error - pid->prev_error) / dt;
    pid->prev_error = error;

    float out = pid->kp * error
              + pid->ki * pid->integral
              + pid->kd * derivative;

    // Saturación + anti-windup: no dejes crecer la integral sin límite
    if (out > pid->out_max) { out = pid->out_max; pid->integral -= error * dt; }
    if (out < pid->out_min) { out = pid->out_min; pid->integral -= error * dt; }
    return out;
}

Los detalles que separan un PID de juguete de uno profesional están en lo que rodea a esa fórmula: un dt constante y bien medido, la saturación de la salida con anti-windup (para que la integral no se dispare cuando el actuador llega al máximo), el filtrado del término derivativo y el uso de aritmética adecuada (entera o de punto fijo) en MCUs sin unidad de coma flotante.

Cómo ajustar (tunear) un PID

  • Empieza solo con P: súbela hasta que el sistema responda rápido pero justo antes de que empiece a oscilar.
  • Añade I poco a poco para eliminar el error permanente, sin pasarte (provoca sobreoscilación).
  • Usa D con moderación para amortiguar, solo si el ruido del sensor lo permite.
  • Métodos como Ziegler-Nichols dan un punto de partida, pero el ajuste fino casi siempre es empírico y depende de tu hardware real.

Errores comunes

  • Calcular el PID con un dt variable (por ejemplo dentro de un loop() sin control de tiempo): los resultados se vuelven impredecibles.
  • Olvidar el anti-windup: el sistema responde con un retardo enorme tras saturar.
  • Aplicar la derivada directamente sobre una señal ruidosa, lo que mete vibraciones en el actuador.
  • Querer resolverlo todo con PID cuando el proceso tiene grandes retardos o no linealidades: a veces hace falta otra estrategia.

Conclusión

Un control PID bien implementado es la diferencia entre un producto que se siente sólido y uno que vibra, se calienta o responde tarde. El concepto es sencillo, pero hacerlo robusto en un microcontrolador real —con su temporización, su ruido y los límites del actuador— es un trabajo de firmware fino. En Regular Solids diseñamos e implementamos lazos de control para motores, temperatura, potencia y movimiento en productos embebidos. Si tienes un producto que necesita controlar algo con precisión, cuéntanoslo.

If your product has to keep a variable at a target value —a motor's speed, an oven's temperature, an arm's position, a pump's pressure— sooner or later you'll meet PID control. It's the most widely used control algorithm in industry, and understanding it well is the difference between a product that responds smoothly and one that oscillates, overshoots or reacts too late.

What a PID controller is

A PID controller (Proportional-Integral-Derivative) is an algorithm that continuously adjusts an output so a measured value gets close to a desired value, called the reference or setpoint. It does this by computing the error (the difference between what you want and what you have) and correcting it through three components working together.

Setpoint Σ + error e(t) Controller P · I · D u(t) Process / Plant output y(t) Sensor
Closed-loop control: the sensor measures the real output, it's compared with the setpoint and the PID corrects the error.

The three components: P, I and D

  • Proportional (P): reacts to the current error. The further you are from target, the harder it corrects. It speeds up the response, but on its own leaves a small steady-state error and, if too high, causes oscillation.
  • Integral (I): accumulates past error. This is what removes that steady-state error: as long as a gap remains, it keeps pushing until it nails the value. In exchange, overdoing it slows things down and can cause overshoot.
  • Derivative (D): anticipates future error by looking at how fast it changes. It acts like a brake that smooths the response and reduces overshoot, but it amplifies sensor noise, so use it carefully.

The controller output is the sum of the three: u(t) = Kp·e + Ki·∫e·dt + Kd·de/dt. Tuning the gains Kp, Ki and Kd is what defines the system's character.

A simple example: a motor's speed

Picture a motor that must spin at 1,000 rpm. You measure the real rpm with an encoder, subtract them from the desired 1,000 and get the error. The PID turns that error into a PWM signal driving the motor: if it's slow, raise the PWM; if it overshoots, lower it. The encoder measures again and the cycle repeats tens or hundreds of times per second. The result is a motor that holds its speed even as the load changes —exactly what a car's cruise control does on a hill—.

How to implement it in firmware

On a microcontroller, the PID is computed in a fixed-interval loop (for example, every 10 ms from a timer interrupt). A basic discrete implementation in C looks like this:

typedef struct {
    float kp, ki, kd;
    float integral, prev_error;
    float out_min, out_max;   // output limits
} pid_t;

float pid_update(pid_t *pid, float setpoint, float measured, float dt) {
    float error = setpoint - measured;
    pid->integral += error * dt;
    float derivative = (error - pid->prev_error) / dt;
    pid->prev_error = error;

    float out = pid->kp * error
              + pid->ki * pid->integral
              + pid->kd * derivative;

    // Saturation + anti-windup: don't let the integral grow unbounded
    if (out > pid->out_max) { out = pid->out_max; pid->integral -= error * dt; }
    if (out < pid->out_min) { out = pid->out_min; pid->integral -= error * dt; }
    return out;
}

The details that separate a toy PID from a professional one live around that formula: a constant, well-measured dt, output saturation with anti-windup (so the integral doesn't blow up when the actuator hits its limit), filtering of the derivative term, and the right arithmetic (integer or fixed-point) on MCUs without a floating-point unit.

How to tune a PID

  • Start with P only: raise it until the system responds quickly but just before it starts to oscillate.
  • Add I gradually to remove the steady-state error, without overdoing it (it causes overshoot).
  • Use D sparingly to dampen, only if sensor noise allows it.
  • Methods like Ziegler-Nichols give a starting point, but fine tuning is almost always empirical and depends on your real hardware.

Common mistakes

  • Computing the PID with a variable dt (for example inside a loop() with no timing control): results become unpredictable.
  • Forgetting anti-windup: the system responds with a huge delay after saturating.
  • Applying the derivative directly on a noisy signal, injecting vibration into the actuator.
  • Trying to solve everything with PID when the process has large delays or nonlinearities: sometimes another strategy is needed.

Conclusion

A well-implemented PID is the difference between a product that feels solid and one that vibrates, overheats or reacts late. The concept is simple, but making it robust on a real microcontroller —with its timing, its noise and the actuator's limits— is fine firmware work. At Regular Solids we design and implement control loops for motors, temperature, power and motion in embedded products. If you have a product that needs to control something precisely, tell us about it.

Si el teu producte ha de mantenir una variable en un valor objectiu —la velocitat d'un motor, la temperatura d'un forn, la posició d'un braç, la pressió d'una bomba— tard o d'hora et trobaràs amb el control PID. És l'algorisme de control més utilitzat de la indústria, i entendre'l bé marca la diferència entre un producte que respon amb suavitat i un altre que oscil·la, se'n passa o reacciona tard.

Què és un control PID

Un controlador PID (Proporcional-Integral-Derivatiu) és un algorisme que ajusta de manera contínua una sortida perquè una mesura real s'acosti a un valor desitjat, anomenat referència o setpoint. Ho fa calculant l'error (la diferència entre el que vols i el que hi ha) i corregint-lo a partir de tres components que treballen juntes.

Referència Σ + error e(t) Controlador P · I · D u(t) Procés / Planta sortida y(t) Sensor
Llaç de control en bucle tancat: el sensor mesura la sortida real, es compara amb la referència i el PID corregeix l'error.

Les tres components: P, I i D

  • Proporcional (P): reacciona a l'error actual. Com més lluny estàs de l'objectiu, més fort corregeix. Augmenta la velocitat de resposta, però tota sola deixa un petit error permanent i, si és molt alta, provoca oscil·lacions.
  • Integral (I): acumula l'error passat. És la que elimina aquest error permanent: mentre quedi diferència, segueix empenyent fins a clavar el valor. A canvi, si te'n passes, alenteix i pot provocar sobreoscil·lació (overshoot).
  • Derivativa (D): anticipa l'error futur mirant amb quina rapidesa canvia. Actua com un fre que suavitza la resposta i redueix l'overshoot, però amplifica el soroll del sensor, així que cal fer-la servir amb compte.

La sortida del controlador és la suma de les tres: u(t) = Kp·e + Ki·∫e·dt + Kd·de/dt. Ajustar els guanys Kp, Ki i Kd és el que defineix el caràcter del sistema.

Un exemple senzill: la velocitat d'un motor

Imagina un motor que ha de girar a 1.000 rpm. Mesures les rpm reals amb un encoder, les restes a les 1.000 desitjades i obtens l'error. El PID converteix aquest error en un senyal PWM que alimenta el motor: si va lent, puja el PWM; si se'n passa, el baixa. L'encoder torna a mesurar i el cicle es repeteix desenes o centenars de vegades per segon. El resultat és un motor que manté la velocitat encara que canviï la càrrega —exactament el mateix que fa el control de creuer d'un cotxe en una pujada—.

Com s'implementa en firmware

En un microcontrolador, el PID es calcula en un bucle a interval fix (per exemple, cada 10 ms des d'una interrupció de temporitzador). Una implementació discreta bàsica en C és així:

typedef struct {
    float kp, ki, kd;
    float integral, prev_error;
    float out_min, out_max;   // límites de la salida
} pid_t;

float pid_update(pid_t *pid, float setpoint, float measured, float dt) {
    float error = setpoint - measured;
    pid->integral += error * dt;
    float derivative = (error - pid->prev_error) / dt;
    pid->prev_error = error;

    float out = pid->kp * error
              + pid->ki * pid->integral
              + pid->kd * derivative;

    // Saturación + anti-windup: no dejes crecer la integral sin límite
    if (out > pid->out_max) { out = pid->out_max; pid->integral -= error * dt; }
    if (out < pid->out_min) { out = pid->out_min; pid->integral -= error * dt; }
    return out;
}

Els detalls que separen un PID de joguina d'un de professional són en allò que envolta aquesta fórmula: un dt constant i ben mesurat, la saturació de la sortida amb anti-windup (perquè la integral no es dispari quan l'actuador arriba al màxim), el filtratge del terme derivatiu i l'ús d'aritmètica adequada (entera o de coma fixa) en MCU sense unitat de coma flotant.

Com ajustar (tunejar) un PID

  • Comença només amb P: puja-la fins que el sistema respongui ràpid però just abans que comenci a oscil·lar.
  • Afegeix I a poc a poc per eliminar l'error permanent, sense passar-te (provoca sobreoscil·lació).
  • Fes servir D amb moderació per esmorteir, només si el soroll del sensor ho permet.
  • Mètodes com Ziegler-Nichols donen un punt de partida, però l'ajust fi gairebé sempre és empíric i depèn del teu maquinari real.

Errors comuns

  • Calcular el PID amb un dt variable (per exemple dins d'un loop() sense control de temps): els resultats es tornen impredictibles.
  • Oblidar l'anti-windup: el sistema respon amb un retard enorme després de saturar.
  • Aplicar la derivada directament sobre un senyal sorollós, cosa que fica vibracions a l'actuador.
  • Voler resoldre-ho tot amb PID quan el procés té grans retards o no linealitats: de vegades cal una altra estratègia.

Conclusió

Un control PID ben implementat és la diferència entre un producte que se sent sòlid i un que vibra, s'escalfa o respon tard. El concepte és senzill, però fer-lo robust en un microcontrolador real —amb la seva temporització, el seu soroll i els límits de l'actuador— és una feina de firmware fi. A Regular Solids dissenyem i implementem llaços de control per a motors, temperatura, potència i moviment en productes encastats. Si tens un producte que necessita controlar alguna cosa amb precisió, explica'ns-ho.

Si votre produit doit maintenir une variable à une valeur cible —la vitesse d'un moteur, la température d'un four, la position d'un bras, la pression d'une pompe— tôt ou tard vous rencontrerez la régulation PID. C'est l'algorithme de régulation le plus utilisé dans l'industrie, et bien le comprendre fait toute la différence entre un produit qui répond en douceur et un autre qui oscille, dépasse la consigne ou réagit trop tard.

Qu'est-ce qu'un régulateur PID

Un régulateur PID (Proportionnel-Intégral-Dérivé) est un algorithme qui ajuste en continu une sortie pour qu'une mesure réelle se rapproche d'une valeur souhaitée, appelée référence ou consigne (setpoint). Il le fait en calculant l'erreur (la différence entre ce que vous voulez et ce que vous avez) et en la corrigeant à partir de trois composantes qui travaillent ensemble.

Consigne Σ + erreur e(t) Régulateur P · I · D u(t) Procédé / Système sortie y(t) Capteur
Boucle de régulation en boucle fermée : le capteur mesure la sortie réelle, on la compare à la consigne et le PID corrige l'erreur.

Les trois composantes : P, I et D

  • Proportionnelle (P) : réagit à l'erreur actuelle. Plus vous êtes loin de la cible, plus elle corrige fort. Elle augmente la vitesse de réponse, mais à elle seule elle laisse une petite erreur permanente et, si elle est trop élevée, provoque des oscillations.
  • Intégrale (I) : accumule l'erreur passée. C'est elle qui élimine cette erreur permanente : tant qu'il reste un écart, elle continue de pousser jusqu'à atteindre exactement la valeur. En contrepartie, si l'on exagère, elle ralentit et peut provoquer un dépassement (overshoot).
  • Dérivée (D) : anticipe l'erreur future en observant la vitesse à laquelle elle change. Elle agit comme un frein qui adoucit la réponse et réduit le dépassement, mais elle amplifie le bruit du capteur, il faut donc l'utiliser avec précaution.

La sortie du régulateur est la somme des trois : u(t) = Kp·e + Ki·∫e·dt + Kd·de/dt. Régler les gains Kp, Ki et Kd est ce qui définit le caractère du système.

Un exemple simple : la vitesse d'un moteur

Imaginez un moteur qui doit tourner à 1 000 tr/min. Vous mesurez les tr/min réels avec un encodeur, vous les soustrayez aux 1 000 souhaités et vous obtenez l'erreur. Le PID convertit cette erreur en un signal PWM qui alimente le moteur : s'il va lentement, il augmente le PWM ; s'il dépasse, il le baisse. L'encodeur mesure à nouveau et le cycle se répète des dizaines ou des centaines de fois par seconde. Le résultat est un moteur qui maintient sa vitesse même quand la charge change —exactement ce que fait le régulateur de vitesse d'une voiture dans une côte—.

Comment l'implémenter dans le firmware

Sur un microcontrôleur, le PID est calculé dans une boucle à intervalle fixe (par exemple, toutes les 10 ms depuis une interruption de minuterie). Une implémentation discrète de base en C ressemble à ceci :

typedef struct {
    float kp, ki, kd;
    float integral, prev_error;
    float out_min, out_max;   // límites de la salida
} pid_t;

float pid_update(pid_t *pid, float setpoint, float measured, float dt) {
    float error = setpoint - measured;
    pid->integral += error * dt;
    float derivative = (error - pid->prev_error) / dt;
    pid->prev_error = error;

    float out = pid->kp * error
              + pid->ki * pid->integral
              + pid->kd * derivative;

    // Saturación + anti-windup: no dejes crecer la integral sin límite
    if (out > pid->out_max) { out = pid->out_max; pid->integral -= error * dt; }
    if (out < pid->out_min) { out = pid->out_min; pid->integral -= error * dt; }
    return out;
}

Les détails qui séparent un PID jouet d'un PID professionnel se trouvent dans ce qui entoure cette formule : un dt constant et bien mesuré, la saturation de la sortie avec anti-windup (pour que l'intégrale ne s'emballe pas quand l'actionneur atteint sa limite), le filtrage du terme dérivé et l'utilisation d'une arithmétique appropriée (entière ou à virgule fixe) sur les MCU sans unité à virgule flottante.

Comment régler (tuner) un PID

  • Commencez avec P seul : augmentez-le jusqu'à ce que le système réponde rapidement mais juste avant qu'il ne commence à osciller.
  • Ajoutez I progressivement pour éliminer l'erreur permanente, sans exagérer (cela provoque un dépassement).
  • Utilisez D avec modération pour amortir, seulement si le bruit du capteur le permet.
  • Des méthodes comme Ziegler-Nichols donnent un point de départ, mais le réglage fin est presque toujours empirique et dépend de votre matériel réel.

Erreurs courantes

  • Calculer le PID avec un dt variable (par exemple à l'intérieur d'une loop() sans contrôle du temps) : les résultats deviennent imprévisibles.
  • Oublier l'anti-windup : le système répond avec un retard énorme après avoir saturé.
  • Appliquer la dérivée directement sur un signal bruité, ce qui injecte des vibrations dans l'actionneur.
  • Vouloir tout résoudre avec un PID quand le procédé a de grands retards ou des non-linéarités : il faut parfois une autre stratégie.

Conclusion

Un PID bien implémenté est la différence entre un produit qui inspire confiance et un autre qui vibre, surchauffe ou réagit tard. Le concept est simple, mais le rendre robuste sur un microcontrôleur réel —avec sa temporisation, son bruit et les limites de l'actionneur— est un travail de firmware fin. Chez Regular Solids, nous concevons et implémentons des boucles de régulation pour moteurs, température, puissance et mouvement dans des produits embarqués. Si vous avez un produit qui doit contrôler quelque chose avec précision, parlez-nous-en.