![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
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 } } } } }