Qué es un control PID y cómo implementarlo en firmwareWhat a PID controller is and how to implement it in 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.
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
dtvariable (por ejemplo dentro de unloop()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.
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 aloop()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.