PID que funciona con encoder y tiene autotunning.
Dependencies: QEI TextLCD mbed
Fork of TAREA_4_PROCESADORES by
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 } } } } } } }