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

Files at this revision

API Documentation at this revision

Comitter:
seccastanova
Date:
Tue Jun 05 15:42:17 2018 +0000
Parent:
4:82ac4b34c3d9
Commit message:
Controlador PID para Horno de Reflujo

Changed in this revision

Debounced.lib Show annotated file Show diff for this revision Revisions of this file
Pulse1.lib Show annotated file Show diff for this revision Revisions of this file
RTC-DS1307.lib Show annotated file Show diff for this revision Revisions of this file
TextLCD.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Debounced.lib	Tue Jun 05 15:42:17 2018 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/WarwickRacing/code/Debounced/#8992c13bbb9b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Pulse1.lib	Tue Jun 05 15:42:17 2018 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/tony63/code/Pulse1/#48651f86a80c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RTC-DS1307.lib	Tue Jun 05 15:42:17 2018 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/users/leihen/code/RTC-DS1307/#5627b407e097
--- a/TextLCD.lib	Sat Jun 03 01:07:49 2017 +0000
+++ b/TextLCD.lib	Tue Jun 05 15:42:17 2018 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/avallejopo/code/TextLCD/#aba8ab3dde9d
+https://os.mbed.com/users/seccastanova/code/TextLCD_1/#2c6ef1b6851a
--- 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
+}
+
+