PID que funciona con pulsadores y tiene autotunning.

Dependencies:   Debounced QEI TextLCD mbed

PID.CPP

Committer:
PROCESADORES_2017_2
Date:
2017-11-28
Revision:
0:2d05e443a44d

File content as of revision 0:2d05e443a44d:

#include "mbed.h"
#include "TextLCD.h"
#include "DebouncedIn.h"

TextLCD lcd(PTB8, PTB9,PTB10,PTB11,PTE2, PTE3);

AnalogIn Vin(PTC2);        
AnalogOut Vout(PTE30);     

DigitalOut led1(LED1);      //led de cambio de posición
DigitalOut led2(LED2);      //led incremento de parámetros
DigitalOut led3(LED3);      //led decremento de parámetros

DebouncedIn P1(PTC16);    //Pulsador que aumenta
DebouncedIn P2(PTC13);    //SET 
DebouncedIn P3(PTC12);    //Pulsador que disminuye
int t2;
int o2=0;
float t1;
int B;

float ko,Kp,Ki,Kd,kc,TC;
int AT=0;
int i=1;
int j=1;
int k=1;
int v6;
int q;
int q2;
char D[30];
float v2;
//------------------------------------------------------------------------------
int a, sp, kp, ki, kd, ciclo; // indice de la variable
float med, sp0, ap, err, ai, ad, pid, err_v;

   //Códigos LCD
int C1=0x0E;            // Muestra el cursor
// 0x18;                // desplazamiento izquierda
// 0x1A;                // desplazamiento derecha
int C4=0x0C;            // Quita el cursor


Timer t;

int p=1;
int main()
{
    led1=led2=led3=1;
    lcd.cls();          //limpio la pantalla
    lcd.locate(5,1);
    lcd.printf("BIENVENIDO");
    wait(1.5);
    lcd.cls();
    //lcd.writeCommand(int C1);          //Comando para mostrar el cursor en el LCD                   
    lcd.locate(0,0);               //Ubica e imprime nombre de las variables en la LCD
    lcd.printf("Sp=%d",sp);
    lcd.locate(8,0);
    lcd.printf("Kp=%d",kp);
    lcd.locate(0,1);
    lcd.printf("Ki=%d",ki);
    lcd.locate(8,1);
    lcd.printf("Kd=%d",kd);
    
    while(true){    if ((P1.rising())&&(P3.rising())){      
                                                AT=1;
                        if (AT==1){
                                                if(p==1){
                                                lcd.cls();          //limpio la pantalla
                                                lcd.locate(5,1);
                                                lcd.printf("AUTOTUNING");
                                                wait(1.5);
                                                lcd.cls();
                                                
                                                sp=2;  //Set point inicial
                                                p=2;   
                                                }
                                                if (p==2){
                                              for (Kp=0.5;Kp<2;Kp=Kp+0.1){
                                                
                                                if (j==1 && k==1 && v6==0){
                                                for (i=1;i<20;i++){
                                                            pid=999;
                                                            Vout=(pid/999); 
                                                            v2=(Vin.read())*3300;//la medicion es convertida a un valor en mV,siendo el máximo valor esperado 3300mV (3.3V)
                                                            float kp0;
                                                            sp0 = sp;
                                                            err = (sp0*1000-v2); //Estoy ingresando un valor en V, pero opero internamente en mV
                                                            kp0 = Kp;
                                                            ap = kp0*err;
                                                            pid = ap;
                                                            
                                                            if (pid>999){pid=999;}
                                                            if (pid<0){pid=0;}
                                                
                                                            Vout=(pid/999); 
                                                      //      lcd.locate(5,1);
                                                        //    lcd.printf("y %4.2f",v2/1000);
                                                          //   lcd.locate(0,0);
                                                          //  lcd.printf("i %d",i);
                                                               lcd.locate(5,1);
                                                               lcd.printf("Leyendo..");
                                                            D[i]=v2/1000;
                                                            
                                                            led1=0;
                                                            wait(1);
                                                            led1=1;
                                                            }
                                                            }
                                                                  lcd.cls();                       
                                                if (i==20 && k==1 && v6==0){
                                                
                                                for (j=1;j<20;j=j+2)    {
                                                    //lcd.locate(0,0);
                                                    //lcd.printf("j %d",j); 
                                                                                      
                                                            if (D[j]==D[j+2]){ 
                                                            led2=0;
                                                            q=q++;
                                                            lcd.locate(5,1);
                                                            lcd.printf("Operando..");
                                                            wait(1);
                                                                                }
                                                                        }
                                                                        
                                                                    }
                                                lcd.cls();
                                                
                                                if(j==21 && i==20 && k!=21 && v6==0){
                                                    for(k=1;k<20;k=k+2) {
                                                 //lcd.locate(0,0);
                                                   // lcd.printf("k %d",k);     
                                                    if (D[k+1]==D[k+3]){ 
                                                    led3=0;
                                                    led2=1;
                                                    q2=q2++;
                                                    lcd.locate(5,1);
                                                    lcd.printf("Analisis...");
                                                    wait(1);}
                                                    
                                                                    }
                                                                                                
                                                       }
                                                                                             
                                                        lcd.cls();
                                                
                                                 
                                                if (i==20 && j==21 && k==21 && q>8 && q2>8){
                                                    led2=0;
                                                    kc=Kp;
                                                    p=3;
                                                    v6=1;
                                                    lcd.locate(5,1);
                                                    lcd.printf("Terminado");
                                                    wait(1);
                                                    lcd.cls();
                                                    lcd.printf("KC: %4.2f",Kp);
                                                    wait(1);
                                                    //UTILIZO A ESTE KP COMO GANANCIA CRITICA
                                               
                                                    break;
                                                                }
                                                    if(i==20 && j>20 && k==21 && q<=8 && q2<=8){
                                                                        lcd.locate(5,1);
                                                                        lcd.printf("Terminado");
                                                                        wait(1);
                                                                        lcd.cls();
                                                                        lcd.printf("NO ES LA KC");
                                                                       wait(1);
                                                                       lcd.cls();
                                                                        i=1;
                                                                        j=1;
                                                                        k=1;
                                                                        q=0;
                                                                        q2=0;
                                                                        }
                                                                            }
                                                                                               
                                                }                                                               
                                             }
                                             if (v6==1){
                                                 TC=1;
                                                 Kp=0.59*kc;
                                                 Ki=1.18*kc*(1/TC);
                                                 Kd=0.074*kc*TC;
                                                    
                                                 lcd.cls();
                                                 lcd.printf("INICIA EL PID");
                                                 wait(2);
                                                               // se imprimen los parches del control  *****************************************
                                                
                                                   lcd.locate(0,0);
                                                   lcd.printf("E:%d");
                                                   lcd.locate(8,0);
                                                   lcd.printf("Y:%d");
                                                   lcd.locate(0,1);
                                                   lcd.printf("Sp:%d");
                                                   lcd.locate(8,1);
                                                lcd.printf("Co:%0.1f");
                                              // CICLO PRINCIPAL CONTROLADOR PID
                                                                                 
                                                                                 while(1) {
                                                                                   
                                                                             wait(0.001);
                                             //                                                                                                        
                                                                             v2 = (Vin.read()*3300);//la medicion es convertida a un valor en mV,siendo el máximo valor esperado 3300mV (3.3V)
                                                                             sp0 = sp;
                                                                             err = (sp0*1000-v2); //Estoy ingresando un valor en V, pero opero internamente en mV
                                                                             float kp0;
                                                                             kp0 = Kp;
                                                                             ap = kp0*err;
                                                                             float ki0;
                                                                             ki0 = Ki;        
                                                                             ai =  (ki0*err)+ai;     //calculo de la integral del error
                                                                             float kd0;
                                                                             kd0 =Kd;
                                                                             ad =  kd0*(err-err_v);  //calculo de la accion derivativa
                                                                             pid = (ap+ai+ad);
                                                                            // se verifica que pid sea menor o igual la valor maximo *****************
                                                                             if (pid > 999){
                                                                                   pid=999;
                                                                                  } // se verifica que pid sea positivo **************************************
                                                                                  if (pid < 0){
                                                                                  pid=0;
                                                                                  } 
                                                                                  // se verifica que la accion integral no sea muy grande
                                                                                   if (ai > 999){ai=1000;
                                                                                   } 
                                                                                  //           
                                                                                  Vout=(pid/999);                
                                                                                                        //Mostrar resultados PID
                                                                                  if(ciclo>700)  {         
                                                                                  lcd.locate(2,0);
                                                                                  lcd.printf("      "); 
                                                                                  lcd.locate(0,0);
                                                                                  lcd.printf("E:%4.2f",err/1000);
                                                                                  lcd.locate(10,0);
                                                                                  lcd.printf("      ");
                                                                                lcd.locate(8,0);
                                                                                  lcd.printf("Y:%4.2f",v2/1000);
                                                                                  lcd.locate(2,1);
                                                                                           lcd.printf("      ");
                                                                                        lcd.locate(0,1);
                                                                                       lcd.printf("Sp:%4.2f",sp0);
                                                                                        lcd.locate(10,1);
                                                                                   lcd.printf("      ");
                                                                                   lcd.locate(11,1);
                                                                                    lcd.printf(":%0.1f",pid*3.3/999);
                                                                                    ciclo=0;
                                                                                              }
                                                                                            else 
                                                                                               ciclo++;     
                                                                                               err_v = err;  //guarda el error 
                                                                                                }      //  Envía parámetro pid al puerto analogico de salida (D/A) y se repite el cicl                                                                                                            
                   }
                   }
                                                                                            
                                                                                                   
                                                                                                                                                                       
                     else{                                         
                    if (AT==0){
                                                
                    if (P2.rising()) {      //Cambia la posición del cursor  
                       
                       a++;
                       led1=0;
                       wait(0.15);     //enciende el led rojo cada vez que se oprime este botón
                       led1=1;      
                                    if (a>3){
                                    a = 0;
                                    }   
                                   switch (a){
                                   case 0:
                                   
                                   lcd.locate(2,0);
                                   lcd.printf("=");
                                   break;
                                   
                                   case 1:
                                   lcd.locate(10,0);
                                   lcd.printf("=");
                                   break;
               
                                   case 2:
                                   lcd.locate(2,1);
                                   lcd.printf("=");
                                   break;
                                   
                                   case 3:
                                   lcd.locate(10,1);
                                   lcd.printf("=");
                                   break;
                                   }
                            }
          
                            if  (P1.rising()) {      //Incrementa la variable      
                            led2=0;
                            wait(0.15);              //enciende el led verde cada vez que se oprime el botón de incremento
                            led2=1;
                            
                                        switch (a) {
                                        case 0:
                                        if (sp>3){
                                                    sp=3;}
                                        lcd.locate(2,0);        //Ubica el parámetro Set-point
                                        lcd.printf("=  ");
                                        lcd.locate(3,0);
                                        lcd.printf("%d", ++sp);
                                                
                                        break;
                           
                                        case 1:
                                        if (kp>999){
                                                    kp=999;}
                                        lcd.locate(10,0);       //Ubica el parámetro kp
                                        lcd.printf("=  ");
                                        lcd.locate(11,0);
                                        lcd.printf("%d", ++kp);
                                              
                                        break;
                           
                                        case 2:
                                        if (ki>999){ ki=999;}
                                        lcd.locate(2,1);        //Ubica el parámetro ki
                                        lcd.printf("=  ");
                                        lcd.locate(3,1);
                                        lcd.printf("%d", ++ki);
                                         
                                        break;
                                        
                                        case 3:
                                        if (kd>999){ kd=999;}
                                        lcd.locate(10,1);       //Ubica el parámetro kd
                                        lcd.printf("=  ");
                                        lcd.locate(11,1);
                                        lcd.printf("%d", ++kd);
                                          
                                        break;
                                }
               }
                              if   (P3.rising()) {      //Decrementa la variable      
                                     wait(0.1);
                                     led3=0;
                                     wait(0.15);             //enciende el led azul cada vez que se oprime este botón
                                     led3=1;
                                     
                                             switch (a) {
                                             case 0: 
                                             if (sp<0) {            //No se admite valores negativos
                                              sp=0;
                                              }                                                                                                                             
                                             lcd.locate(2,0);       //Ubica el parámetro Set-point
                                             lcd.printf("=    ");
                                             lcd.locate(3,0);
                                             lcd.printf("%d",sp--);
                                             break;
                                     
                                             case 1:
                                             if (kp<0) {            //No se admite valores negativos
                                             kp=0;
                                             }
                                             lcd.locate(10,0);      //Ubica el parámetro kp
                                             lcd.printf("=    ");
                                             lcd.locate(11,0);
                                             lcd.printf("%d",kp--);
                                             break;
                                               
                                             case 2:
                                             if (ki<0) {             //No se admite valores negativos
                                             ki=0;
                                             }
                                             lcd.locate(2,1);        //Ubica el parámetro ki 
                                             lcd.printf("=    ");
                                             lcd.locate(3,1);
                                             lcd.printf("%d",ki--);
                                             break;
                                       
                                             case 3:
                                             if (kd<0)  {            //No se admite valores negativos
                                             kd=0;
                                             }
                                             lcd.locate(10,1);       //Ubica el parámetro kd
                                             lcd.printf("=    ");
                                             lcd.locate(11,1);
                                             lcd.printf("%d",kd--);
                                             break;
                                                }
                                 }
                        //PARA GUARDAR LOS PARAMETROS SE PRESIONA EL PULSADOR SET DURANTE 5 SEGUNDOS
                        if (P2==1 && kp>0 && ki>0 && kd>0 )
                        {B=1;
                        t.start(); //empieza timer
                        t2=t.read(); //lee el timer y lo almacena en una variable entera t2
                                             
                            }
                                    if(t2==5 && P2==1){
                                        t.stop(); //para el timer
                                        B=0;
                                        lcd.cls();
                                         }
                             
                               if (t2==5 && B==0)
                               {      
                                  t2=0;
                                  lcd.printf("GUARDADOS!"); 
                                   wait(2);
                                   lcd.cls();
                                   lcd.printf("INICIA EL PID");
                                   wait(2);
                                  // se imprimen los parches del control
                                   lcd.cls();
                                         
                                   lcd.printf("E:%d");
                                   lcd.locate(8,0);
                                   lcd.printf("Y:%d");
                                   lcd.locate(0,1);
                                   lcd.printf("Sp:%d");
                                   lcd.locate(8,1);
                                   lcd.printf("Co:%0.1f");
                                   wait(1);
                                  
                                   // CICLO PRINCIPAL CONTROLADOR PID
                                 
                                   while(1) {
                                   
                                   wait(0.001);
                                   med = (Vin.read()*3300);//la medicion es convertida a un valor en mV,siendo el máximo valor esperado 3300mV (3.3V)
                                   sp0 = sp;
                                   err = (sp0*1000-med); //Estoy ingresando un valor en V, pero opero internamente en mV
                                   float kp0;
                                   kp0 = kp;
                                   ap = kp0*err;
                                   float ki0;
                                   ki0 = ki;      
                                   ai =  (ki0*err)+ai;     //calculo de la integral del error
                                   float kd0;
                                   kd0 = kd;
                                   ad =  kd0*(err-err_v);  //calculo de la accion derivativa
                                   pid = ap+ai+ad;
                                   
                                   
                                      // se verifica que pid sea menor o igual la valor maximo *****************
                                      if (pid > 999){
                                   pid=999;
                                   } 
                                   
                                   // se verifica que pid sea positivo **************************************
                                   if (pid < 0){
                                   pid=0;
                                   } 
                                         
                                   // se verifica que la accion integral no sea muy grande
                                   if (ai > 999){
                                   ai=1000;
                                   } 
                                             
                                   Vout=(pid/999);       
                                    //Mostrar resultados PID
                                      if(ciclo>700)  {         
                                       lcd.locate(2,0);
                                       lcd.printf("      "); 
                                       lcd.locate(0,0);
                                       lcd.printf("E=%2.1f",err/1000); //error
                                       lcd.locate(10,0);
                                       lcd.printf("      ");
                                       lcd.locate(8,0);
                                       lcd.printf("Y=%4.2f",med/1000); //Salida del circuito
                                       lcd.locate(2,1);
                                       lcd.printf("      ");
                                       lcd.locate(0,1);
                                       lcd.printf("Sp=%4.2f",sp0); //Set point
                                        lcd.locate(10,1);
                                        lcd.printf("   ");
                                        lcd.locate(10,1);
                                        lcd.printf("=%0.1f",pid*3.3/999); //Esfuerzo de control
                                       
                                       ciclo=0;
                                       }
                                       else 
                                       ciclo++;     
                                       err_v = err;  //guarda el error 
                                      }      //  Envía parámetro pid al puerto analogico de salida (D/A) y se repite el ciclo
                                  }    
                                                 
                                  }
                                  }     
                                }                                                                  
                                }