Cómo implementar un controlador PID en Arduino


Seguimos con la serie de entradas dedicadas a teoría de controladores viendo cómo implementar un control PID en un microprocesador como Arduino.

En entradas anteriores hemos visto una introducción a la teoría de control, presentado el controlador todo/nada con histéresis, el poderoso controlador PID, y visto cómo ajustar los parámetros de un controlador PID.

Ahora toca dejar la teoría, desempolvar el teclado, ver cómo se implementa un controlador PID en un microprocesador como Arduino. Afortunadamente, es bastante sencillo hacer un PID básico y, como veremos en la segunda parte, tenemos disponible una librería muy completa para que sea incluso más sencillo.

Un PID es un elemento esencial a la hora de abordar una gran cantidad de proyectos interesantes, como regular automáticamente el nivel de luz, mantener la temperatura, conseguir que un motor gire a velocidad constante, plataformas estabilizadoras, hacer que un robot avance recto o incluso robots que se mantienen en equilibrio sobre dos ruedas.

Anuncio:

Controlador PID a mano

Primero vamos a ver cómo implementar un controlador sencillo por nosotros mismos. En realidad, el código no es excesivamente complejo. Supongamos que nuestro controlador toma la entrada de la variable controlada en A0, y efectúa la salida mediante una señal PWM en el pin 3.

El código de un PID básico podría ser el siguiente

// Asignaciones pins
const int PIN_INPUT = A0;
const int PIN_OUTPUT = 3;

// Constantes del controlador
double Kp=2, Ki=5, Kd=1;

// variables externas del controlador
double Input, Output, Setpoint;
 
// variables internas del controlador
unsigned long currentTime, previousTime;
double elapsedTime;
double error, lastError, cumError, rateError;
 
void setup()
{
	Input = analogRead(PIN_INPUT);
	Setpoint = 100;
}    
 
void loop(){
	
	pidController.Compute();
	
	Input = analogRead(PIN_INPUT);			// leer una entrada del controlador
	Output = computePID(Input);		// calcular el controlador
	delay(100);
	analogWrite(PIN_OUTPUT, Output);			// escribir la salida del controlador
}
 
double computePID(double inp){     
        currentTime = millis();                					// obtener el tiempo actual
        elapsedTime = (double)(currentTime - previousTime);     // calcular el tiempo transcurrido
        
        error = Setpoint - Input;                               // determinar el error entre la consigna y la medición
        cumError += error * elapsedTime;                		// calcular la integral del error
        rateError = (error - lastError) / elapsedTime;   		// calcular la derivada del error
 
        double output = kp*error + ki*cumError + kd*rateError;     // calcular la salida del PID
 
        lastError = error;                                		// almacenar error anterior
        previousTime = currentTime;                       		// almacenar el tiempo anterior
 
        return output;
}

Como vemos no es demasiado difícil. Tenemos una función 'computePID()' que realiza todo el trabajo. En esta función calculamos el tiempo transcurrido entre llamadas, que necesitamos para calcular tanto la derivada como la integral del error.

A continuación, comparamos la entrada del controlador con la consigna para determinar el error y realizamos las 'pseduo' integrales y derivadas (su equivalente discreto). Finalmente, calculamos la respuesta del sistema mediante la fórmula del PID, y guardamos los valores para el siguiente ciclo.

¿No ha sido tan duro, verdad? Sin embargo, aunque es completamente funcional, nuestro controlador PID es bastante simple. Por tanto, tiene ciertas carencias ante situaciones que ocurren frecuentemente en la realidad.

Podríamos mejorar nuestro código, pero ya no iba a ser tan sencillo ni rápido hacerlo. Y lo mejor ¡no hace falta! Para nuestra alegría alguien ha hecho todo el trabajo por nosotros, como veremos en el siguiente apartado.

Controlador PID con librería

Afortunadamente tenemos disponible la librería Arduino PID desarrollada por Brett Beauregard. Una pequeña maravilla que contiene muchas mejoras respecto a un PID básico, que están detalladas en este enlace del autor.

Os recomiendo que leáis la documentación de la librería porque es toda una clase sobre controladores PID.

La librería incluye varios ejemplos sobre su uso, hasta dispone de funciones de auto tunning. Aquí tenéis un ejemplo sencillo que muestra cómo sería su uso en un proyecto, que es equivalente al ejemplo anterior mejorado con la librería.

#include <PID_v1.h>

// Asignaciones pins
const int PIN_INPUT = A0;
const int PIN_OUTPUT = 3;

// Constantes del controlador
double Kp=2, Ki=5, Kd=1;

// variables externas del controlador
double Input, Output, Setpoint;

PID pidController(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);
 
void setup()
{
	Input = analogRead(PIN_INPUT);
	Setpoint = 100;
	
	pidController.SetMode(AUTOMATIC);  	// encender el PID
}
 
void loop()
{
	Input = analogRead(PIN_INPUT);
	pidController.Compute();			// actualizar el PID
	analogWrite(PIN_OUTPUT, Output);
}

Hemos visto que resulta bastante sencillo implementar un controlador PID en un microprocesador como Arduino. Y es incluso más sencillo a la pequeña joya de librería Arduino PID. Así que no hay motivos para tener escusas o miedos a la hora de implementar un controlador PID en nuestros proyectos.

En las próximas entradas de la serie empezaremos a ver ejemplos prácticos de proyectos donde podemos implementar un control PID en Arduino. ¡Hasta pronto!

5 8 votes
Article Rating

Anuncio:

Previous Polly, una librería de patrones de resiliencia para .NET
Next Cómo emplear un ESP8266 o ESP32 como servidor de un API Rest con Json
3 Comments
oldest
newest
Inline Feedbacks
View all comments
Gabriel
1 year ago

Buenas Luis en primer lugar gracias por tus aportes son increíbles, te llevo siguiendo desde hace algunos años y la verdad me has solventado muchas dudas, gracias!
Y segundo creo que tiene una pequeña errata tu código.

double Input, Output, setPoint; entiendo que es SetPoint

Un saludo y sigue así!

Juan P
6 months ago
Reply to  Gabriel

Pues Supongo que si declara la variable de la misma manera no debe tener problema

Eva
9 months ago

Muchas gracias! He estudiado dos cursos de control en la universidad y todo y quedarme clara la notación teórica y matemática, a la hora de aplicarlo no lo acabo de tener muy claro!
Estoy deseando ver si continua la serie con ejemplos reales! Muchas gracias!