Cómo hacer un PID con Arduino

Tutorial de Control PID de Arduino

En los sistemas de control, un controlador corrige la salida de un sistema particular a una entrada deseada en presencia de errores y perturbaciones. El tipo más popular de controlador es PID, que es un acrónimo de Proportional, Integral and Derivative (Proporcional, Integral y Derivado). En este tutorial de control PID de Arduino, te mostraremos cómo puedes emplear este tipo de controlador en tu proyecto.

¿Qué es el PID?

Como se mencionó anteriormente, PID es la abreviatura en inglés de proporcional, integral y derivada. El nombre proviene de los métodos de cómo este controlador trata las perturbaciones en el sistema. Sin embargo, este tipo de controlador sólo se encuentra en los sistemas de retroalimentación. Sugerimos leer un material escrito específicamente para este tema, pero haremos todo lo posible para explicarlo aquí tan simple como se pueda.

Un sistema de retroalimentación es un sistema en el que parte de la salida se «retroalimenta» a la entrada. Por ejemplo, puedes tener un proyecto que controle el fuego en el horno. Abajo tenemos una ilustración simple:

Control de temperatura con PID

Deseas mantener la temperatura en el horno hasta un determinado punto de llegada. Un sensor instalado en el horno determina la temperatura en cualquier momento. Este sensor, en este caso, proporciona la retroalimentación como referencia sobre el aumento o disminución de la temperatura requerida. La diferencia entre el valor del sensor de realimentación y un punto de ajuste de temperatura es el error.

Control proporcional

El control proporcional se refiere a una revisión que es proporcional a la magnitud del error. Digamos que el controlador en nuestro ejemplo es una válvula electrónica para controlar el combustible al horno. Si el error es pequeño, la válvula liberará una pequeña cantidad de combustible para que el punto de ajuste y la retroalimentación coincidan. Si el error es grande, la válvula debe liberar más combustible.

Control integral

El control proporcional produce un desplazamiento en su corrección debido a las perturbaciones. El controlador Integral tiene la capacidad de eliminar este desplazamiento y volver a poner el error a cero. Dicho controlador produce un ajuste que se basa en el error acumulado a lo largo del tiempo. Sin un control integral, el sistema no puede hacer frente a las tendencias de los errores.

Usando nuestro ejemplo anterior, un desplazamiento puede estar presente cuando la válvula de combustible no volvió a su posición original cuando se incrementó y luego disminuyó su salida de combustible. El controlador integral detectará esto y girará la válvula de combustible a su posición original.

Control de Derivados

Finalmente, el control de Derivados se ocupa de la tasa de cambio del error. Si el control integral examina el historial del error, el control derivado predice el error. Básicamente, la cantidad de corrección se basará en la rapidez con la que cambia el error. Este tipo de controlador funciona mejor con errores dinámicos en los que los controladores proporcionales e integrales no pueden lidiar.

Digamos que la temperatura en el horno va de 130 °C a 140 °C contra un punto de ajuste de 120 °C en 2 segundos. Los controladores proporcionales e integrales responderán a la magnitud del error, pero le será difícil ponerse al día sobre la rapidez con la que ocurrió el error… El controlador de derivados puede tratar con esto porque ha estado observando la tasa de cambio del error desde el principio.

Un sistema de retroalimentación con un controlador PID:

sistema de retroalimentación con un controlador PID

Aquí la variable de entrada o punto de ajuste es r(t), la variable de salida es y(t), la variable controlada es u(t) y el error es e(t). Continuando con nuestro ejemplo de horno, r(t) sería la temperatura deseada e y(t) es la temperatura real; e(t) es la diferencia entre la temperatura deseada y la temperatura real; u(t) es la suma de las correcciones de los controladores P, I y D que se alimenta a la planta que es la válvula de combustible.

Ten en cuenta que un controlador PID no se puede utilizar fuera de la caja. La afinación debe hacerse para asegurar que se logre el rendimiento deseado. Esto se hace cambiando cuidadosamente las constantes K como se muestra en el diagrama de arriba. Estas constantes deben determinarse de antemano y modificarse en función de la respuesta real del sistema hasta que se alcancen los valores óptimos.

Implementación de PID en código

Para implementar un controlador PID en un código o un programa de Arduino, se deben conocer cinco parámetros: constantes proporcionales, integrales y derivadas, valor de entrada y valor de llegada.

El cálculo del PID debe estar dentro de una función de bucle. La primera parte de la función debería ser determinar el tiempo transcurrido. En Arduino, el tiempo actual puede ser determinado por milis() y el tiempo transcurrido es justo:

currentTime = millis();
elapsedTime = currentTime - previousTime;

A continuación, se debe determinar el error:

error = setPoint - input;

Recuerda que la integral del error es el error acumulativo en el tiempo:

cumError += error * elapsedTime;

La derivada del error es la tasa de cambio del error:

rateError = (error - lastError)/elapsedTime;

Por último, la salida calculada es:

output = Kp * error + Ki * cumError + Kd * rateError;

Aquí, el Kp, Ki y Kd son las constantes predeterminadas.

Finalmente, las variables deben ser anotadas para la siguiente iteración:

lastError = error;
previousTime = currentTime;

Intentemos un ejemplo más concreto. Imagínate una rueda unida a un motor. Queremos que la rueda permanezca en la posición indicada:

ejemplo PID rueda

Un codificador rotativo en la rueda da el ángulo en grados de la posición actual de la rueda. En la posición deseada de la rueda, el ángulo es cero.

Lo que queremos es que el motor gire cuando la rueda está fuera de posición. Además, el motor se controla a través de la modulación de ancho de pulso. Cuanto más amplio es el pulso, más lejos gira el motor.

A continuación, implementemos este sencillo sistema de control usando un Arduino. Aquí está el código:

//PID constants
double kp = 2
double ki = 5
double kd = 1

unsigned long currentTime, previousTime;
double elapsedTime;
double error;
double lastError;
double input, output, setPoint;
double cumError, rateError;

void setup(){}

void loop(){
input = analogRead(A0); //read from rotary encoder connected to A0
output = computePID(input);
delay(100);
analogWrite(3, output); //control the motor based on PID value

}

double computePID(double inp){
currentTime = millis(); //get current time
elapsedTime = (double)(currentTime - previousTime); //compute time elapsed from previous computation

error = Setpoint - inp; // determine error
cumError += error * elapsedTime; // compute integral
rateError = (error - lastError)/elapsedTime; // compute derivative

double out = kp*error + ki*cumError + kd*rateError; //PID output

lastError = error; //remember current error
previousTime = currentTime; //remember current time

return out; //have function return the PID output
}

En la función de bucle o loop, el codificador rotativo determina la posición actual de la rueda y su valor de salida se convierte en un parámetro para la función computePID(). Esta función devuelve un valor para controlar el motor utilizando PWM.

Librería PID de Arduino

Podemos simplificar aún más el uso de PID en proyectos de Arduino con la ayuda de la librería PID de Brett Beauregard. La librería sólo requiere que especifiques los valores de kd, ki, kp y setpoint y ya está listo.

Aquí está el código PID_Basic.ino que viene con la librería. Este código básicamente proporciona la misma salida que el código que proporcionamos arriba, pero mejor:

#include <PID_v1.h>

#define PIN_INPUT 0
#define PIN_OUTPUT 3

//Define Variables we'll be connecting to
double Setpoint, Input, Output;

//Specify the links and initial tuning parameters
double Kp=2, Ki=5, Kd=1;
PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);

void setup()
{
//initialize the variables we're linked to
Input = analogRead(PIN_INPUT);
Setpoint = 100;

//turn the PID on
myPID.SetMode(AUTOMATIC);
}

void loop()
{
Input = analogRead(PIN_INPUT);
myPID.Compute();
analogWrite(PIN_OUTPUT, Output);
}

Aquí se puede crear una clase PID y tener como parámetros las constantes de entrada, salida, consigna y k. Para calcular el PID, simplemente llame a la función Compute(). También contiene una función SetMode() que activa (AUTOMATIC) o desactiva (MANUAL) el PID. La lista completa de las funciones utilizadas por la biblioteca se encuentra aquí.

Hemos dicho que el código anterior es mejor que el que proporcioné porque trata de las limitaciones del PID que está más allá del alcance de este artículo.

Pin It on Pinterest

Shares