PID digital de luminosidad con arduino

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



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

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

La siguiente figura muestra la respuesta del controlador a varios escalones.


Figura 6.  Respuesta del sistema en lazo cerrado.
Compartir:

No hay comentarios.:

Publicar un comentario

Donaciones

Suscribete

SÍGUENOS EN FACEBOOK

Posts Populares

Categorías

Post Recientes