UDS Team / Mbed 2 deprecated Nucleo_UDS_controller_Alberto_version

Dependencies:   Menu PID_v2 PinDetect QEI TextLCD Thermistor mbed

Revision:
0:b6fd8ca8bfbf
Child:
1:219e882c32eb
diff -r 000000000000 -r b6fd8ca8bfbf main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Sep 30 14:42:56 2015 +0000
@@ -0,0 +1,335 @@
+#include "mbed.h"
+#include "TextLCD.h"
+#include "PID.h"
+#include "QEI.h"
+
+#define TPIT_MIN     70
+#define TPIT_MAX     250
+#define TMEAT_MIN    50
+#define TMEAT_MAX    120
+#define TPIT_FAIL    300
+#define TMEAT_FAIL   250
+#define MAX_HOURS    24
+ 
+/*
+
+ This FW implements a PID temperature controller specifically designed for Ugly Drum Smokers (UDS)
+ and uses a K-type termocouple as pit temperature sensors and a PWM-controlled fan to regulate the
+ airflow at the intake.
+ A second K-type termocouple is used to monitor the meat temperature, while a countdown timer takes care
+ of the cooking time.
+ The required HW consists of:
+ - 1x STM32 F411RE Nucleo board
+ - 1x 20x4 Text LCD
+ - 1x Quadrature rotary encoder
+ - 1x Pushbutton (if not embedded in the encoder)
+ - 2x MAX6675 modules
+ - 2x K-type termocouples (pit & meat)
+ - 1x Buzzer
+ - 1x 12V fan
+ - 1x N-MOS capable of driving the fan
+ - 1x fly-wheeling diode
+
+*/
+
+uint8_t Hrs=0, Min=0, Sec=0, warning=0, set_mode=1, timeout=0;
+float FanSpeed, Tpit, Tmeat, Tset, Talm;
+float Vpot;
+
+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     (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)
+
+DigitalOut  TC_CLK  (D8);       // D4=PB5 --> MAX6675 CLK (to both chips)
+//DigitalOut  TC_CS1  (D9);       // D5=PB4 --> MAX6675 CS (chip 1)
+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)
+
+DigitalOut  BUZZER  (A2);       // A2=PA4 --> self-oscillating buzzer
+PwmOut      ALM     (D9);
+InterruptIn Button  (D7);       // D7=PA8 <-- Hold/Set pushbutton
+
+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
+
+Ticker Sec_Beat;        // timer ticker
+Ticker LCD_Refresh;     // LCD refresh ticker
+
+
+// ------------------- Prototypes -----------------------
+
+void Button_Pressed(void);
+void Timer_tick(void);
+void Update_LCD(void);
+int MAX6675_GetTemp(int);
+
+
+// -------------------- Routines ------------------------
+
+void Button_Pressed() {
+    
+    set_mode++;
+    if(set_mode>3) set_mode = 0; 
+    Button.fall(NULL);
+    Wheel.reset();        
+}
+
+
+// -------------------------------------------------------------
+
+void Timer_tick() 
+{
+                     
+    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--;                
+                } 
+            }
+        }            
+    }
+     
+    Tmeat = (float)(MAX6675_GetTemp(0)/4); // read meat & pit temperature
+    Tpit = (float)(MAX6675_GetTemp(1)/4);  
+    
+    if(timeout||warning)    // toggle the buzzer
+        BUZZER=!BUZZER;
+               
+    return;
+}
+
+// -------------------------------------------------------------
+
+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; 
+    
+    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(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;
+    }
+    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  
+}
+
+
+// -------------------------------------------------------------
+
+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);
+
+  return(Temp);
+  
+}
+
+
+// -------------------------------------------------------------
+// -------------------------------------------------------------
+// -------------------------------------------------------------
+
+int main() {
+
+  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   
+    
+  Wheel.reset();            // reset quadrature encoder 
+    
+  MyLCD.cls();              // clear LCD
+
+  Sec_Beat.attach(&Timer_tick, 1);      // configure tickers
+  LCD_Refresh.attach(&Update_LCD, 0.2);
+    
+  myPID.setInputLimits(0, 300);     // set PID in/out ranges 
+  myPID.setOutputLimits(0, 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