![](/media/cache/group/default_image.jpg.50x50_q85.jpg)
PID for ramp temperature control using LM35 temperature sensor and two actuators, a bulb and a ventilator.
Dependencies: DebouncedIn QEI TextLCD_encoder mbed
Fork of PID_Encoder by
main.cpp
- Committer:
- Gregorio
- Date:
- 2014-06-12
- Revision:
- 5:ad88703dc6d3
- Parent:
- 4:d42fe3777735
File content as of revision 5:ad88703dc6d3:
#include "mbed.h" #include "DebouncedIn.h" #include "TextLCD.h" #include "QEI.h" TextLCD lcd(PTB10, PTB11, PTE2, PTE3, PTE4, PTE5); // rs, e, d4-d7 entradas del LCD QEI wheel (PTD5, PTD0, NC, 100); // entradas para el ENCODER AnalogIn LM(PTB1); // temperatura leida por un LM35 PwmOut bomb(PTD4); //salida para activar un bombillo PwmOut vent(PTA12); //salida para activar un ventilador DigitalOut led3(LED3); // Led para indicar que los botones se presionan DebouncedIn button3(PTC16); //boton 3 es el pulsador del ENCODER DebouncedIn button4(PTA13); // boton 4 es para la configuración de las constantes del pid, de tiempo de rampa y de temperatura del horno //codigos movimiento del curzor LCD int C2=0x18; // desplaza izquierda int C3=0x1A; // desplaza derecha int C4=0x0C; // quito cursor bajo int C1=0x0F; // solo muestra el curzor //definicion de varibles int i=1; // i controla cambio de "modo" del boton 4. i=1 -> (constantes PID), i=2 -> (Tiempo y temperatura) int j=1; //j controla cambio de posiciones para cambiar variable (con el boton del ENCODER) int kp=40, ki=40, kd=40, sp; //constantes del pid y del setpoint int t1=60, t2=60, t3=60; //tiempos de la rapmpa de subida, temperatura estable y tiempo de bajada t1=t2=t3 [segundos] int temp=45; // temp:temperatura final a la que llega el horno[ºC] float ta, avg, a[10]; // ta: temperatura ambiente que se lee con el LM35, antes de empezar control, avg, promedio de temperatura para minimizar error float yr, ap, ai, ad, err, med, err_v, cycle, pid; // float dt1, dt2, dt3,c=0; // variables para ciclos de control en tiempos t1, t2 y t3 int b=0; // Se usa para imprimir datos en la LCD float pidn; Timer t; // Inicia el código int main() { while(1) { if(i==1) { lcd.cls(); lcd.writeCommand(C1);//escribimos un comando segun el manual del modulo LCD lcd.locate(0,0); lcd.printf(" PID"); 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); led3 =1; if (button3.falling()) { //INCREMENTA POSICION DEL MENU CON BOTON 3 (Switche encoder) led3 =!led3; } if (j==1) { kp=kp+wheel.getPulses(); wheel.reset(); if (kp>999) { kp=999; } if (kp<0) { kp=0; } lcd.locate(11,0); lcd.printf(" "); lcd.locate(11,0); lcd.printf("%d",kp); wait(0.2); if(button3.falling()) { j=2; led3=0; wait(0.3); wheel.reset(); } } if (j==2) { ki=ki+wheel.getPulses(); wheel.reset(); if (ki>999) { ki=999; } if (ki<0) { ki=0; } lcd.locate(3,1); lcd.printf(" "); lcd.locate(3,1); lcd.printf("%d",ki); wait(0.2); if(button3.falling()) { j=3; led3=0; wait(0.3); wheel.reset(); } } if (j==3) { kd=kd+wheel.getPulses(); wheel.reset(); if (kd>999) { kd=999; } if (kd<0) { kd=0; } lcd.locate(11,1); lcd.printf(" "); lcd.locate(11,1); lcd.printf("%d",kd); wait(0.2); if(button3.falling()) { j=1; led3=0; wait(0.3); wheel.reset(); } } if (j==4) { j=1; } if(button4.falling()) { i=2; j=0; } }//CIERRA EL MODO i=1 -> constantes PID if(i==2) { //INICIA EL MODO i=2 -> tiempos y temperatura lcd.cls(); lcd.writeCommand(C1);//escribimos un comando segun el manual del modulo LCD lcd.locate(0,0); lcd.printf("T1:%d",t1); lcd.locate(8,0); lcd.printf("T2:%d",t2); lcd.locate(0,1); lcd.printf("T3:%d",t3); lcd.locate(8,1); lcd.printf("Tm:%d",temp); led3 =1; if (button3.falling()) { //INCREMENTA POSICION DEL MENU CON BOTON 3 (Switche encoder) led3 =!led3; } if (j==0) { t1=t1+wheel.getPulses(); wheel.reset(); if (t1>5*60) { // Tiempos no mayores a 6 minutos t1=5*60; } if (t1<60) { t1=60; } lcd.locate(3,0); lcd.printf(" ",t1); lcd.locate(3,0); lcd.printf("%d",t1); wait(0.2); if(button3.falling()) { j=1; led3=0; wait(0.3); wheel.reset(); } } if (j==1) { t2=t2+wheel.getPulses(); wheel.reset(); if (t2>5*60) { t2=5*60; } if (t2<60) { t2=60; } lcd.locate(11,0); lcd.printf(" "); lcd.locate(11,0); lcd.printf("%d",t2); wait(0.2); if(button3.falling()) { j=2; led3=0; wait(0.3); wheel.reset(); } } if (j==2) { t3=t3+wheel.getPulses(); wheel.reset(); if (t3>5*60) { t3=5*60; } if (t3<60) { t3=60; } lcd.locate(3,1); lcd.printf(" "); lcd.locate(3,1); lcd.printf("%d",t3); wait(0.2); if(button3.falling()) { j=3; led3=0; wait(0.3); wheel.reset(); } } if (j==3) { temp=temp+wheel.getPulses(); wheel.reset(); if (temp>60) { temp=60; } if (temp<20) { temp=20; } lcd.locate(11,1); lcd.printf(" "); lcd.locate(11,1); lcd.printf("%d",temp); wait(0.2); if(button3.falling()) { j=0; led3=0; wait(0.3); wheel.reset(); } } if (j==4) { j=0; } if (button4.falling()) { break; } }//CIERRE MODO i=2 -> tiempo y temperatura }// Cierre del while(1) //%--------------------------------------------------------------------- lcd.writeCommand(C4);//escribimos un comando segun el manual del modulo LCD para quitar cursor bajo lcd.cls(); //borra la pantalla lcd.printf("Valores \nGuardados"); wait(1); avg=0; for(i=0; i<10; i++) { a[i]=LM.read(); wait(.001); } for(i=0; i<10; i++) { avg=avg+(a[i]/10); } ta=(avg*3.10143686*100); lcd.cls(); //borra la pantalla lcd.printf("T Ambiente:%.2f",ta); wait(2); // se imprimen los parches del control ***************************************** lcd.cls(); lcd.printf("Er:%.2f",err); lcd.locate(8,0); lcd.printf("Me:%.2f",med); lcd.locate(0,1); lcd.printf("dt:%.2f",dt1); lcd.locate(10,1); lcd.printf("t:%.0f",0); wait(1); // CICLO PARA CONTROL DE RAMPA ASCENDENTE (T1) b=0; t.start(); // Comienza el ciclo for para la primera parte del control(Rampa ascendente) for(dt1=ta; dt1<=temp; dt1+=(temp-ta)/t1) { avg=0; for(i=0; i<10; i++) { a[i]=LM.read(); wait(.001); } for(i=0; i<10; i++) { avg=avg+(a[i]/10); } med=(avg*3.10143686*100); //leer puerto analogo y asignar a med (*100 ya que LM35 da 10mV/ºC) err = (dt1-med); // Para activar la bombilla en el tiempo de ascenso if(err>=0) { vent=0; ap = kp*err; //calculo de la acción proporcional // se verifica que la accion integral no sea muy grande if(ai<100) { ai =(ki*err)+ai; //calculo de la integral del error } ad = kd*(err-err_v); //calculo de la accion derivativa pid = (ap+ai+ad); // se verifica que pid sea positivo ************************************** if(pid<=0) { pid=0; } // se verifica que pid sea menor o igual la valor maximo ***************** if(pid>=100) { pid=100; } err_v = err; //Normalizacion de la salida pidn=pid/100; // se envia el valor pid a puerto analogico de salida (D/A) ************** bomb.write(pidn); } // Para activar ventilador en el tiempo de ascenso if(err<0) { bomb=0; err=-1*err; ap = kp*err; if(ai<100) { ai =(ki*err)+ai; } ad = kd*(err-err_v); pid = (ap+ai+ad); if(pid<=0) { pid=0; } if(pid>=100) { pid=100; } err_v = err; pidn=pid/100; vent.write(pidn); } // se repite el ciclo lcd.cls(); lcd.locate(0,0); lcd.printf("Er:%.2f",err); lcd.locate(8,0); lcd.printf("Me:%.2f",med); lcd.locate(0,1); lcd.printf("dt:%.2f",dt1); lcd.locate(10,1); lcd.printf("t1:%.0f",t.read()); wait(1); } bomb=0; vent=0; // Comienza el segundo ciclo para la segunda parte del control (Temperatura estable) t.start(); while(t<=t2) { avg=0; for(i=0; i<10; i++) { a[i]=LM.read(); wait(.001); } for(i=0; i<10; i++) { avg=avg+(a[i]/10); } med=(avg*3.10143686*100); //leer puerto analogo y asignar a med (*100 ya que LM35 da 10mV/ºC) err = (temp-med); // Para activar la bombilla en el tiempo de ascenso if(err>=0) { vent=0; ap = kp*err; //calculo de la acción proporcional // se verifica que la accion integral no sea muy grande if(ai<100) { ai =(ki*err)+ai; //calculo de la integral del error } ad = kd*(err-err_v); //calculo de la accion derivativa pid = (ap+ai+ad); // se verifica que pid sea positivo ************************************** if(pid<=0) { pid=0; } // se verifica que pid sea menor o igual la valor maximo ***************** if(pid>=100) { pid=100; } err_v = err; //Normalizacion de la salida pidn=pid/100; // se envia el valor pid a puerto analogico de salida (D/A) ************** bomb.write(pidn); } // Para activar ventilador en el tiempo de ascenso if(err<0) { bomb=0; err=-1*err; ap = kp*err; if(ai<100) { ai =(ki*err)+ai; } ad = kd*(err-err_v); pid = (ap+ai+ad); if(pid<=0) { pid=0; } if(pid>=100) { pid=100; } err_v = err; //Normalizacion de la salida pidn=pid/100; // se envia el valor pid a puerto analogico de salida (D/A) ************** vent.write(pidn); } lcd.cls(); lcd.locate(0,0); lcd.printf("Er:%.2f",err); lcd.locate(8,0); lcd.printf("Me:%.2f",med); lcd.locate(0,1); lcd.printf("Tm:%.2d",temp); lcd.locate(10,1); lcd.printf("t2:%.0f",t.read()); wait(1); } bomb=0; vent=0; // Comienza el tercer ciclo para la ultima parte del control (Descenso de rampa) t.start(); for(dt3=temp; dt3>=ta; dt3-=((temp-ta)/t3)) { avg=0; for(i=0; i<10; i++) { a[i]=LM.read(); wait(.001); } for(i=0; i<10; i++) { avg=avg+(a[i]/10); } med=(avg*3.10143686*100);//leer puerto analogo y asignar a med (*100 ya que LM35 da 10mV/ºC) err = (med-dt3); if(err>=0) { bomb=0; ap = kp*err; //calculo de la acción proporcional // se verifica que la accion integral no sea muy grande if(ai<100) { ai =(ki*err)+ai; //calculo de la integral del error } ad = kd*(err-err_v); //calculo de la accion derivativa pid = (ap+ai+ad); // se verifica que pid sea positivo ************************************** if(pid<=0) { pid=0; } // se verifica que pid sea menor o igual la valor maximo ***************** if(pid>=100) { pid=100; } // se actualizan las variables ******************************************* err_v = err; lcd.cls(); lcd.locate(0,0); lcd.printf("Er:%.2f",err); lcd.locate(8,0); lcd.printf("Me:%.2f",med); lcd.locate(0,1); lcd.printf("dt:%.2f",dt3); lcd.locate(10,1); lcd.printf("t3:%.0f",t.read()); //Normalizacion de la salida pidn=pid/100; // se envia el valor pid a puerto analogico de salida (D/A) ************** vent.write(pidn); // se repite el ciclo wait(1); } if(err<0) { err=-1*err; vent=0; ap = kp*err; //calculo de la acción proporcional // se verifica que la accion integral no sea muy grande if(ai<100) { ai =(ki*err)+ai; //calculo de la integral del error } ad = kd*(err-err_v); //calculo de la accion derivativa pid = (ap+ai+ad); // se verifica que pid sea positivo ************************************** if(pid<=0) { pid=0; } // se verifica que pid sea menor o igual la valor maximo ***************** if(pid>=100) { pid=100; } // se actualizan las variables ******************************************* err_v = err; lcd.cls(); lcd.locate(0,0); lcd.printf("Er:%.2f",err); lcd.locate(8,0); lcd.printf("Me:%.2f",med); lcd.locate(0,1); lcd.printf("dt:%.2f",dt3); lcd.locate(10,1); lcd.printf("t3:%.0f",t.read()); //Normalizacion de la salida pidn=pid/100; // se envia el valor pid a puerto analogico de salida (D/A) ************** bomb.write(pidn); // se repite el ciclo wait(1); } } bomb=0; vent=0; lcd.cls(); lcd.printf("Control\nTreminado"); }