Controlador PID

Dependencies:   Debounced Pulse1 QEI RTC-DS1307 TextLCD_1 mbed

Fork of grafica_PID_android by Nicolás Villegas Echavarría

/media/uploads/seccastanova/whatsapp_image_2018-06-05_at_10.25.03_am.jpeg

Revision:
5:f39e8f190857
Parent:
4:82ac4b34c3d9
--- a/main.cpp	Sat Jun 03 01:07:49 2017 +0000
+++ b/main.cpp	Tue Jun 05 15:42:17 2018 +0000
@@ -1,255 +1,451 @@
 /*
- * Código por: Laura Álvila
- *             Daniela López
- *             Nicolás Villegas            
- */
- 
+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 "TextLCD.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
-QEI encoder (PTA13, PTD5, NC, 10);
+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 led1(LED1);
-DigitalOut led2(LED2);
-DigitalOut led3(LED3);
+DigitalOut red(LED1);
+DigitalOut green(LED2);
+DigitalOut blue(LED3);
 
-DigitalIn button3(PTC16); // Botón del encoder
-DigitalIn button4(PTC17); // Pulsador
+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 = 0, kpnum = 0 ,kdnum = 0, pos = 1;
+int spnum = 0, kinum = 15, kpnum = 50 ,kdnum = 3;
 int j,k; 
 long t_pid = 0, t_btn = 0;
 
-int main() {
+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){ 
     
-    // Se asigna baudrate y se configura el puerto serie de la USART
+    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();
     
-    
-    // Animación de bienvenida:
-    
-    for (int i = 3; i < 15; ++i) {
-        lcd.cls();
-        lcd.locate(0,0);
-        lcd.printf("**Control PID**");
-        wait_ms(1000/i);
-        
-        ++i;
-        lcd.cls();
-        lcd.locate(1,0);
-        lcd.printf("**Control PID**");
-        wait_ms(1000/i);
-        
-        ++i;
-        lcd.cls();
-        lcd.locate(1,1);
-        lcd.printf("**Control PID**");
-        wait_ms(1000/i);
-        
-        ++i;
-        lcd.cls();
-        lcd.locate(0,1);
-        lcd.printf("**Control PID**");
-        wait_ms(1000/i);
-    }
-
-init:
-    
+    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);
-      
-    lcd.locate(8,0);
-    lcd.printf("Ki=%d", kinum);
     
-    lcd.locate(0,1);
-    lcd.printf("Kd=%d", kdnum);
-    
-    lcd.locate(8,1);
-    lcd.printf("**PID**");
-    
-    lcd.locate(0,0);
-    lcd.printf("Kp=%d", kpnum);
-    
-    bool state = 1; // Esta variable determina si se están modificando las constantes del controlador o el Set-Point.
-    
-    while(true) {
-
-        diferencia=(encoder.getPulses() - cambio)*3;
-        cambio=encoder.getPulses();
-        
-        if (diferencia != 0 && state) {
-            switch (pos) {
-                case 1:
-                    kpnum += diferencia;
-                    
-                    if (kpnum >= 999)
-                        kpnum = 999;
-                    else if (kpnum < 0)
-                        kpnum = 0;
-                        
-                    lcd.locate(3,0);
-                    lcd.printf("    ");
-                    lcd.locate(3,0);
-                    lcd.printf("%d", kpnum);
-                    break;
-                case 2:
-                    kinum += diferencia;
-                    
-                    if (kinum >= 999)
-                        kinum = 999;
-                    else if (kinum < 0)
-                        kinum = 0;
-
-                    lcd.locate(11,0);
-                    lcd.printf("    ");
-                    lcd.locate(11,0);
-                    lcd.printf("%d", kinum);
-                    break;
-                case 3:
-                    kdnum += diferencia;
-                    
-                    if (kdnum >= 999)
-                        kdnum = 999;
-                    else if (kdnum < 0)
-                        kdnum = 0;
-
-                    lcd.locate(3,1);
-                    lcd.printf("    ");
-                    lcd.locate(3,1);
-                    lcd.printf("%d", kdnum);
-                    break;
-            }
-        }
-        
-        if (diferencia != 0 && !state) {
-            
-            spnum += diferencia;
-              
-            if (spnum >= 999) spnum = 999;
-            else if (spnum < 0) spnum = 0;
+    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;
                 
-            lcd.locate(10,0);
-            lcd.printf("   ");
-            lcd.locate(10,0);
-            lcd.printf("%d", spnum);
-        }
-            
-
-        if (!button3) { // Cambia la posición de ingreso de parámetros
-            led2 = !led2;
-            switch(pos++) {
-                case 3:
-                    pos = 1;
-                    lcd.locate(3,0);
-                    lcd.printf("%d", kpnum);
-                    break;
                 case 1:
-                    lcd.locate(11,0);
-                    lcd.printf("%d", kinum);
-                    break;
+                    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("%d", kdnum);
-                    break;
+                    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;
             }
-            wait(0.2);
-        }
-
-        if (!button4 && state) {
-            lcd.cls();
-            lcd.locate(8,1);
-            lcd.printf("**PID**");
+        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("Set-Point=");
-            lcd.locate(10,0);
-            lcd.printf("%d", spnum);
-            wait(0.2);
-            state = 0;
-        }
-        else if (!button4 && !state) {
-            wait(0.2);
-            break;
-        }
-        wait(0.1);        
-    }
-    
-
- // Transición
-    lcd.writeCommand(C4); // Escribimos un comando segun el manual del módulo LCD para quitar cursor bajo
-    lcd.cls();
-    lcd.locate(0,0); lcd.printf("y=");
-    lcd.locate(8,0); lcd.printf("e=");
-    lcd.locate(0,1); lcd.printf("r=");
-    lcd.locate(8,1); lcd.printf("u=");
-
-loop:   
+            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 > 10) {
-        
-        med = y.read()*999;
-        err = spnum - 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 = spnum;
-        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. 
-        lcd.locate(3,0);  lcd.printf("%3.0f ", med);
-        lcd.locate(3,1);  lcd.printf("%3d ", spnum);
-        lcd.locate(11,0); lcd.printf("%3.0f ", err);
-        lcd.locate(11,1); lcd.printf("%3.0f ", pid);
-
-        err_v = err;
-        o = pid/999;
-        u.write(o);
-        
-        t_pid = t.read_ms();
+            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;
+    
     }
-    else {
-        
-        diferencia=(encoder.getPulses() - cambio)*6;  // Es posible cambiar el Set-Point cuando el controlador ya está funcionando. 
-        cambio=encoder.getPulses();
-        
-        if (diferencia != 0) {
-            spnum += diferencia;
-            if (spnum >= 999) spnum = 999;
-            else if (spnum < 0) spnum = 0;
-        }
-            
     }
-    
-    if (!button4) { // Si se presiona el pulsador se vuelve al menú inicial para configurar de nuevo el controlador.
-        u.write(0);
-        med = 0;
-        err = 0;
-        pid = 0;
-        
-        goto init;
-    }
-    else
-        goto loop;
-        
-}
\ No newline at end of file
+}
+
+