Cómo hacer un PID con Arduino Deja un comentario

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 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:

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:

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

#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.

También te puede interesar

 

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

Enviar Whatsapp
Hola 👋
¿En qué podemos ayudarte?