![](/media/cache/profiles/IMG-20170731-WA002223234124.jpg.50x50_q85.jpg)
Controlador PID
Dependencies: Debounced Pulse1 QEI RTC-DS1307 TextLCD_1 mbed
Fork of grafica_PID_android by
main.cpp
- Committer:
- seccastanova
- Date:
- 2018-06-05
- Revision:
- 5:f39e8f190857
- Parent:
- 4:82ac4b34c3d9
File content as of revision 5:f39e8f190857:
/* ESTE PROGRAMA SIMULA EL CONTROL DE UN HORNO DE REFLUJO CON UN PID, USANDO SALIDA ANALÓGICA O PWM (OPCION DISPONIBLE EN MENU). ADEMÁS SE ENVÍAN LOS DATOS POR BLUETOOTH A UNA APLICACIÓN EN ANDROID (DESARROLLADA EN APPINVENTOR) PARA SU VISUALIZACIÓN. ESTA TAREA FUE DESARROLLADA POR SEBASTIÁN CAMILO CASTAÑO VANEGAS Y CARLOS MAURICIO ALZATE TORRES PARA LA MATERIA DE PROCESADORES DE LA UNIVERSIDAD NACIONAL DE MEDELLÍN SEMESTRE I DEL AÑO 2018 */ #include "mbed.h" #include "DebouncedIn.h" #include "TextLCD.h" #include "QEI.h" #include "Rtc_Ds1307.h" #include "string.h" #include "Pulse1.h" Serial GSM(PTE0,PTE1); // Módulo Bluetooh TextLCD lcd(PTB10, PTB11, PTE2, PTE3, PTE4, PTE5); // rs, e, d4-d7 Rtc_Ds1307 rtc(PTC9, PTC8); //Reloj QEI wheel (PTA13, PTD5, NC, 10); Timer t; AnalogIn y(PTC2); // Entrada análoga: Salida del sistema AnalogOut u(PTE30); // Salida análoga: Señal de control PwmOut u2(PTE29); // Salida wn PWM: Señal de control DigitalOut rele(PTB8); // Activación de relé DigitalOut red(LED1); DigitalOut green(LED2); DigitalOut blue(LED3); DebouncedIn button3(PTC16); // Botón del encoder -> cambiar opciones dentro de los menu DebouncedIn button4(PTC17); // Pulsador -> cambiar de menu int C1=0x0F; int C2=0x18; int C3=0x1A; int C4=0x0C; int conta=0; int m=0; int cambio = 0, diferencia = 0; float pid, o, ai, ad, ap, med, err, setpoint; float err_v; int spnum = 0, kinum = 15, kpnum = 50 ,kdnum = 3; int j,k; long t_pid = 0, t_btn = 0; int c = 0; //consigna int min = 0; //minutos int seg = 0; //segundos int T1 = 120,T2 = 180,T3 = 240; //tiempos consigna int Tmax = 500; //temperatura maxima int TI = 25; //temperatura ambiente (Fija) int pos = 0; // posicion inicializada en cero int state = 0; // estado inicializado en cero int selsalida=0; //Salida Análoga:0 PWM:1 int salidaAn=0; int salidaPWM=0; int tiemp=0; // FUNCIONES ---------------------------------------------------------------------------------------------------- // Funcion para consigna void cons(int m, int n){ tiemp= 60*m+ n; //el tiempo a segundos if(tiemp <=T1){ c = ((Tmax-TI)*tiemp/T1)+TI; //Tramo 1: Rampa subida temperatura } else if(tiemp > T1 and tiemp <= T2){ c = Tmax; } else if(tiemp > T2 and tiemp <= T3){ c = ((TI - Tmax)*(tiemp-T2)/(T3-T2)) + Tmax; } else if(tiemp>T3){ c = TI; } } //Funcion para presiones de botones void buttpress(){ //Presion boton de encoder if (button3.falling()) { pos++; } if (button4.falling()) { state++; pos=0; conta=0; selsalida=0; rele=0; lcd.cls(); lcd.writeCommand(C1); } } // FUNCIÓN PRINCIPAL int main() { red=1; blue=1; green=1; rele=0; Rtc_Ds1307::Time_rtc tm = {}; //Estructura para el reloj rtc.getTime(tm); //lee el tiempo del DS1307 u2.period_ms(10); // Se asigna baudrate y se configura el puerto serie de la USART GSM.baud(9600); GSM.format(8,Serial::None,1); t.start(); lcd.cls(); lcd.locate(0,0); lcd.printf(" Control PID "); lcd.locate(0,1); lcd.printf("Horno de reflujo"); wait_ms(3000); lcd.cls(); lcd.writeCommand(C1); while(true){ switch(state%4){ //Menus case 0: //Menu 1: Configuracion controlador //Grafica titulos if(conta==0){ lcd.locate(0,0); lcd.printf(" Constantes PID "); wait_ms(2000); lcd.cls(); conta++; } lcd.locate(0,0); lcd.printf("Kp= %03d",kpnum); lcd.locate(8,0); lcd.printf("Ki= %03d",kinum); lcd.locate(0,1); lcd.printf("Kd= %03d",kdnum); switch(pos%3){ //Configuracion variables case 0: //Kp red=0; blue=1; green=1; m=0; m=wheel.getPulses(); if (m!=0) { kpnum+=m*3; if (kpnum >= 999) kpnum = 999; else if (kpnum < 0) kpnum = 0; wheel.reset(); m=0; } lcd.locate(4,0); lcd.printf("%03d", kpnum); buttpress(); //Verifica si se presiono el boton break; case 1: //Ki red=1; blue=1; green=0; m=0; m=wheel.getPulses(); if (m!=0) { kinum+=m*3; if (kinum >= 999) kinum = 999; else if (kinum < 0) kinum = 0; wheel.reset(); m=0; } lcd.locate(12,0); lcd.printf("%03d", kinum); buttpress(); //Verifica si se presiono el boton break; case 2: //Kd red=1; blue=0; green=1; m=0; m=wheel.getPulses(); if (m!=0) { kdnum+=m*3; if (kdnum >= 999) kdnum = 999; else if (kdnum < 0) kdnum = 0; wheel.reset(); m=0; } lcd.locate(4,1); lcd.printf("%03d", kdnum); buttpress(); //Verifica si se presiono el boton break; } break; case 1: //Menu 2: Configuracion referencia if(conta==0){ lcd.locate(0,0); lcd.printf(" Parametros del "); lcd.locate(0,1); lcd.printf(" Horno "); wait_ms(2000); lcd.cls(); conta++; } //Grafica titulos red=0; blue=0; green=0; lcd.locate(0,0); lcd.printf("Tmax="); lcd.locate(9,0); lcd.printf("T1="); lcd.locate(0,1); lcd.printf("T2="); lcd.locate(9,1); lcd.printf("T3="); //Grafica valores iniciales de variables lcd.locate(5,0); lcd.printf("%03d",Tmax); lcd.locate(12,0); lcd.printf("%04d",T1); lcd.locate(3,1); lcd.printf("%04d",T2); lcd.locate(12,1); lcd.printf("%04d",T3); switch(pos%4){ // Se mueve entre las variables case 0: m=0; m=wheel.getPulses(); if (m!=0) { Tmax+=m*10; if (Tmax >= 800) Tmax = 800; else if (Tmax < TI) Tmax = TI; wheel.reset(); m=0; } lcd.locate(5,0); lcd.printf("%03d", Tmax); buttpress(); break; case 1: m=0; m=wheel.getPulses(); if (m!=0) { T1+=m*10; if (T1 >= 1800) T1 = 1800; else if (T1 < 0) T1 = 0; wheel.reset(); m=0; } if (T2<T1)T2=T1; lcd.locate(12,0); lcd.printf("%4d", T1); buttpress(); break; case 2: m=0; m=wheel.getPulses(); if (m!=0) { T2+=m*10; if (T2 >= 1800) T2 = 1800; else if (T2 < T1) T2 = T1; wheel.reset(); m=0; } if (T3<T2)T3=T2; lcd.locate(3,1); lcd.printf("%4d", T2); buttpress(); break; case 3: m=0; m=wheel.getPulses(); if (m!=0) { T3+=m*10; if (T3 >= 1800) T3 = 1800; else if (T3 < T2) T3 = T2; wheel.reset(); m=0; } lcd.locate(12,1); lcd.printf("%4d", T3); buttpress(); break; } break; ////// ELECCIÓN DE SALIDA ///////////////////////////////////////////////////////////////////////////////////////////////////// case 2: if(conta==0){ lcd.locate(0,0); lcd.printf(" Seleccione el "); lcd.locate(0,1); lcd.printf(" tipo de salida "); wait(2); lcd.locate(0,0); lcd.printf("-> Analogica "); lcd.locate(0,1); lcd.printf("-- PWM "); conta++; } if(selsalida==0) //Salida Analógica { red=0; green=1; blue=1; salidaAn=1; salidaPWM=0; m=wheel.getPulses(); if(m!=0) { selsalida=1; m=0; wheel.reset(); lcd.locate(1,0); lcd.printf("- Analogica "); lcd.locate(1,1); lcd.printf("> PWM "); } } /////////////////// if(selsalida==1) //Salida PWM { red=1; green=1; blue=0; salidaAn=0; salidaPWM=1; m=wheel.getPulses(); if(m!=0) { selsalida=0; m=0; wheel.reset(); lcd.locate(1,0); lcd.printf("> Analogica "); lcd.locate(1,1); lcd.printf("- PWM "); } } if (button4.falling()) { state++; pos=0; conta=0; lcd.cls(); lcd.writeCommand(C1); } break; case 3: // Menu 3: Dinamica del sistema y visualizacion //control: rtc.getTime(tm); //READING THE RTC //Grafica titulos if(conta==0){ if (salidaAn==1){ red=0; green=1; blue=1; } if (salidaPWM==1){ red=1; green=1; blue=0; rele=1; } lcd.locate(0,0);lcd.printf(" Parametros "); lcd.locate(0,1);lcd.printf(" Guardados "); wait(1.5); lcd.locate(0,0);lcd.printf(" Inicia control "); lcd.locate(0,1);lcd.printf(" de reflujo "); wait(1.5); lcd.cls(); tm.min=0; tm.sec=0; conta++; rtc.setTime(tm,true,false); } min=tm.min; seg=tm.sec; cons(min,seg); lcd.locate(0,0); lcd.printf("y= %3.0f",med); lcd.locate(8,0); lcd.printf("e=%3.0f ",err); lcd.locate(0,1); lcd.printf("r= %03d",c); lcd.locate(8,1); lcd.printf("t=%02d:%02d ",tm.min,tm.sec); if (t.read_ms() - t_pid > 20) { cons(min,seg); med = y.read()*999; err = c - med; // Se calcula el error ap = kpnum*err*0.01f; // Se calcula la acción proporcional ai += kinum*err*0.01f; // Cálculo de la integral del error ad = kdnum*(err - err_v)*0.01f; // Cálculo de la acción derivativa pid = ap + ai + ad; if (pid <= 0) pid = 0; if (pid > 999) pid = 999; setpoint = c; GSM.printf("#%3.0f%3.0f&", med, setpoint); // Se envía una cadena de caracteres por el puerto serial. Se agregan identificadores #...& que denotan el comienzo y la terminación de la misma. // Esto se hace con el fin de evitar errores en la transmisión. Estos identificadores se usan en la aplicación de AppInventor. err_v = err; o = pid/999; if (salidaAn==1)u.write(o); if (salidaPWM==1)u2.write(o); t_pid = t.read_ms(); } buttpress(); break; } } }