microwave simulator

Dependencies:   C12832_lcd LM75B mbed

Committer:
rabad1
Date:
Fri Oct 18 20:41:08 2013 +0000
Revision:
0:2f825861a3a2
Child:
1:fac01d40d819
Microwave v0.9

Who changed what in which revision?

UserRevisionLine numberNew contents of line
rabad1 0:2f825861a3a2 1 #include "mbed.h"
rabad1 0:2f825861a3a2 2
rabad1 0:2f825861a3a2 3 #include "LM75B.h"
rabad1 0:2f825861a3a2 4 #include "C12832_lcd.h"
rabad1 0:2f825861a3a2 5 #include "keypad.h"
rabad1 0:2f825861a3a2 6
rabad1 0:2f825861a3a2 7 // uncomment to allow DEBUG
rabad1 0:2f825861a3a2 8 #define DEBUG
rabad1 0:2f825861a3a2 9
rabad1 0:2f825861a3a2 10 #define BUTTON_LEFT (p13)
rabad1 0:2f825861a3a2 11 #define BUTTON_RIGHT (p16)
rabad1 0:2f825861a3a2 12 #define BUTTON_START (p15)
rabad1 0:2f825861a3a2 13 #define BUTTON_STOP (p12)
rabad1 0:2f825861a3a2 14 #define BUTTON_DOOR (p14)
rabad1 0:2f825861a3a2 15
rabad1 0:2f825861a3a2 16 #define DOOR_CLOSED (0)
rabad1 0:2f825861a3a2 17 #define DOOR_OPEN (1)
rabad1 0:2f825861a3a2 18
rabad1 0:2f825861a3a2 19 #define LED_OFF (0)
rabad1 0:2f825861a3a2 20 #define LED_ON (1)
rabad1 0:2f825861a3a2 21
rabad1 0:2f825861a3a2 22 #define TRUE (1)
rabad1 0:2f825861a3a2 23 #define FALSE (0)
rabad1 0:2f825861a3a2 24
rabad1 0:2f825861a3a2 25 #define MIN_COOKING_TIME (0) // secs
rabad1 0:2f825861a3a2 26 #define MAX_COOKING_TIME (180)
rabad1 0:2f825861a3a2 27 #define COOKING_TIME_INCREMENT (60)
rabad1 0:2f825861a3a2 28 #define MAX_TICKER_TIME (60)
rabad1 0:2f825861a3a2 29 #define WDOG_TIME (1)
rabad1 0:2f825861a3a2 30
rabad1 0:2f825861a3a2 31 #define WHILE_LOOP_INTERVAL_MS (5) // msec
rabad1 0:2f825861a3a2 32
rabad1 0:2f825861a3a2 33 #define TEMP_INCREMENT (10.0f) // degC
rabad1 0:2f825861a3a2 34
rabad1 0:2f825861a3a2 35 typedef enum
rabad1 0:2f825861a3a2 36 {
rabad1 0:2f825861a3a2 37 STATUS_IDLE = 0,
rabad1 0:2f825861a3a2 38 STATUS_COOKING,
rabad1 0:2f825861a3a2 39 STATUS_DONE
rabad1 0:2f825861a3a2 40 } etSTATUS;
rabad1 0:2f825861a3a2 41
rabad1 0:2f825861a3a2 42 #ifdef DEBUG
rabad1 0:2f825861a3a2 43 #define MAX_LATENCY (10) // msec
rabad1 0:2f825861a3a2 44 #define ERROR_MICROWAVE_SM (1L<<0)
rabad1 0:2f825861a3a2 45 #define ERROR_LATENCY_DOOR (1L<<1)
rabad1 0:2f825861a3a2 46 #define ERROR_LATENCY_STOP (1L<<2)
rabad1 0:2f825861a3a2 47 #endif /* DEBUG */
rabad1 0:2f825861a3a2 48
rabad1 0:2f825861a3a2 49 // forward declarations
rabad1 0:2f825861a3a2 50 void init_microwave(void);
rabad1 0:2f825861a3a2 51 void press_left(void);
rabad1 0:2f825861a3a2 52 void press_right(void);
rabad1 0:2f825861a3a2 53 void press_start(void);
rabad1 0:2f825861a3a2 54 void press_stop(void);
rabad1 0:2f825861a3a2 55 void press_door(void);
rabad1 0:2f825861a3a2 56 void wdog_update(void);
rabad1 0:2f825861a3a2 57 void update_output(void);
rabad1 0:2f825861a3a2 58
rabad1 0:2f825861a3a2 59 void microwave_sm(void); // microwave state machine
rabad1 0:2f825861a3a2 60
rabad1 0:2f825861a3a2 61 // input peripherals
rabad1 0:2f825861a3a2 62 Keypad keypad( BUTTON_LEFT, press_left, // keypad
rabad1 0:2f825861a3a2 63 BUTTON_RIGHT, press_right,
rabad1 0:2f825861a3a2 64 BUTTON_START, press_start,
rabad1 0:2f825861a3a2 65 BUTTON_STOP, press_stop,
rabad1 0:2f825861a3a2 66 BUTTON_DOOR, press_door );
rabad1 0:2f825861a3a2 67 LM75B tmp(p28,p27); // temperature sensor
rabad1 0:2f825861a3a2 68
rabad1 0:2f825861a3a2 69
rabad1 0:2f825861a3a2 70 // output peripherals
rabad1 0:2f825861a3a2 71 C12832_LCD lcd; // LCD screen
rabad1 0:2f825861a3a2 72 DigitalOut cooking_status(LED1); // LED for cooking progress
rabad1 0:2f825861a3a2 73 DigitalOut carousel_status(LED2); // LED for carousel
rabad1 0:2f825861a3a2 74 #ifdef DEBUG
rabad1 0:2f825861a3a2 75 DigitalOut debugLED(LED4); // general debug LED
rabad1 0:2f825861a3a2 76 #endif /* DEBUG */
rabad1 0:2f825861a3a2 77 PwmOut alarm(p26);
rabad1 0:2f825861a3a2 78
rabad1 0:2f825861a3a2 79 // Timers
rabad1 0:2f825861a3a2 80 Ticker wdog; // 1sec watchdog
rabad1 0:2f825861a3a2 81 #ifdef DEBUG
rabad1 0:2f825861a3a2 82 Timer latency_wdog;
rabad1 0:2f825861a3a2 83 #endif /* DEBUG */
rabad1 0:2f825861a3a2 84
rabad1 0:2f825861a3a2 85 // global status variables
rabad1 0:2f825861a3a2 86 volatile signed short ssCookingTime;
rabad1 0:2f825861a3a2 87 unsigned char ucDoorStatus = DOOR_CLOSED;
rabad1 0:2f825861a3a2 88 float fTemp = 0.0f;
rabad1 0:2f825861a3a2 89 etSTATUS opStatus;
rabad1 0:2f825861a3a2 90 volatile unsigned char start_requested;
rabad1 0:2f825861a3a2 91 volatile unsigned char stop_requested;
rabad1 0:2f825861a3a2 92 volatile unsigned char temp_ticker;
rabad1 0:2f825861a3a2 93 #ifdef DEBUG
rabad1 0:2f825861a3a2 94 unsigned long ulErrorCode = 0UL;
rabad1 0:2f825861a3a2 95 #endif /* DEBUG */
rabad1 0:2f825861a3a2 96
rabad1 0:2f825861a3a2 97 int main()
rabad1 0:2f825861a3a2 98 {
rabad1 0:2f825861a3a2 99 unsigned char while_loop_counter = 0;
rabad1 0:2f825861a3a2 100
rabad1 0:2f825861a3a2 101 init_microwave();
rabad1 0:2f825861a3a2 102
rabad1 0:2f825861a3a2 103 while(1)
rabad1 0:2f825861a3a2 104 {
rabad1 0:2f825861a3a2 105 wait_ms(WHILE_LOOP_INTERVAL_MS);
rabad1 0:2f825861a3a2 106 while_loop_counter++;
rabad1 0:2f825861a3a2 107
rabad1 0:2f825861a3a2 108 microwave_sm(); // execute state machine
rabad1 0:2f825861a3a2 109
rabad1 0:2f825861a3a2 110 // do not need to update LCD as often
rabad1 0:2f825861a3a2 111 if ( while_loop_counter & 0x20 )
rabad1 0:2f825861a3a2 112 {
rabad1 0:2f825861a3a2 113 update_output();
rabad1 0:2f825861a3a2 114 }
rabad1 0:2f825861a3a2 115 }
rabad1 0:2f825861a3a2 116 }
rabad1 0:2f825861a3a2 117
rabad1 0:2f825861a3a2 118 void init_microwave(void)
rabad1 0:2f825861a3a2 119 {
rabad1 0:2f825861a3a2 120 ssCookingTime = 0L;
rabad1 0:2f825861a3a2 121 cooking_status = LED_OFF;
rabad1 0:2f825861a3a2 122 carousel_status = LED_OFF;
rabad1 0:2f825861a3a2 123 opStatus = STATUS_IDLE;
rabad1 0:2f825861a3a2 124 start_requested = FALSE;
rabad1 0:2f825861a3a2 125 stop_requested = FALSE;
rabad1 0:2f825861a3a2 126 }
rabad1 0:2f825861a3a2 127
rabad1 0:2f825861a3a2 128 void press_left(void)
rabad1 0:2f825861a3a2 129 {
rabad1 0:2f825861a3a2 130 if ( opStatus == STATUS_DONE )
rabad1 0:2f825861a3a2 131 {
rabad1 0:2f825861a3a2 132 return;
rabad1 0:2f825861a3a2 133 }
rabad1 0:2f825861a3a2 134 ssCookingTime += COOKING_TIME_INCREMENT;
rabad1 0:2f825861a3a2 135 if ( ssCookingTime >= MAX_COOKING_TIME )
rabad1 0:2f825861a3a2 136 {
rabad1 0:2f825861a3a2 137 ssCookingTime = MAX_COOKING_TIME;
rabad1 0:2f825861a3a2 138 }
rabad1 0:2f825861a3a2 139 }
rabad1 0:2f825861a3a2 140
rabad1 0:2f825861a3a2 141 void press_right(void)
rabad1 0:2f825861a3a2 142 {
rabad1 0:2f825861a3a2 143 if ( opStatus != STATUS_IDLE )
rabad1 0:2f825861a3a2 144 {
rabad1 0:2f825861a3a2 145 return;
rabad1 0:2f825861a3a2 146 }
rabad1 0:2f825861a3a2 147 ssCookingTime -= COOKING_TIME_INCREMENT;
rabad1 0:2f825861a3a2 148 if ( ssCookingTime <= MIN_COOKING_TIME )
rabad1 0:2f825861a3a2 149 {
rabad1 0:2f825861a3a2 150 ssCookingTime = MIN_COOKING_TIME;
rabad1 0:2f825861a3a2 151 }
rabad1 0:2f825861a3a2 152 }
rabad1 0:2f825861a3a2 153
rabad1 0:2f825861a3a2 154 void press_start(void)
rabad1 0:2f825861a3a2 155 {
rabad1 0:2f825861a3a2 156 if ( opStatus != STATUS_IDLE )
rabad1 0:2f825861a3a2 157 {
rabad1 0:2f825861a3a2 158 return;
rabad1 0:2f825861a3a2 159 }
rabad1 0:2f825861a3a2 160
rabad1 0:2f825861a3a2 161 if ( ssCookingTime && (ucDoorStatus == DOOR_CLOSED) )
rabad1 0:2f825861a3a2 162 {
rabad1 0:2f825861a3a2 163 start_requested = TRUE;
rabad1 0:2f825861a3a2 164 }
rabad1 0:2f825861a3a2 165 }
rabad1 0:2f825861a3a2 166
rabad1 0:2f825861a3a2 167 void press_stop(void)
rabad1 0:2f825861a3a2 168 {
rabad1 0:2f825861a3a2 169 if ( opStatus == STATUS_IDLE )
rabad1 0:2f825861a3a2 170 {
rabad1 0:2f825861a3a2 171 init_microwave();
rabad1 0:2f825861a3a2 172 return;
rabad1 0:2f825861a3a2 173 }
rabad1 0:2f825861a3a2 174 else
rabad1 0:2f825861a3a2 175 {
rabad1 0:2f825861a3a2 176 #ifdef DEBUG
rabad1 0:2f825861a3a2 177 latency_wdog.start();
rabad1 0:2f825861a3a2 178 #endif
rabad1 0:2f825861a3a2 179 stop_requested = TRUE;
rabad1 0:2f825861a3a2 180 }
rabad1 0:2f825861a3a2 181 }
rabad1 0:2f825861a3a2 182
rabad1 0:2f825861a3a2 183 void press_door(void)
rabad1 0:2f825861a3a2 184 {
rabad1 0:2f825861a3a2 185 ucDoorStatus = !ucDoorStatus;
rabad1 0:2f825861a3a2 186 if ( opStatus == STATUS_COOKING )
rabad1 0:2f825861a3a2 187 {
rabad1 0:2f825861a3a2 188 #ifdef DEBUG
rabad1 0:2f825861a3a2 189 latency_wdog.start();
rabad1 0:2f825861a3a2 190 #endif
rabad1 0:2f825861a3a2 191 }
rabad1 0:2f825861a3a2 192 }
rabad1 0:2f825861a3a2 193
rabad1 0:2f825861a3a2 194 void wdog_update(void)
rabad1 0:2f825861a3a2 195 {
rabad1 0:2f825861a3a2 196 if ( opStatus == STATUS_COOKING )
rabad1 0:2f825861a3a2 197 {
rabad1 0:2f825861a3a2 198 ssCookingTime--;
rabad1 0:2f825861a3a2 199
rabad1 0:2f825861a3a2 200 // reset wdog
rabad1 0:2f825861a3a2 201 if ( ssCookingTime )
rabad1 0:2f825861a3a2 202 {
rabad1 0:2f825861a3a2 203 wdog.attach(wdog_update, 1);
rabad1 0:2f825861a3a2 204 }
rabad1 0:2f825861a3a2 205
rabad1 0:2f825861a3a2 206 if ( temp_ticker )
rabad1 0:2f825861a3a2 207 {
rabad1 0:2f825861a3a2 208 temp_ticker--;
rabad1 0:2f825861a3a2 209 }
rabad1 0:2f825861a3a2 210 }
rabad1 0:2f825861a3a2 211 }
rabad1 0:2f825861a3a2 212
rabad1 0:2f825861a3a2 213 void microwave_sm(void)
rabad1 0:2f825861a3a2 214 {
rabad1 0:2f825861a3a2 215 switch ( opStatus )
rabad1 0:2f825861a3a2 216 {
rabad1 0:2f825861a3a2 217 case STATUS_IDLE:
rabad1 0:2f825861a3a2 218 fTemp = tmp.read();
rabad1 0:2f825861a3a2 219 if ( ssCookingTime && !ucDoorStatus && start_requested )
rabad1 0:2f825861a3a2 220 {
rabad1 0:2f825861a3a2 221 start_requested = FALSE;
rabad1 0:2f825861a3a2 222 wdog.attach(wdog_update, 1);
rabad1 0:2f825861a3a2 223 temp_ticker = (ssCookingTime > MAX_TICKER_TIME) ? MAX_TICKER_TIME : ssCookingTime;
rabad1 0:2f825861a3a2 224 opStatus = STATUS_COOKING;
rabad1 0:2f825861a3a2 225 }
rabad1 0:2f825861a3a2 226 break;
rabad1 0:2f825861a3a2 227
rabad1 0:2f825861a3a2 228 case STATUS_COOKING:
rabad1 0:2f825861a3a2 229 if ( ucDoorStatus == DOOR_OPEN )
rabad1 0:2f825861a3a2 230 {
rabad1 0:2f825861a3a2 231 #ifdef DEBUG
rabad1 0:2f825861a3a2 232 if (latency_wdog.read_ms() > MAX_LATENCY)
rabad1 0:2f825861a3a2 233 {
rabad1 0:2f825861a3a2 234 ulErrorCode |= ERROR_LATENCY_DOOR;
rabad1 0:2f825861a3a2 235 }
rabad1 0:2f825861a3a2 236 latency_wdog.stop();
rabad1 0:2f825861a3a2 237 #endif /* DEBUG */
rabad1 0:2f825861a3a2 238 init_microwave();
rabad1 0:2f825861a3a2 239 }
rabad1 0:2f825861a3a2 240 else if ( stop_requested )
rabad1 0:2f825861a3a2 241 {
rabad1 0:2f825861a3a2 242 #ifdef DEBUG
rabad1 0:2f825861a3a2 243 if (latency_wdog.read_ms() > MAX_LATENCY)
rabad1 0:2f825861a3a2 244 {
rabad1 0:2f825861a3a2 245 ulErrorCode |= ERROR_LATENCY_STOP;
rabad1 0:2f825861a3a2 246 }
rabad1 0:2f825861a3a2 247 latency_wdog.stop();
rabad1 0:2f825861a3a2 248 #endif /* DEBUG */
rabad1 0:2f825861a3a2 249 init_microwave();
rabad1 0:2f825861a3a2 250 }
rabad1 0:2f825861a3a2 251 else
rabad1 0:2f825861a3a2 252 {
rabad1 0:2f825861a3a2 253 if ( !ssCookingTime )
rabad1 0:2f825861a3a2 254 {
rabad1 0:2f825861a3a2 255 opStatus = STATUS_DONE;
rabad1 0:2f825861a3a2 256 }
rabad1 0:2f825861a3a2 257 else if ( !temp_ticker )
rabad1 0:2f825861a3a2 258 {
rabad1 0:2f825861a3a2 259 fTemp += TEMP_INCREMENT;
rabad1 0:2f825861a3a2 260 temp_ticker = (ssCookingTime > MAX_TICKER_TIME) ? MAX_TICKER_TIME : ssCookingTime;
rabad1 0:2f825861a3a2 261 }
rabad1 0:2f825861a3a2 262 }
rabad1 0:2f825861a3a2 263 break;
rabad1 0:2f825861a3a2 264
rabad1 0:2f825861a3a2 265 case STATUS_DONE:
rabad1 0:2f825861a3a2 266 if ( ucDoorStatus == DOOR_OPEN || stop_requested )
rabad1 0:2f825861a3a2 267 {
rabad1 0:2f825861a3a2 268 init_microwave();
rabad1 0:2f825861a3a2 269 }
rabad1 0:2f825861a3a2 270 break;
rabad1 0:2f825861a3a2 271
rabad1 0:2f825861a3a2 272 default:
rabad1 0:2f825861a3a2 273 #ifdef DEBUG
rabad1 0:2f825861a3a2 274 // something is wrong if we got here!
rabad1 0:2f825861a3a2 275 ulErrorCode |= ERROR_MICROWAVE_SM;
rabad1 0:2f825861a3a2 276 #endif /* DEBUG */
rabad1 0:2f825861a3a2 277 break;
rabad1 0:2f825861a3a2 278 }
rabad1 0:2f825861a3a2 279 }
rabad1 0:2f825861a3a2 280
rabad1 0:2f825861a3a2 281 void update_output(void)
rabad1 0:2f825861a3a2 282 {
rabad1 0:2f825861a3a2 283 static unsigned char toggle_alarm = 0;
rabad1 0:2f825861a3a2 284 static etSTATUS previousState = (etSTATUS) 0xFF;
rabad1 0:2f825861a3a2 285
rabad1 0:2f825861a3a2 286 // clear the screen only when we transition states to prevent flicker
rabad1 0:2f825861a3a2 287 if ( previousState != opStatus )
rabad1 0:2f825861a3a2 288 {
rabad1 0:2f825861a3a2 289 lcd.cls();
rabad1 0:2f825861a3a2 290 previousState = opStatus;
rabad1 0:2f825861a3a2 291 }
rabad1 0:2f825861a3a2 292 lcd.locate(0,0);
rabad1 0:2f825861a3a2 293 lcd.printf("Cooking Time: %3d secs\n",ssCookingTime);
rabad1 0:2f825861a3a2 294
rabad1 0:2f825861a3a2 295 switch ( opStatus )
rabad1 0:2f825861a3a2 296 {
rabad1 0:2f825861a3a2 297 case STATUS_IDLE:
rabad1 0:2f825861a3a2 298 // alarm should be off in this state
rabad1 0:2f825861a3a2 299 toggle_alarm = 0;
rabad1 0:2f825861a3a2 300 alarm = 0.0;
rabad1 0:2f825861a3a2 301 break;
rabad1 0:2f825861a3a2 302
rabad1 0:2f825861a3a2 303 case STATUS_COOKING:
rabad1 0:2f825861a3a2 304 // display temp
rabad1 0:2f825861a3a2 305 lcd.locate(0,10);
rabad1 0:2f825861a3a2 306 lcd.printf("Temp: %.2f degC\n", fTemp);
rabad1 0:2f825861a3a2 307
rabad1 0:2f825861a3a2 308 // update LEDs
rabad1 0:2f825861a3a2 309 cooking_status = !cooking_status;
rabad1 0:2f825861a3a2 310 carousel_status = !carousel_status;
rabad1 0:2f825861a3a2 311
rabad1 0:2f825861a3a2 312 // alarm should be off in this state
rabad1 0:2f825861a3a2 313 toggle_alarm = 0;
rabad1 0:2f825861a3a2 314 alarm = 0.0;
rabad1 0:2f825861a3a2 315 break;
rabad1 0:2f825861a3a2 316
rabad1 0:2f825861a3a2 317 case STATUS_DONE:
rabad1 0:2f825861a3a2 318 // LEDs off in this state
rabad1 0:2f825861a3a2 319 cooking_status = LED_OFF;
rabad1 0:2f825861a3a2 320 carousel_status = LED_OFF;
rabad1 0:2f825861a3a2 321
rabad1 0:2f825861a3a2 322 // sound alarm
rabad1 0:2f825861a3a2 323 toggle_alarm++;
rabad1 0:2f825861a3a2 324 if ( toggle_alarm & 8 )
rabad1 0:2f825861a3a2 325 {
rabad1 0:2f825861a3a2 326 alarm.period(1.0/5000);
rabad1 0:2f825861a3a2 327 alarm = 0.5;
rabad1 0:2f825861a3a2 328 }
rabad1 0:2f825861a3a2 329 else
rabad1 0:2f825861a3a2 330 {
rabad1 0:2f825861a3a2 331 alarm = 0.0;
rabad1 0:2f825861a3a2 332 }
rabad1 0:2f825861a3a2 333
rabad1 0:2f825861a3a2 334 lcd.locate(0,10);
rabad1 0:2f825861a3a2 335 lcd.printf("ENJOY YOUR MEAL!\n");
rabad1 0:2f825861a3a2 336 break;
rabad1 0:2f825861a3a2 337 }
rabad1 0:2f825861a3a2 338 lcd.locate(0,23);
rabad1 0:2f825861a3a2 339 lcd.printf("door %s\n", ucDoorStatus ? "open " : "closed");
rabad1 0:2f825861a3a2 340 #ifdef DEBUG
rabad1 0:2f825861a3a2 341 lcd.locate(95,23);
rabad1 0:2f825861a3a2 342 lcd.printf("0x%04X\n", ulErrorCode);
rabad1 0:2f825861a3a2 343 #endif /* DEBUG */
rabad1 0:2f825861a3a2 344 }