UDS Team / Mbed 2 deprecated Nucleo_UDS_controller_Alberto_version

Dependencies:   Menu PID_v2 PinDetect QEI TextLCD Thermistor mbed

Revision:
1:219e882c32eb
Parent:
0:b6fd8ca8bfbf
Child:
3:884bfa90a09d
diff -r b6fd8ca8bfbf -r 219e882c32eb main.cpp
--- a/main.cpp	Wed Sep 30 14:42:56 2015 +0000
+++ b/main.cpp	Fri Nov 27 10:50:06 2015 +0000
@@ -2,15 +2,20 @@
 #include "TextLCD.h"
 #include "PID.h"
 #include "QEI.h"
+#include "Menu.h"
+#include "PinDetect.h"
+#include "Thermistor.h"
 
-#define TPIT_MIN     70
-#define TPIT_MAX     250
+#define TPIT_MIN     0.0
+#define TPIT_MAX     250.0
+#define TCOAL_MIN     0.0
+#define TCOAL_MAX     1000.0
 #define TMEAT_MIN    50
 #define TMEAT_MAX    120
-#define TPIT_FAIL    300
-#define TMEAT_FAIL   250
 #define MAX_HOURS    24
- 
+
+#define PULLUP_MEAT 10000.0
+
 /*
 
  This FW implements a PID temperature controller specifically designed for Ugly Drum Smokers (UDS)
@@ -32,34 +37,83 @@
 
 */
 
-uint8_t Hrs=0, Min=0, Sec=0, warning=0, set_mode=1, timeout=0;
-float FanSpeed, Tpit, Tmeat, Tset, Talm;
+int Hrs=0, Min=0, Sec=0, warning=0, timeout=0;
+int TimerRunning = 0;
+float FanSpeed, TcoalPID, Tcoal, Tpit, Tmeat, Tset;
+float Talm = 200.0;
+float TcoalSet, DfanSet;
 float Vpot;
+uint8_t req_LCD_update;
+
+uint8_t displayLine;
+
+int pitPidMode = 0;
+int coalPidMode = 0;
+
+char stringa[20];
+
+void UpdatePidMode(void);
+void SetCoalTemp(void);
+void SetFanDuty(void);
+void SetPIDK(void);
+void ResetSeconds(void);
+
+float coalKc = 0.1, coalTauI = 6.0;
+float pitKc = 0.1, pitTauI = 60.0;
+
+MenuNode MNhead(NULL,"Exit");
+MenuNode MNpid(&MNhead,"PID settings");
+//MenuNode MNpitap(&MNpid,"Pit Auto PID");
+MenuNode MNpitPidTarget(&MNhead,"Pit Target temp",(void *) &Tset,'f',NULL,1.0,TPIT_MIN,TPIT_MAX);
 
-DigitalOut  RLED    (PC_5);     // Pin 2 of CN10 (MORPHO connector, debug only)
-DigitalOut  YLED    (PC_6);     // Pin 4 of CN10 (MORPHO connector, debug only)
-DigitalOut  GLED    (PC_8);     // Pin 6 of CN10 (MORPHO connector, debug only)
+MenuNode MNpitPidMode(&MNpid,"Pit PID mode",(void *) &pitPidMode,'i',&UpdatePidMode,1.0,0.0,1.0,(char *[]){"Manual","Auto"});
+MenuNode MNcoalPidMode(&MNpid,"Coal PID mode",(void *) &coalPidMode,'i',&UpdatePidMode,1.0,0.0,1.0,(char *[]){"Manual","Auto"});
+
+MenuNode MNpitPidOutput(&MNpid,"Coal Temp (man)",(void *) &TcoalSet,'f',&SetCoalTemp,5.0,TCOAL_MIN,TCOAL_MAX);
+MenuNode MNcoalPidOutput(&MNpid,"Fan Speed (man)",(void *) &DfanSet,'f',&SetFanDuty,0.05,0.0,1.0);
+MenuNode MNcoalKc(&MNpid,"Coal Kc",(void *) &coalKc,'e',&SetPIDK,1.25,0.0001,100.0);
+MenuNode MNcoalTauI(&MNpid,"Coal TauI",(void *) &coalTauI,'e',&SetPIDK,1.25,1.0,1000.0);
+MenuNode MNpitKc(&MNpid,"Pit Kc",(void *) &pitKc,'e',&SetPIDK,1.25,0.0001,100.0);
+MenuNode MNpitTauI(&MNpid,"Pit TauI",(void *) &pitTauI,'e',&SetPIDK,1.25,1.0,10000.0);
+
+MenuNode MNtmr(&MNhead,"Timer settings");
+MenuNode MNtmrRun(&MNtmr,"Timer mode",(void *) &TimerRunning,'i',NULL,1.0,0.0,2.0,(char *[]){"Stop","Countdown", "Timer"});
+MenuNode MNtmrHrs(&MNtmr,"Hours",(void *) &Hrs,'i',&ResetSeconds,1.0,0.0,24.0);
+MenuNode MNtmrMin(&MNtmr,"Minutes",(void *) &Min,'i',&ResetSeconds,5.0,0.0,55.0);
 
-PwmOut      FAN     (D3);       // D3=PB3 --> PMW output (FAN control)
-AnalogIn    POT1    (A0);       // A0=PA0 <-- Pit setpoint potentiometer (debug only)
-AnalogIn    POT2    (A1);       // A1=PA1 <-- Meat alarm potentiometer (debug only)
+MenuNode MNtalm(&MNhead,"Meat Target temperature", &Talm,'f', NULL, 1.0, 30.0, 150.0);
+
+Menu MN(&MNhead);
+
+Thermistor MeatThermistor(25.0, 100000.0, 3950.0);
+
 
-DigitalOut  TC_CLK  (D8);       // D4=PB5 --> MAX6675 CLK (to both chips)
-//DigitalOut  TC_CS1  (D9);       // D5=PB4 --> MAX6675 CS (chip 1)
+//DigitalOut  RLED    (PC_5);     // Pin 2 of CN10 (MORPHO connector, debug only)
+//DigitalOut  YLED    (PC_6);     // Pin 4 of CN10 (MORPHO connector, debug only)
+//DigitalOut  GLED    (PC_8);     // Pin 6 of CN10 (MORPHO connector, debug only)
+
+PwmOut      FAN     (D5);       // D3=PB3 --> PMW output (FAN control)
+
+DigitalOut  TC_CLK  (D4);       // D4=PB5 --> MAX6675 CLK (to both chips)
+
 DigitalOut  TC_CS1  (A5);       // A0=PC0 --> MAX6675 CS (chip 1)
 DigitalOut  TC_CS2  (D2);       // D2=PA10 --> MAX6675 CS (chip 2)
-DigitalIn   TC_SDO  (D4);       // D8=PA9 <-- MAX6675 SDO (from both chips)
+DigitalIn   TC_SDO  (D8);       // D8=PA9 <-- MAX6675 SDO (from both chips)
 
-DigitalOut  BUZZER  (A2);       // A2=PA4 --> self-oscillating buzzer
+//DigitalOut  BUZZER  (A2);       // A2=PA4 --> self-oscillating buzzer
 PwmOut      ALM     (D9);
-InterruptIn Button  (D7);       // D7=PA8 <-- Hold/Set pushbutton
+
+PinDetect Button  (D7);       // D7=PA8 <-- Hold/Set pushbutton
+
+AnalogIn MeatIn (A0);
 
-PID myPID(0.003, 60.0, 0.0, 0.5);   // Specify Kc, Ti, Td & refresh rate
-QEI Wheel(D5, D6, NC, 16);          // quadrature encoder
-TextLCD MyLCD(D15, D14, D13, D12, D11, D10, TextLCD::LCD20x4); //20x4 LCD connection
+PID pitPID(0.1, 60.0, 0.0, 1.0);   // Specify Kc, Ti, Td & refresh rate
+PID coalPID(0.1, 6.0, 0.0, 1.0);   // Specify Kc, Ti, Td & refresh rate
+QEI Wheel(D3, D6, NC, 16, QEI::X4_ENCODING);          // quadrature encoder
+TextLCD MyLCD(D15, D14, D13, D12, D11, D10, TextLCD::LCD16x2); //20x4 LCD connection
 
 Ticker Sec_Beat;        // timer ticker
-Ticker LCD_Refresh;     // LCD refresh ticker
+//Ticker decSecBeat;     // 1/10th sec beat
 
 
 // ------------------- Prototypes -----------------------
@@ -69,267 +123,356 @@
 void Update_LCD(void);
 int MAX6675_GetTemp(int);
 
+void ResetSeconds(void)
+{
+    Sec = 0;
+}
 
 // -------------------- Routines ------------------------
+void SetPIDK(void)
+{
+    pitPID.setTunings(pitKc, pitTauI, 0.0);
+    coalPID.setTunings(coalKc, coalTauI, 0.0);
+}
 
-void Button_Pressed() {
-    
-    set_mode++;
-    if(set_mode>3) set_mode = 0; 
-    Button.fall(NULL);
-    Wheel.reset();        
+void SetCoalTemp(void)
+{
+    if(!pitPID.isAuto())
+        pitPID.setOutput(TcoalSet);
+}
+
+void SetFanDuty(void)
+{
+    if(!coalPID.isAuto())
+        coalPID.setOutput(DfanSet);
 }
 
 
-// -------------------------------------------------------------
 
-void Timer_tick() 
+void Button_Pressed()
 {
-                     
-    if((Hrs==0)&&(Min==0)&&(Sec==0))
-        timeout = 1;
-    else 
-    {    
-        timeout = 0;
-        BUZZER = 0;
-        
-        if ((!set_mode)&&(!timeout)) 
-        {    
-            Sec--;
-            if((Hrs==0)&&(Min==0)&&(Sec==0)) 
-                timeout = 1;
-            else if((Sec==0)||(Sec>60))
-            {
-                Sec=59;
-                if(Min>0) 
-                    Min--;
-                else if (Hrs>0)
-                {
-                    Min=59;
-                    Hrs--;                
-                } 
-            }
-        }            
+    
+    if(!MN.isLeaf())
+        MN.descend();
+    else
+    {
+        if(MN.isSelect())
+            MN.setEdit();
+        else if(MN.isEdit())
+        {
+            MN.resetEdit();
+            MN.execFun();
+        }
     }
-     
-    Tmeat = (float)(MAX6675_GetTemp(0)/4); // read meat & pit temperature
-    Tpit = (float)(MAX6675_GetTemp(1)/4);  
+    
+    req_LCD_update = 1;    
+    Wheel.reset();
     
-    if(timeout||warning)    // toggle the buzzer
-        BUZZER=!BUZZER;
-               
-    return;
+}
+
+
+void UpdatePidMode(void)
+{
+    coalPID.setMode(coalPidMode);
+    pitPID.setMode(pitPidMode);
 }
 
 // -------------------------------------------------------------
 
-void Update_LCD(void) {
-    
-    
-    switch(set_mode)
-    {
-                  
-    case 0:
-          
-        MyLCD.locate(19,0);
-        MyLCD.printf(" ");
-        MyLCD.locate(19,1);
-        MyLCD.printf(" ");
-        MyLCD.locate(19,2);
-        MyLCD.printf(" ");                
-        
-    break;
-
-    case 1:    // set cooking time
-          
-        MyLCD.locate(19,0);
-        MyLCD.printf("*");
-        Min = Sec = 0;
-        Hrs = int(Wheel.getPulses());
-        if((Hrs>MAX_HOURS))
-        {  
-            Wheel.reset();
-            Hrs = MAX_HOURS;
-        }
-        
-    break; 
+void Timer_tick()
+{
+    float Rmeat;
     
-    case 2:     // set meat temperature alarm
-          
-        MyLCD.locate(19,1);
-        MyLCD.printf("*");
-        Talm = TMEAT_MIN + int(Wheel.getPulses());
-        if((Talm<TMEAT_MIN)||(Talm>TMEAT_MAX))
-        {  
-            Wheel.reset();
-            Talm=TMEAT_MIN;
-        }
-        
-    break;
-    
-    case 3:     // set pit target temperature
-          
-        MyLCD.locate(19,2);
-        MyLCD.printf("*");
-        Tset = TPIT_MIN + int(Wheel.getPulses());
-        if((Tset<TPIT_MIN)||(Tset>TPIT_MAX))
-        {  
-            Wheel.reset();
-            Tset=TPIT_MIN;
-        }
-        
-    break;
-
-    default:
-        set_mode = 0;   
-           
-    };
-                
-    //Tmeat = (float)(MAX6675_GetTemp(0)/4);
-    //Tpit = (float)(MAX6675_GetTemp(1)/4);
-    //Tmeat = TMEAT_MIN + POT1*(TMEAT_MAX-TMEAT_MIN)-5;   // debug only
-    //Tpit = 2+TPIT_MIN + POT2*(TPIT_MAX-TPIT_MIN);    // debug only        
-
-    //-------------------------------------------------
+    if((Hrs==0)&&(Min==0)&&(Sec==0) && (TimerRunning == 1))
+        timeout = 1;
+    else 
+    {
+        timeout = 0;
 
-    if(Tmeat>Talm)      // Meat is ready!
-        warning = 1;        
-    else
-        warning = 0;        
-        
-    //-------------------------------------------------
-    
-    if(warning||timeout) // in case of a warning or timeout
-    { 
-        MyLCD.locate(0,3);
-        MyLCD.printf(" ---- WARNING! ---- ");
-
-        //FAN.write(0);     // stop the fan (optional)
-    }
-    else // otherwise
-    {
-        BUZZER = 0;             // buzzer off
-        FAN.write(FanSpeed);    // update fan speed
-        MyLCD.locate(0,3);
-        MyLCD.printf(" FAN SPEED:         ");
-        MyLCD.locate(12,3);
-        MyLCD.printf("%2.0f%% ", FanSpeed*100);        
-    }         
-    
-    //-------------------------------------------------
-            
-    if(Tpit>300)    // if Tpit is too high
-    { 
-        MyLCD.locate(0,2);  
-        MyLCD.printf(" CHECK PIT PROBE!   ");
-        FAN.write(0);     // stop the fan
-        warning=1;
+        if (TimerRunning == 1) 
+        {
+            Sec--;
+            if((Hrs==0)&&(Min==0)&&(Sec==0))
+                timeout = 1;
+            else if((Sec<=0)||(Sec>60)) 
+            {
+                Sec=59; 
+                if(Min>0)
+                    Min--;
+                else if (Hrs>0) 
+                {
+                    Min=59;
+                    Hrs--;
+                }
+            }
+        }
+        else if ((TimerRunning == 2) ) 
+        {
+            Sec++;
+            if((Sec>=60)) 
+            {
+                Sec=0;
+                Min++; 
+                if(Min>=60)
+                {
+                    Min = 0;
+                    Hrs++;
+                }                                                  
+            }
+        }
     }
-    else // otherwise show pit temperature and setpoint
-    {
-        warning=0;
-        MyLCD.locate(0,2);  
-        MyLCD.printf(" TPIT=             ");
-        MyLCD.locate(8,2);  
-        MyLCD.printf("%2.0f ", Tpit);        
-        MyLCD.locate(13,2);  
-        MyLCD.printf("(%2.0f) ", Tset);        
-    }      
-               
- 
-    //-------------------------------------------------
- 
-    if(Tmeat>200)    // if Tmeat is too high
-    { 
-        MyLCD.locate(0,1);
-        MyLCD.printf(" CHECK MEAT PROBE!   ");
-        FAN.write(0);     // stop the fan
-        warning=1;
-    }
-    else // otherwise show meat temperature and alarm threshold 
-    {
-        warning=0;
-        MyLCD.locate(0,1);
-        MyLCD.printf(" TMEAT=            ");
-        MyLCD.locate(8,1);
-        MyLCD.printf("%2.0f ", Tmeat);        
-        MyLCD.locate(13,1);
-        MyLCD.printf("(%2.0f) ", Talm);        
-    }      
-   
-   
-    MyLCD.locate(0,0);
-    MyLCD.printf(" TIMER: %2d:%2d:%2d ", Hrs, Min, Sec);
-   
-    Button.fall(&Button_Pressed); // enable button interrupt  
+
+   Tcoal = (float)(MAX6675_GetTemp(0)/2); // read meat & pit temperature
+   Tpit = (float)(MAX6675_GetTemp(1)/2);
+    
+    pitPID.setProcessValue(Tpit);
+    TcoalPID = pitPID.compute();
+    coalPID.setSetPoint( TcoalPID );
+    
+    coalPID.setProcessValue(Tcoal);
+    FanSpeed = coalPID.compute();
+    
+    FAN.write(FanSpeed);
+    
+    if(MN.isHead())
+        req_LCD_update = 1;
+
+
+    Rmeat = MeatIn.read();        
+    Rmeat = (Rmeat * PULLUP_MEAT) / (1 - Rmeat);
+    
+    Tmeat = MeatThermistor.trans_R2T(Rmeat);
+    
+
+    if(Tmeat>Talm || timeout)      // Meat is ready!
+        warning = 1;
+    else
+        warning = 0;
+
+
+    return;
 }
 
 
 // -------------------------------------------------------------
+int saturate(int data, int min, int max)
+{
+    if(data > max)
+        return max;
+    else if (data < min)
+        return min;
+    else return data;
+}
 
+
+char * idleString(int n, char *dst)
+{
+    int tcoal_l, tpit_l, tmeat_l;   
+
+    switch(n)
+    {
+        
+        case 0:
+            sprintf(dst,"%02d:%02d:%02d Tgt %02dC",Hrs,Min,Sec,int(Talm));
+            break;
+        case 1:
+            tcoal_l = saturate(int(Tcoal),0,999);
+            tpit_l = saturate(int(Tpit),0,999);
+            tmeat_l = saturate(int(Tmeat),0,999);
+            sprintf(dst,"C%3dC P%3dC M%2dC",tcoal_l,tpit_l,tmeat_l);
+            break;
+        case 2:
+            sprintf(dst,"d%3d CP%4dC    ",int(FanSpeed * 100), int(TcoalPID));
+            break;
+        case 3:
+            sprintf(dst,"Ciao Mamma");
+            break;
+    }
+    
+    return dst;
+}
+
+
+void Update_LCD(void)
+{
+    
+
+    if(MN.isHead())
+    {
+              
+       MyLCD.locate(0,0);
+       MyLCD.printf(idleString(displayLine,stringa));
+       MyLCD.locate(0,1);
+       MyLCD.printf(idleString((displayLine+1)&0x03,stringa));
+       
+    }
+    else
+    {
+        MyLCD.locate(0,0);
+        MyLCD.printf("%-16s",MN.getText());
+        if(MN.isSelect())
+        {
+            MyLCD.locate(0,1);
+            MyLCD.printf("%-16s",MN.getNextText());
+        }
+        else
+        {
+            MyLCD.locate(0,1);
+            MyLCD.printf("%-16s",MN.getDataText(stringa));
+        }
+    }
+
+
+    //Button.fall(&Button_Pressed);
+    
+#if 0
+
+
+if(warning||timeout) // in case of a warning or timeout
+{
+    MyLCD.locate(0,3);
+    MyLCD.printf(" ---- WARNING! ---- ");
+
+    //FAN.write(0);     // stop the fan (optional)
+} else // otherwise
+{
+    BUZZER = 0;             // buzzer off
+}
+
+#endif
+}
+
+// -------------------------------------------------------------
 int MAX6675_GetTemp(int chip)
 {
-  int Temp=0, mask=32768;
-  int i; 
-        
-  if(chip==0)
-    TC_CS1 = 0; // select chip #1
-  else
-    TC_CS2 = 0;  // select chip #2
-  wait_ms(1);
-  for(i=0; i<16; i++){   
-      
-   TC_CLK = 1;  // CLK high    
-   if(TC_SDO == 1 ) Temp = Temp | mask;  
-   wait_ms(1); 
-   TC_CLK = 0;  // CLK low 
-   wait_ms(1);
-   mask = mask/2;  
-  }     
-  wait_ms(1);
-  TC_CS1 = 1;  // Both CS high
-  TC_CS2 = 1;
-  
-  Temp=((Temp>>3)&0x0FFF);
+    int Temp=0, mask=32768;
+    int i;
+
+    if(chip==0)
+        TC_CS1 = 0; // select chip #1
+    else
+        TC_CS2 = 0;  // select chip #2
+    wait_ms(1);
+    for(i=0; i<16; i++) {
 
-  return(Temp);
-  
+        TC_CLK = 1;  // CLK high
+        if(TC_SDO == 1 ) Temp = Temp | mask;
+        wait_ms(1);
+        TC_CLK = 0;  // CLK low
+        wait_ms(1);
+        mask = mask/2;
+    }
+    wait_ms(1);
+    TC_CS1 = 1;  // Both CS high
+    TC_CS2 = 1;
+
+    Temp=((Temp>>3)&0x0FFF);
+
+    return(Temp);
+
 }
 
-
 // -------------------------------------------------------------
 // -------------------------------------------------------------
 // -------------------------------------------------------------
 
-int main() {
+int main()
+{
+
+    FAN.period_us(500);       // set initial fan PWM period and duty-cycle
+    FAN.write(0.1);
+
+    pitPID.setInputLimits(TPIT_MIN, TPIT_MAX);
+    pitPID.setOutputLimits(TCOAL_MIN, TCOAL_MAX);
+    
+    coalPID.setInputLimits(TCOAL_MIN, TCOAL_MAX);
+    coalPID.setOutputLimits(0.0, 1.0);
+    
+    ALM.period_us(500);      // set initial ALM period and duty-cycle
+    ALM.write(0.01);
 
-  FAN.period_us(100);       // set initial fan PWM period and duty-cycle
-  FAN.write(0.1);  
-  
-  ALM.period_us(2000);      // set initial ALM period and duty-cycle
-  ALM.write(0.2);   
-  
-  TC_SDO.mode(PullDown);    // enable pull-down on TC_SDO
-  Button.mode(PullUp);      // enable pushbutton pull-up   
+    TC_SDO.mode(PullDown);    // enable pull-down on TC_SDO
+    
+    Button.mode(PullUp);      // enable pushbutton pull-up
+    
+    Button.setSampleFrequency( 20000 );
+    
+    //Wheel.reset();            // reset quadrature encoder
+    Hrs = 2;
+    timeout = 0;
     
-  Wheel.reset();            // reset quadrature encoder 
-    
-  MyLCD.cls();              // clear LCD
+    MyLCD.cls();              // clear LCD
+
+    MyLCD.locate(0,0);
+    MyLCD.printf(__TIME__, Hrs, Min, Sec);
+    MyLCD.locate(1,1);
+    MyLCD.printf(__DATE__, Hrs, Min, Sec);
+
+
+    Sec_Beat.attach(&Timer_tick, 1);      // configure tickers    
+    //decSecBeat.attach(&Fast_tick, 1);      // configure tickers
+    FanSpeed = 0;
 
-  Sec_Beat.attach(&Timer_tick, 1);      // configure tickers
-  LCD_Refresh.attach(&Update_LCD, 0.2);
+    //Button.fall(&Button_Pressed);  // enable button interrupt
+    Button.attach_deasserted( &Button_Pressed );
     
-  myPID.setInputLimits(0, 300);     // set PID in/out ranges 
-  myPID.setOutputLimits(0, 1);     
+    while(1)
+    {
+        if(req_LCD_update) {
+            Update_LCD();
+            req_LCD_update = 0;
+        }
+        
+        if(warning)
+            ALM.write(0.01);
+        else
+            ALM.write(0.0);
+        
+        if(MN.isSelect())
+        {
+            if(Wheel.getPulses() > 0)
+            {
+                MN.next();
+                Wheel.reset();
+                req_LCD_update = 1;
+            }
+            else if(Wheel.getPulses() < 0)
+            {
+                MN.prev();
+                Wheel.reset();
+                req_LCD_update = 1;
+            }
+        }
+        else if(MN.isEdit())
+        {
+            if(Wheel.getPulses())
+            {
+                MN.edit(Wheel.getPulses());
+                Wheel.reset();
+                req_LCD_update = 1;
+            }
+        }
+        else if(MN.isIdle())
+        {
+            if(Wheel.getPulses() > 0)
+            {
+                displayLine++;
+                displayLine &= 0x3;
+                Wheel.reset();
+                req_LCD_update = 1;
+            }
+            else if(Wheel.getPulses() < 0)
+            {
+                displayLine--;
+                displayLine &= 0x3;
+                Wheel.reset();
+                req_LCD_update = 1;
+            }
+            
+        }
+    }
+    
 
-  Button.fall(&Button_Pressed);  // enable button interrupt
- 
-  while(1) {
-              
-    myPID.setSetPoint(Tset);            // update pit setpoint (PID reference)                 
-    myPID.setProcessValue(Tpit);        // update pit temperature (PID input)
-    FanSpeed = float(myPID.compute());  // calculate fan speed (PID output)
-          
-  } //while
-    
+
+
 } //main
\ No newline at end of file