PID que funciona con encoder y tiene autotunning.

Dependencies:   QEI TextLCD mbed

Fork of TAREA_4_PROCESADORES by john lopez

main.cpp

Committer:
PROCESADORES_2017_2
Date:
2017-11-28
Revision:
2:f854af43e0c2
Parent:
1:9ca362d07dd0

File content as of revision 2:f854af43e0c2:

#include "mbed.h"
#include "TextLCD.h"
#include "DebouncedIn.h"
#include "QEI.h"
 
AnalogIn Vin(PTC2);
AnalogOut Vout(PTE30);


TextLCD lcd(PTB8, PTB9,PTB10,PTB11,PTE2, PTE3); //Puertos LCD rs, e, d4, d5, d6, d7
QEI Encoder (PTA1, PTA2, NC, 624);               //Puertos de la tarjeta asignados para el Encoder
 
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

Timer t;
int B,t2,tim;
DebouncedIn bot1(PTC17);    //cambiar la posición 
    //salida de bucle
  
   //Códigos LCD
int C1=0x0E;                // Muestra el cursor
// 0x18;                // desplazamiento izquierda
// 0x1A;                // desplazamiento derecha
int C4=0x0C;
//Variables autotuning----------------------------------------------------------
int TC;
float kc;
float ko;
float v2;
int AT=0;
int i=1;
int j=1;
int k=1;
int q;
int q2;
char D[30];
int v6;

//------------------------------------------------------------------------------
int a, kp, ki, kd, sp, ciclo, valor, v; // indice de la variable
float  med, sp0, pid, ap, err, ai, ad,err_v;
Timer o;
 int o2;
int p=1;
int main() {
float Kp,Kd,Ki;
    t.reset();
    
    led1=led2=led3=1;
    lcd.printf("Control PID");
    wait(1.5);
    lcd.cls();
    
    lcd.writeCommand(C1);   //comando para mostrar el cursor en el LCD
                       
    lcd.locate(0,0);        // Ubica e imprime nombre de los parámetros en del PID en la pantalla LCD
    lcd.printf("Sp=");
    lcd.locate(8,0);
    lcd.printf("Kp=");
    lcd.locate(0,1);
    lcd.printf("Ki=");
    lcd.locate(8,1);
    lcd.printf("Kd=");
    
   
     //Inicio del ciclo
     
     while(1) {  if (bot1==0 && kp==0 && ki==0 && kd==0 && sp==0) 
                 {AT=1;      }
                 
                 if (AT==1){ 
                                                if(p==1){
                                                lcd.cls();       //limpio la pantalla  
                                                lcd.locate(5,1);
                                                lcd.printf("AUTOTUNING");
                                                wait(0.5);
                                                lcd.cls();
                                                p=2;
                                                Kp=0.5;
                                                sp=3;
                                                
                                                }
                                            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("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(8,0);
                                                            //lcd.printf("Q %d",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(0,1);
                                                    //lcd.printf("Q2 %d",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);
                                                    
                                                    break;
                                                                }
                                                    if(i==20 && j>20 && k==21 && q<=8 && q2<=8){
                                                                        lcd.locate(5,1);
                                                                        lcd.printf("Terminado");
                                                                        wait(1);
                                                                        lcd.cls();
                                                                        lcd.locate(5,1);
                                                                        lcd.printf("NO ES LA KC");
                                                                        wait(1);
                                                                        lcd.cls();
                                                                       
                                                                        i=1;
                                                                        j=1;
                                                                        k=1;
                                                                        q=0;
                                                                        q2=0;
                                                                        }
                                                                            }
                                                                                               
                                                }                                                               
                                             
                                             if (v6==1){
                                                 lcd.cls();
                                                 lcd.locate(5,1);
                                                 lcd.printf("Calculando..");
                                                 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 (bot1.falling()&&B==0 && kp==0 && ki==0 && kd==0) {            //----------------- Aumenta de posición el cursor a la primera línea de menu
                      
               
                led1=0;
                wait(.15); 
                led1=1;
                ++a;
                }
         
                        valor = Encoder.getPulses();    //------------- Asigna el valor de los pulsos del encoder a una variable llamada "valor"                                                
                       if(B==0 && t2==0){
                        switch(a) {
            
                        case 0:
                       
                        sp = sp + valor;                //------------- Asigna el valor del encoder al parámetro sp y tiene en cuenta el valor anterior
                        Encoder.reset();                //------------- Resetea el valor del encoder
                        if (sp<0){
                            sp=0;                       //------------- No se admite valores negativos
                            }
                        if (sp>3){                      //Limito el valor del Set Point;
                            sp=3;
                            }
                        
                        lcd.locate(2,0);                //------------- Ubica e imprime el parámetro "sp" en la pantalla LCD
                        lcd.printf("=    ",sp);
                        lcd.locate(3,0);
                        lcd.printf("%i",sp);
                        wait(0.15);
                        
                            if (bot1.falling() && sp>0 && a==0 &&B==0) {       //--------------Aumenta de posición el cursor a la segunda línea de menu
                         
                            a=1;
                            led1=0;
                            wait(.15); 
                            led1=1;
                            Encoder.reset();            //------------- Resetea el valor del encoder
                            }
                        break;                           
                            
                                case 1:
                                
                                kp = kp + valor;        //------------- Asigna el valor del encoder al parámetro kp y tiene en cuenta el valor anterior
                                Encoder.reset();        //------------- Resetea el valor del encoder
                                if (kp<0){
                                kp=0;                   //------------- No se admite valores negativos
                                }
                                if (kp>999){ kp=999;}  //Limito el valor de KP
                        
                                lcd.locate(10,0);       //------------- Ubica e imprime el parámetro "sp" en la pantalla LCD
                                lcd.printf("=    ",kp);
                                lcd.locate(11,0);
                                lcd.printf("%i",kp);                        
                                wait(0.15);
                                   
                                    if (bot1.falling()&& kp>0 && a==1 && B==0) { //--------------Aumenta de posición el cursor a la tercera línea de menu    
                                    
                                    
                                    
                                    a=2;
                                    led1=0;
                                    wait(.15); 
                                    led1=1;
                                    Encoder.reset();      //------------- Resetea el valor del encoder
                                    }
                                break; 
                        
                                        case 2:
                                        
                                        ki = ki + valor;  //------------- Asigna el valor del encoder al parámetro ki y tiene en cuenta el valor anterior
                                        Encoder.reset();  //------------- Resetea el valor del encoder
                                        if (ki<0){
                                        ki=0;             //------------- No se admite valores negativos
                                        }
                                        if (ki>999){ ki=999;}  //Limito el valor de KI
                                        lcd.locate(2,1);  //------------- Ubica e imprime el parámetro "sp" en la pantalla LCD
                                        lcd.printf("=    ",ki);
                                        lcd.locate(3,1);
                                        lcd.printf("%i",ki);                                            
                                        wait(0.15);
                                        
                                           if (bot1.falling()&&ki>0 && a==2 && B==0) { //--------------Aumenta de posición el cursor a la cuarta línea de menu         
                                                                                                                              
                                            a=3;
                                            led1=0;
                                            wait(.15); 
                                            led1=1;
                                            Encoder.reset();    //------------- Resetea el valor del encoder
                                            }
                                        break;
                        
                                                case 3:
                                                kd = kd + valor; //------------- Asigna el valor del encoder al parámetro kd y tiene en cuenta el valor anterior
                                                Encoder.reset(); //------------- Resetea el valor del encoder
                                                if (kd<0){
                                                kd=0;            //------------- No se admite valores negativos
                                                }
                                                if (kd>999){ kd=999;}   //Limito el valor de KD
                                                lcd.locate(10,1);//------------- Ubica e imprime el parámetro "kd" en la pantalla LCD
                                                lcd.printf("=    ",kd);
                                                lcd.locate(11,1);
                                                lcd.printf("%i",kd);
                                                wait(0.15);
                                                
                                                
                                                    if (bot1.falling()&&kd>0 &&a==3 && B==0) {  //--------------Aumenta de posición el cursor a la cuarta línea de menu    
                                                                                                       
                                                    
                                                    a=0;
                                                    led1=0;
                                                    wait(.15); 
                                                    led1=1;
                                                    Encoder.reset();       //------------- Resetea el valor del encoder
                                                    }  
                                                   break;                                              
                                                }
                                }            
                                //PARA GUARDAR LOS PARAMETROS SE PRESIONA EL PULSADOR DEEL ENCODER 5 SEG
                    if (bot1==0 && kp>0 && ki>0 && kd>0)
                                 { 
                                   t.start(); //inicio el timer
                                   t2=t.read();//leo el valor del timer y lo almaceno en una variable entera "t2"
                                   B=1;
                                   
                                                                                                                                                                                                                
                                                   if(t2==5){
                                                              t.stop(); //paro el timer
                                                              t.reset();//lo reseteo
                                                              led3=0;   //led indicador-- enciendo led azul
                                                              B=0;
                                                            lcd.cls();
                                                           }
                                                     
                                                   if (t2==5 && B==0)
                                                     {      
                                                      lcd.cls();                                              //borra la pantalla
                                                      lcd.printf("GUARDADOS!"); 
                                                      wait(2);
                                                      lcd.cls();
                                                      lcd.printf("INICIA EL PID");
                                                      wait(2);
                                                       lcd.cls();
                                                    //Se imprimen los parches de control 
                                                       lcd.printf("E=%d");   //Error
                                                       lcd.locate(8,0);  
                                                       lcd.printf("Y=%d");   //Salida
                                                       lcd.locate(0,1);
                                                       lcd.printf("Sp=%d");   //Set point
                                                       lcd.locate(8,1);
                                                       lcd.printf("Co=%3.0f"); //Esfuerzo de control
                                                       wait(1);
                                                                      
                                                                   
                                                  //CICLO PID        
                                                       
                                                 while (true){
                                                       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_v-err);  //calculo de la accion derivativa  
                                                       pid = (ap+ai+ad);
                                                    
                                                                                                                                                                  
                                                       // se verifica que pid sea positivo
                                                       if (pid < 0){
                                                       pid=0;}
                                                      // Se limita el valor del PID
                                                           if (pid > 999)
                                                    {   pid=999;    }
                                             
                                                       // 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",med/1000);
                                           lcd.locate(2,1);
                                           lcd.printf("      ");
                                           lcd.locate(0,1);
                                           lcd.printf("Sp=%4.2f",sp0);
                                           lcd.locate(11,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  
                                           
                                            //  se repite el ciclo
        
        }
        }
                                                  }     
                                          }    
                        }
                  }
         }