Introducción
Este tutorial muestra cómo implementar un controlador PID digital de luminosidad con arduino. Cabe señalar que más de la mitad de los controladores industriales que se usan hoy en día utilizan
esquemas de control PID o PID modificado.
En la siguiente figura se muestra el diagrama de bloques del sistema en lazo cerrado.
Figura 1. Diagrama de bloques del sistema en lazo cerrado.
Donde Sp es el punto de ajuste
deseado, Pv es la variable de proceso medida, e es el error (Sp-Pv) y Cv es variable de
control.
El control PID implementado es de la forma estándar algunas veces llamado algoritmo ISA, o ideal.
Figura 2. Diagrama de bloques del control PID ISA .
La función de transferencia en el dominio Z para el controlador PID ISA digital esta dada por
La señal de control Cv es la suma de
tres términos: P (que es proporcional al error), I (que es
proporcional a la integral del error), y el término D (que es proporcional a la
derivada del error). Los parámetros del controlador son la ganancia
proporcional Kp, el tiempo integral Ti, el tiempo derivativo Td y el tiempo de muestreo T.
Para implementar el algoritmo de control en el arduino es necesario pasar la ecuación anterior a ecuaciones en diferencias, para esto se utiliza las siguientes propiedades de la transformada Z.
Aplicando las propiedades de la transformada Z se obtiene
Donde e(k) representa el error en el instante actual y e(k-1) el error en el instante anterior.
Hardware requerido
- 1 Arduino
- 1 Led blanco de 5mm
- 2 Resistencias de 10k ohm
- 1 Potenciómetro de 10k ohm
- 1 Protoboard
- Cable
Circuito
En la figura 3 se muestra el esquema de conexión. Para la fuente de luminosidad se utiliza un led ultrabrillante de 5 mm,
color blanco en serie con una resistencia de 10k ohm. El pin 6 se utiliza como salida de control (Cv) y para la lectura de la variable de proceso (Pv) se usa una LDR mediante un divisor de voltaje.
Para variar el punto de ajuste (Sp) se utiliza un potenciómetro de 10k ohm. Para un mayor rango de control colocar el circuito en una caja cerrada como la figura 4.
Para variar el punto de ajuste (Sp) se utiliza un potenciómetro de 10k ohm. Para un mayor rango de control colocar el circuito en una caja cerrada como la figura 4.
Figura 3. Esquema de conexión.
Código
Primero definimos nuestro rango de control aplicando el mínimo Cv (0 ciclo de trabajo PWM al 0%) y máximo Cv (255 ciclo de trabajo 100%) y leyendo el valor digital del sensor (0-1023) mediante el siguiente programa.
Rango_de_Control.ino
Rango_de_Control.ino
float sensorValue = 0; int PWM=0; char cadena[30]; byte posicion = 0; void setup() { Serial.begin(9600); } void loop() { if (Serial.available()) { memset(cadena, 0, sizeof(cadena)); while (Serial.available() > 0) { cadena[posicion] = Serial.read(); posicion++; delay(10); } posicion = 0; PWM = atoi(cadena); } sensorValue=analogRead(A0); analogWrite(6,PWM); Serial.print("sensorValue : "); Serial.print(sensorValue); Serial.print(" PWM : "); Serial.println(PWM); delay(1000); }
Ingresar el Cv mediante el monitor serial de Arduino.
Figura 4. Rango de control mínimo (0 PWM ~ 40 valor digital).
Figura 5. Rango de control máximo (255 PWM ~ 755 valor digital).
A continuación se implementa el algoritmo PID. Para mas detalles del código mira el vídeo.
Control_PID.ino
float Pv = 0; // variable de proceso medida (porcentaje luminosidad) float Sp= 0; // punto de ajuste deseado (porcentaje luminosidad) int Cv=0; // variable manipulada (MV) o variable de control (PWM) float error=0; //error actual float error_1=0; // error anterior float Kp=0.05; // ganancia proporcional float P=0.0; // término P float Ti=0.03; // tiempo integral float I=0.0; // término I float Td=0.0001; // tiempo derivativo float D=0.0; // término D int T=100; // tiempo de muestreo milisegundos // Variables para asegurar tiempo muestreo unsigned long pasado=0; unsigned long actual; void setup() { Serial.begin(9600); } void loop() { actual=millis(); // milisegundos desde que se inició el programa unsigned long dt=actual-pasado; if(dt>=T) { pasado=actual; Pv=promedio(100,0); // Escalamiento de Pv Pv=abs(map(Pv,5,880,0,100)); Sp=promedio(100,1); // Escalamiento de Pv Sp=map(Sp,0,1023,0,100);// Escalamiento de Sp error = Sp - Pv; // Cálculo de error P=Kp*error; // término P I=I+(Kp/Ti)*error*(T/1000.0); // término I D=D=(Kp*Td)*((error-error_1)/(T/1000.0)); // término D error_1=error; // error anterior Cv=P+I+D; // Control PID Cv=constrain(Cv,0,255);// Restricción de acción de control analogWrite(6,Cv); Serial.print("Sp : "); Serial.print(Sp); Serial.print(" Pv : "); Serial.print(Pv); Serial.print(" Cv : "); Serial.println(Cv); } } float promedio(int numeroLecturas,int sensorPin) { float aux=0.0; for (int conta = 1; conta <=numeroLecturas ; conta++) { aux=aux+analogRead(sensorPin); // Escalamiento de Pv delayMicroseconds(10); } return (aux/numeroLecturas); }
Resultados
No hay comentarios.:
Publicar un comentario