Robert Abad / Mbed 2 deprecated microwave

Dependencies:   C12832_lcd LM75B mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include "mbed.h"
00002 
00003 #include "LM75B.h"
00004 #include "C12832_lcd.h"
00005 #include "keypad.h"
00006 
00007 // uncomment to allow DEBUG
00008 //#define DEBUG
00009 
00010 #define BUTTON_LEFT     (p13)
00011 #define BUTTON_RIGHT    (p16)
00012 #define BUTTON_START    (p15)
00013 #define BUTTON_STOP     (p12)
00014 #define BUTTON_DOOR     (p14)
00015 #define TEMP_SCL        (p27)
00016 #define TEMP_SDA        (p28)
00017 #define ALARM           (p26)
00018 
00019 #define DOOR_CLOSED     (0)
00020 #define DOOR_OPEN       (1)
00021 
00022 #define LED_OFF         (0)
00023 #define LED_ON          (1)
00024 
00025 #define TRUE            (1)
00026 #define FALSE           (0)
00027 
00028 #define MIN_COOKING_TIME        (0)     // secs
00029 #define MAX_COOKING_TIME        (180)
00030 #define COOKING_TIME_INCREMENT  (60)
00031 #define MAX_TICKER_TIME         (60)
00032 #define WDOG_TIME               (1)
00033 
00034 #define TEMP_INCREMENT          (10.0f) // degC
00035 
00036 typedef enum
00037 {
00038     STATUS_IDLE = 0,
00039     STATUS_COOKING,
00040     STATUS_DONE
00041 } etSTATUS;
00042 
00043 #ifdef DEBUG
00044   #define MAX_LATENCY           (10)        // msec
00045   #define ERROR_MICROWAVE_SM    (1L<<0)
00046   #define ERROR_LATENCY_DOOR    (1L<<1)
00047   #define ERROR_LATENCY_STOP    (1L<<2)
00048 #endif /* DEBUG */
00049 
00050 // forward declarations
00051 void init_microwave(void);
00052 void press_left(void);
00053 void press_right(void);
00054 void press_start(void);
00055 void press_stop(void);
00056 void press_door(void);
00057 void wdog_update(void);
00058 void update_output(void);
00059 
00060 void microwave_sm(void);    // microwave state machine
00061 
00062 // input peripherals
00063 Keypad keypad( BUTTON_LEFT, press_left,     // keypad
00064                BUTTON_RIGHT, press_right,
00065                BUTTON_START, press_start,
00066                BUTTON_STOP, press_stop,
00067                BUTTON_DOOR, press_door );
00068 LM75B tmp(TEMP_SDA,TEMP_SCL);              // temperature sensor
00069 
00070 
00071 // output peripherals
00072 C12832_LCD lcd;                     // LCD screen
00073 DigitalOut cooking_status(LED1);    // LED for cooking progress
00074 DigitalOut carousel_status(LED2);   // LED for carousel
00075 #ifdef DEBUG
00076   DigitalOut debugLED(LED4);        // general debug LED
00077 #endif /* DEBUG */
00078 PwmOut alarm(ALARM);                // alarm
00079 
00080 // Timers
00081 Ticker wdog;            // 1sec watchdog
00082 #ifdef DEBUG
00083   Timer latency_wdog;
00084 #endif /* DEBUG */
00085 
00086 // global status variables
00087 volatile signed short ssCookingTime;
00088 unsigned char ucDoorStatus = DOOR_CLOSED;
00089 float fTemp = 0.0f;
00090 etSTATUS opStatus;
00091 volatile unsigned char start_requested;
00092 volatile unsigned char stop_requested;
00093 volatile unsigned char temp_ticker;
00094 unsigned char reset_wdog;
00095 #ifdef DEBUG
00096   unsigned long ulErrorCode = 0UL;
00097 #endif /* DEBUG */
00098 
00099 /* Name: main()
00100  * Desc: entry point of application.  This will also invoke the microwave
00101  *       state machine and update output
00102  * Inputs: none
00103  * Outputs: none
00104  */
00105 int main()
00106 {
00107     unsigned int while_loop_counter = 0;
00108     
00109     init_microwave();
00110     
00111     while(1)
00112     {
00113         while_loop_counter++;
00114         
00115         microwave_sm(); // execute state machine
00116         
00117         // do not need to update LCD as often
00118         if ( while_loop_counter & 0x4000 )
00119         {
00120             update_output();
00121         }
00122     }
00123 }
00124 
00125 /* Name: init_microwave()
00126  * Desc: initializes the microwave state machine to STATUS_IDLE
00127  * Inputs: none
00128  * Outputs: none
00129  */
00130 void init_microwave(void)
00131 {
00132     ssCookingTime = 0L;
00133     cooking_status = LED_OFF;
00134     carousel_status = LED_OFF;
00135     opStatus = STATUS_IDLE;
00136     start_requested = FALSE;
00137     stop_requested = FALSE;
00138     reset_wdog = FALSE;
00139 }
00140 
00141 /* Name: press_left()
00142  * Desc: ISR callback function for left button.
00143  * Inputs: none
00144  * Outputs: none
00145  */
00146 void press_left(void)
00147 {
00148     if ( opStatus == STATUS_DONE )
00149     {
00150         return;
00151     }
00152     ssCookingTime += COOKING_TIME_INCREMENT;
00153     if ( ssCookingTime >= MAX_COOKING_TIME )
00154     {
00155         ssCookingTime = MAX_COOKING_TIME;
00156     }
00157 }
00158 
00159 /* Name: press_right()
00160  * Desc: ISR callback function for right button.
00161  * Inputs: none
00162  * Outputs: none
00163  */
00164 void press_right(void)
00165 {
00166     if ( opStatus != STATUS_IDLE )
00167     {
00168         return;
00169     }
00170     ssCookingTime -= COOKING_TIME_INCREMENT;
00171     if ( ssCookingTime <= MIN_COOKING_TIME )
00172     {
00173         ssCookingTime = MIN_COOKING_TIME;
00174     }
00175 }
00176 
00177 /* Name: press_start()
00178  * Desc: ISR callback function for start button.
00179  * Inputs: none
00180  * Outputs: none
00181  */
00182 void press_start(void)
00183 {
00184     if ( opStatus != STATUS_IDLE )
00185     {
00186         return;
00187     }
00188     
00189     if ( ssCookingTime && (ucDoorStatus == DOOR_CLOSED) )
00190     {
00191         start_requested = TRUE;
00192     }
00193 }
00194 
00195 /* Name: press_stop()
00196  * Desc: ISR callback function for stop button.
00197  * Inputs: none
00198  * Outputs: none
00199  */
00200 void press_stop(void)
00201 {
00202     if ( opStatus == STATUS_IDLE )
00203     {
00204         init_microwave();
00205         return;
00206     }
00207     else
00208     {
00209 #ifdef DEBUG
00210         latency_wdog.start();
00211 #endif
00212         stop_requested = TRUE;
00213     }
00214 }
00215 
00216 /* Name: press_door()
00217  * Desc: ISR callback function for door button.
00218  * Inputs: none
00219  * Outputs: none
00220  */
00221 void press_door(void)
00222 {
00223     ucDoorStatus = !ucDoorStatus;
00224     if ( opStatus == STATUS_COOKING )
00225     {
00226 #ifdef DEBUG
00227         latency_wdog.start();
00228 #endif
00229     }
00230 }
00231 
00232 /* Name: wdog_update()
00233  * Desc: callback function for watchdog timer.  This watchog updates the
00234  *       cooking time when the microwave is running (STATUS_COOKING).
00235  * Inputs: none
00236  * Outputs: none
00237  */
00238 void wdog_update(void)
00239 {
00240     if ( opStatus == STATUS_COOKING )
00241     {
00242         ssCookingTime--;
00243         
00244         // reset wdog
00245         if ( ssCookingTime )
00246         {
00247             reset_wdog = TRUE;
00248         }
00249         
00250         if ( temp_ticker )
00251         {
00252             temp_ticker--;
00253         }
00254     }
00255 }
00256 
00257 /* Name: microwave_sm()
00258  * Desc: This is the microwave state machine.  It processes all input and
00259  *       updates all state variables.
00260  * Inputs: none
00261  * Outputs: none
00262  */
00263 void microwave_sm(void)
00264 {
00265     switch ( opStatus )
00266     {
00267     case STATUS_IDLE:
00268         if ( ssCookingTime && !ucDoorStatus && start_requested )
00269         {
00270             fTemp = tmp.read();
00271             start_requested = FALSE;
00272             wdog.attach(wdog_update, 1);
00273             temp_ticker = (ssCookingTime > MAX_TICKER_TIME) ? MAX_TICKER_TIME : ssCookingTime;
00274             opStatus = STATUS_COOKING;
00275         }
00276         break;
00277     
00278     case STATUS_COOKING:
00279         if ( ucDoorStatus == DOOR_OPEN )
00280         {
00281 #ifdef DEBUG
00282             if (latency_wdog.read_ms() > MAX_LATENCY)
00283             {
00284                 ulErrorCode |= ERROR_LATENCY_DOOR;
00285             }
00286             latency_wdog.stop();
00287 #endif /* DEBUG */
00288             init_microwave();
00289         }
00290         else if ( stop_requested )
00291         {
00292 #ifdef DEBUG
00293             if (latency_wdog.read_ms() > MAX_LATENCY)
00294             {
00295                 ulErrorCode |= ERROR_LATENCY_STOP;
00296             }
00297             latency_wdog.stop();
00298 #endif /* DEBUG */
00299             init_microwave();
00300         }
00301         else
00302         {
00303             if ( !ssCookingTime )
00304             {
00305                 opStatus = STATUS_DONE;
00306             }
00307             if ( !temp_ticker )
00308             {
00309                 fTemp += TEMP_INCREMENT;
00310                 temp_ticker = (ssCookingTime > MAX_TICKER_TIME) ? MAX_TICKER_TIME : ssCookingTime;
00311             }
00312             if ( reset_wdog )
00313             {
00314                 wdog.attach(wdog_update, 1);
00315                 reset_wdog = FALSE;
00316             }
00317         }
00318         break;
00319         
00320     case STATUS_DONE:
00321         if ( ucDoorStatus == DOOR_OPEN || stop_requested )
00322         {
00323             init_microwave();
00324         }
00325         break;
00326         
00327     default:
00328 #ifdef DEBUG
00329         // something is wrong if we got here!
00330         ulErrorCode |= ERROR_MICROWAVE_SM;
00331 #endif /* DEBUG */        
00332         break;        
00333     }
00334 }
00335 
00336 /* Name: update_output()
00337  * Desc: Updates all output based on status variables.
00338  * Inputs: none
00339  * Outputs: none
00340  */
00341 void update_output(void)
00342 {
00343     static unsigned char toggle_alarm = 0;
00344     static unsigned char toggle_leds = 0;
00345     static etSTATUS previousState = (etSTATUS) 0xFF;
00346     
00347     // clear the screen only when we transition states to prevent flicker
00348     if ( previousState != opStatus )
00349     {
00350         lcd.cls();
00351         previousState = opStatus;
00352     }
00353     lcd.locate(0,0);
00354     lcd.printf("Cooking Time: %3d secs\n",ssCookingTime);
00355 
00356     switch ( opStatus )
00357     {
00358     case STATUS_IDLE:
00359         // alarm should be off in this state
00360         toggle_alarm = 0;
00361         alarm = 0.0;
00362         break;
00363         
00364     case STATUS_COOKING:
00365         // display temp
00366         lcd.locate(0,10);
00367         lcd.printf("Temp: %.2f degC\n", fTemp);
00368         
00369         // update LEDs
00370         toggle_leds++;
00371         if ( toggle_leds & 0x10 )
00372         {
00373             cooking_status = !cooking_status;
00374             carousel_status = !carousel_status;
00375         }
00376         
00377         // alarm should be off in this state
00378         toggle_alarm = 0;
00379         alarm = 0.0;
00380         break;
00381     
00382     case STATUS_DONE:
00383         // LEDs off in this state
00384         cooking_status = LED_OFF;
00385         carousel_status = LED_OFF;
00386 
00387         // sound alarm
00388         toggle_alarm++;
00389         if ( toggle_alarm & 0x10 )
00390         {
00391             alarm.period(1.0/5000);
00392             alarm = 0.5;
00393         }
00394         else
00395         {
00396             alarm = 0.0;
00397         }
00398         
00399         lcd.locate(0,10);
00400         lcd.printf("ENJOY YOUR MEAL!\n");
00401         break;
00402     }
00403     lcd.locate(0,23);
00404     lcd.printf("door %s\n", ucDoorStatus ? "open  " : "closed");
00405 #ifdef DEBUG
00406     lcd.locate(95,23);
00407     lcd.printf("0x%04X\n", ulErrorCode);
00408 #endif /* DEBUG */        
00409 }