microwave simulator
Dependencies: C12832_lcd LM75B mbed
main.cpp
- Committer:
- rabad1
- Date:
- 2013-10-24
- Revision:
- 2:9f6bdaddefff
- Parent:
- 1:fac01d40d819
File content as of revision 2:9f6bdaddefff:
#include "mbed.h" #include "LM75B.h" #include "C12832_lcd.h" #include "keypad.h" // uncomment to allow DEBUG //#define DEBUG #define BUTTON_LEFT (p13) #define BUTTON_RIGHT (p16) #define BUTTON_START (p15) #define BUTTON_STOP (p12) #define BUTTON_DOOR (p14) #define TEMP_SCL (p27) #define TEMP_SDA (p28) #define ALARM (p26) #define DOOR_CLOSED (0) #define DOOR_OPEN (1) #define LED_OFF (0) #define LED_ON (1) #define TRUE (1) #define FALSE (0) #define MIN_COOKING_TIME (0) // secs #define MAX_COOKING_TIME (180) #define COOKING_TIME_INCREMENT (60) #define MAX_TICKER_TIME (60) #define WDOG_TIME (1) #define TEMP_INCREMENT (10.0f) // degC typedef enum { STATUS_IDLE = 0, STATUS_COOKING, STATUS_DONE } etSTATUS; #ifdef DEBUG #define MAX_LATENCY (10) // msec #define ERROR_MICROWAVE_SM (1L<<0) #define ERROR_LATENCY_DOOR (1L<<1) #define ERROR_LATENCY_STOP (1L<<2) #endif /* DEBUG */ // forward declarations void init_microwave(void); void press_left(void); void press_right(void); void press_start(void); void press_stop(void); void press_door(void); void wdog_update(void); void update_output(void); void microwave_sm(void); // microwave state machine // input peripherals Keypad keypad( BUTTON_LEFT, press_left, // keypad BUTTON_RIGHT, press_right, BUTTON_START, press_start, BUTTON_STOP, press_stop, BUTTON_DOOR, press_door ); LM75B tmp(TEMP_SDA,TEMP_SCL); // temperature sensor // output peripherals C12832_LCD lcd; // LCD screen DigitalOut cooking_status(LED1); // LED for cooking progress DigitalOut carousel_status(LED2); // LED for carousel #ifdef DEBUG DigitalOut debugLED(LED4); // general debug LED #endif /* DEBUG */ PwmOut alarm(ALARM); // alarm // Timers Ticker wdog; // 1sec watchdog #ifdef DEBUG Timer latency_wdog; #endif /* DEBUG */ // global status variables volatile signed short ssCookingTime; unsigned char ucDoorStatus = DOOR_CLOSED; float fTemp = 0.0f; etSTATUS opStatus; volatile unsigned char start_requested; volatile unsigned char stop_requested; volatile unsigned char temp_ticker; unsigned char reset_wdog; #ifdef DEBUG unsigned long ulErrorCode = 0UL; #endif /* DEBUG */ /* Name: main() * Desc: entry point of application. This will also invoke the microwave * state machine and update output * Inputs: none * Outputs: none */ int main() { unsigned int while_loop_counter = 0; init_microwave(); while(1) { while_loop_counter++; microwave_sm(); // execute state machine // do not need to update LCD as often if ( while_loop_counter & 0x4000 ) { update_output(); } } } /* Name: init_microwave() * Desc: initializes the microwave state machine to STATUS_IDLE * Inputs: none * Outputs: none */ void init_microwave(void) { ssCookingTime = 0L; cooking_status = LED_OFF; carousel_status = LED_OFF; opStatus = STATUS_IDLE; start_requested = FALSE; stop_requested = FALSE; reset_wdog = FALSE; } /* Name: press_left() * Desc: ISR callback function for left button. * Inputs: none * Outputs: none */ void press_left(void) { if ( opStatus == STATUS_DONE ) { return; } ssCookingTime += COOKING_TIME_INCREMENT; if ( ssCookingTime >= MAX_COOKING_TIME ) { ssCookingTime = MAX_COOKING_TIME; } } /* Name: press_right() * Desc: ISR callback function for right button. * Inputs: none * Outputs: none */ void press_right(void) { if ( opStatus != STATUS_IDLE ) { return; } ssCookingTime -= COOKING_TIME_INCREMENT; if ( ssCookingTime <= MIN_COOKING_TIME ) { ssCookingTime = MIN_COOKING_TIME; } } /* Name: press_start() * Desc: ISR callback function for start button. * Inputs: none * Outputs: none */ void press_start(void) { if ( opStatus != STATUS_IDLE ) { return; } if ( ssCookingTime && (ucDoorStatus == DOOR_CLOSED) ) { start_requested = TRUE; } } /* Name: press_stop() * Desc: ISR callback function for stop button. * Inputs: none * Outputs: none */ void press_stop(void) { if ( opStatus == STATUS_IDLE ) { init_microwave(); return; } else { #ifdef DEBUG latency_wdog.start(); #endif stop_requested = TRUE; } } /* Name: press_door() * Desc: ISR callback function for door button. * Inputs: none * Outputs: none */ void press_door(void) { ucDoorStatus = !ucDoorStatus; if ( opStatus == STATUS_COOKING ) { #ifdef DEBUG latency_wdog.start(); #endif } } /* Name: wdog_update() * Desc: callback function for watchdog timer. This watchog updates the * cooking time when the microwave is running (STATUS_COOKING). * Inputs: none * Outputs: none */ void wdog_update(void) { if ( opStatus == STATUS_COOKING ) { ssCookingTime--; // reset wdog if ( ssCookingTime ) { reset_wdog = TRUE; } if ( temp_ticker ) { temp_ticker--; } } } /* Name: microwave_sm() * Desc: This is the microwave state machine. It processes all input and * updates all state variables. * Inputs: none * Outputs: none */ void microwave_sm(void) { switch ( opStatus ) { case STATUS_IDLE: if ( ssCookingTime && !ucDoorStatus && start_requested ) { fTemp = tmp.read(); start_requested = FALSE; wdog.attach(wdog_update, 1); temp_ticker = (ssCookingTime > MAX_TICKER_TIME) ? MAX_TICKER_TIME : ssCookingTime; opStatus = STATUS_COOKING; } break; case STATUS_COOKING: if ( ucDoorStatus == DOOR_OPEN ) { #ifdef DEBUG if (latency_wdog.read_ms() > MAX_LATENCY) { ulErrorCode |= ERROR_LATENCY_DOOR; } latency_wdog.stop(); #endif /* DEBUG */ init_microwave(); } else if ( stop_requested ) { #ifdef DEBUG if (latency_wdog.read_ms() > MAX_LATENCY) { ulErrorCode |= ERROR_LATENCY_STOP; } latency_wdog.stop(); #endif /* DEBUG */ init_microwave(); } else { if ( !ssCookingTime ) { opStatus = STATUS_DONE; } if ( !temp_ticker ) { fTemp += TEMP_INCREMENT; temp_ticker = (ssCookingTime > MAX_TICKER_TIME) ? MAX_TICKER_TIME : ssCookingTime; } if ( reset_wdog ) { wdog.attach(wdog_update, 1); reset_wdog = FALSE; } } break; case STATUS_DONE: if ( ucDoorStatus == DOOR_OPEN || stop_requested ) { init_microwave(); } break; default: #ifdef DEBUG // something is wrong if we got here! ulErrorCode |= ERROR_MICROWAVE_SM; #endif /* DEBUG */ break; } } /* Name: update_output() * Desc: Updates all output based on status variables. * Inputs: none * Outputs: none */ void update_output(void) { static unsigned char toggle_alarm = 0; static unsigned char toggle_leds = 0; static etSTATUS previousState = (etSTATUS) 0xFF; // clear the screen only when we transition states to prevent flicker if ( previousState != opStatus ) { lcd.cls(); previousState = opStatus; } lcd.locate(0,0); lcd.printf("Cooking Time: %3d secs\n",ssCookingTime); switch ( opStatus ) { case STATUS_IDLE: // alarm should be off in this state toggle_alarm = 0; alarm = 0.0; break; case STATUS_COOKING: // display temp lcd.locate(0,10); lcd.printf("Temp: %.2f degC\n", fTemp); // update LEDs toggle_leds++; if ( toggle_leds & 0x10 ) { cooking_status = !cooking_status; carousel_status = !carousel_status; } // alarm should be off in this state toggle_alarm = 0; alarm = 0.0; break; case STATUS_DONE: // LEDs off in this state cooking_status = LED_OFF; carousel_status = LED_OFF; // sound alarm toggle_alarm++; if ( toggle_alarm & 0x10 ) { alarm.period(1.0/5000); alarm = 0.5; } else { alarm = 0.0; } lcd.locate(0,10); lcd.printf("ENJOY YOUR MEAL!\n"); break; } lcd.locate(0,23); lcd.printf("door %s\n", ucDoorStatus ? "open " : "closed"); #ifdef DEBUG lcd.locate(95,23); lcd.printf("0x%04X\n", ulErrorCode); #endif /* DEBUG */ }