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 Gustavo Ramirez

Revision:
5:ad88703dc6d3
Parent:
4:d42fe3777735
--- a/main.cpp	Sat May 24 15:05:40 2014 +0000
+++ b/main.cpp	Thu Jun 12 16:43:28 2014 +0000
@@ -1,248 +1,517 @@
 #include "mbed.h"
 #include "DebouncedIn.h"
 #include "TextLCD.h"
-#include "QEI.h" 
+#include "QEI.h"
 
-TextLCD lcd(PTB10, PTB11, PTE2, PTE3, PTE4, PTE5); // rs, e, d4-d7
-QEI wheel (PTD5, PTD0, NC, 100);
-AnalogIn y(PTB1);
-AnalogOut u(PTE30);
-DigitalOut led1(LED1);
-DigitalOut led2(LED2);
-DigitalOut led3(LED3);
-DebouncedIn button1(PTC12);
-DebouncedIn button2(PTC13);
-DebouncedIn button3(PTC16);
-DebouncedIn button4(PTC17);
+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
-      //18 para izquierda
-      //1A para derecha
-
-//int C1=0x0E; // solo muestra el curzor
+//codigos movimiento del curzor LCD
 int C2=0x18; // desplaza izquierda
 int C3=0x1A; // desplaza derecha
 int C4=0x0C; // quito cursor bajo
-int C1=0x0F;
+int C1=0x0F; // solo muestra el curzor
+
 
-int i; // indice de la variable
-int j; //variable controla cambio 4 posiciones
-int kp, ki, kd, sp;
-float yr, ap, ai, ad, err, med, err_v, cycle, pid; 
-int b=0; 
+//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;
 
-int main() {
-    lcd.cls();
-    lcd.writeCommand(C1);//escribimos un comando segun el manual del modulo LCD
-    lcd.locate(0,0);
-    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);
-          
+// Inicia el código
+int main()
+{
     while(1) {
-    
-              led3 =1;
-           if (button3.falling()) {   //INCREMENTA POSICION DEL MENU CON BOTON 3 (Switche encoder)
-              led3 =!led3;              
-               ++j;
-               }    
-                                                
-           if (j==0){      
-               sp=sp+wheel.getPulses();
-               wheel.reset();
-                 if (sp>999){
-                       sp=999;
-                            } 
-                 if (sp<0){
-                       sp=0;
-                          }   
-               lcd.locate(2,0);
-               lcd.printf("     ",sp);
-               lcd.locate(2,0);
-               lcd.printf("%d",sp);
-               wait(0.2);
-               
-               if(button3.falling()){
-                 j=1;
-                 led3=0;
-                 wait(0.3);
-                 wheel.reset();   
-                                    }   
-                   
-                     }
-              
-           if (j==1) {
-               kp=kp+wheel.getPulses();
-               wheel.reset();
-                 if (kp>999){
-                     kp=999;
-                          }              
-                 if (kp<0){
-                     kp=0;
-                          }   
-               lcd.locate(10,0);
-               lcd.printf("     ");
-               lcd.locate(10,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(2,1);
-               lcd.printf("     ");
-               lcd.locate(2,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(10,1);
-               lcd.printf("     ");
-               lcd.locate(10,1);
-               lcd.printf("%d",kd);
-               wait(0.2);
-               
-               if(button3.falling()){
-                 j=0;
-                 led3=0;
-                 wait(0.3);
-                 wheel.reset();
-                                    }
-                                            
-                       } 
-            
-           if (j==4) {
-               j=0;
-                     }                          
-                     
-           if (!button4){
-           break;        //sale del bucle si pisan suiche4
-                        }                  
-              }          //cierro 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("GUARDAMOS \nVALORES |m|"); 
-           wait(2);
-           
-           // se imprimen los parches del control  *****************************************
-           lcd.cls();
-           lcd.printf("Er%d",err);
-           lcd.locate(8,0);
-           lcd.printf("Me%d",med);
-           lcd.locate(0,1);
-           lcd.printf("Sp%d",sp);
-           lcd.locate(8,1);
-           lcd.printf("Co%d",pid);
-           wait(1); 
-           
-           
-           // CICLO PRINCIPAL CONTROLADOR PID
-           b=0;
-           while(1) {
-           med=1000*y.read();                   //leer puerto analogo y asignar a med
-           err = (sp-med);
-           ap = kp*err;
-           
-           // se verifica que la accion integral no sea muy grande
-           if(ai<100)
-           {
-              ai =(ki*err)+ai;    //calculo de la integral del error
-           }
-           //else{
-                //Dejo de sumar la accion integral
-             //  }
-                      
-           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>=1000){pid=1000;}
-                      
-           // se actualizan las variables *******************************************
-           err_v = err;         
-           
-           //se muestran las variables******************************************
-           
-           if (b==0)
-           {
-            t.start();
-            b=1;
-           }
-        if(t>=0.01)
-        {
-           wait(0.2);
-           lcd.locate(2,0);
-           lcd.printf("    ");
-           lcd.locate(2,0);
-           lcd.printf("%d",err);
-           lcd.locate(10,0);
-           lcd.printf("    ");
-           lcd.locate(10,0);
-           lcd.printf("%d",med);
-           lcd.locate(2,1);
-           lcd.printf("    ");
-           lcd.locate(2,1);
-           lcd.printf("%d",sp);
-           lcd.locate(10,1);
-           lcd.printf("    ");
-           lcd.locate(10,1);
-           lcd.printf("%d",pid);
-        }  
-           
-           //Normalizacion de la salida
-           pidn=pid/1000;
-           //  se envia el valor pid a puerto analogico de salida (D/A) **************
-           u.write(pidn);
-          
-           //  se repite el ciclo
-           wait(0.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);
         }
-        
\ No newline at end of file
+        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");
+}