
A simple microwave demo
Dependencies: C12832_lcd LM75B mbed-rtos mbed
rtos_hwk7.cpp
- Committer:
- joeroop
- Date:
- 2014-03-15
- Revision:
- 1:896789dcc911
- Parent:
- 0:3a19dcea1a01
- Child:
- 2:324dc8b89365
File content as of revision 1:896789dcc911:
#include "mbed.h" #include "rtos.h" #include "C12832_lcd.h" //LCD interface #include "LM75B.h" //temperature interface #define DEBOUNCE_TIME_MS 10 #define MAX_COOK_TIME_S 180 //3min #define INIT_COOK_TIME_S 5 //globals and types DigitalOut led1(LED1); DigitalOut led2(LED2); DigitalOut led3(LED3); DigitalOut led4(LED4); C12832_LCD lcd; Timer debounceTimer; InterruptIn irptTimeDn(p16); //cook down InterruptIn irptTimeUp(p13); //cook up InterruptIn irptStart(p15); //start cooking InterruptIn irptStop(p12); //stop cooking InterruptIn irptDoor(p14); //door interrupt Thread *proxy_lcd; Thread *proxy_temp; Thread *proxy_sound; Thread *proxy_state; Thread *proxy_led; Thread *proxy_timer; Thread *proxies[] = { proxy_lcd, proxy_temp, proxy_sound, proxy_state, proxy_led, proxy_timer, }; int PROXIES_SIZE = sizeof(proxies)/sizeof(Thread*); typedef enum { //start at one as we are using this as signals //states WAITING = 1, COOKING, DONE, //interrupts signals TIMEUP, TIMEDN, START, STOP, DOOR } state_t; char *stateStr[] = {"NULL","WAIT","COOK","DONE"}; typedef enum {TEMP_VAL, TIME_ELPS, TIME_RQST} type_t; typedef enum {STATE, TEMP, SOUND, LCD, LED, TIMER, ALL} thread_t; char *threadStr[] = {"STATE", "TEMP", "SOUND", "LCD", "LED", "TIMER", "ALL"}; typedef struct { state_t state; type_t type; union { float temp; int time_elapsed; //seconds of cooking int time_request; //seconds } value; } data_t; MemoryPool<data_t,10> mpool; //used to hold all messages Queue<data_t,10> queue; //used to hold the messages bool debounce(void); void blink_led(void const *args); void send_time(const void *args); //void send_state(const void *args); void send_state(state_t state, thread_t pthr); //Threads void thread_state(void const *args); void thread_lcd(void const *args); void thread_temp(void const *args); void thread_sound(void const *args); void thread_led(void const *args); void thread_timer(void const *args); //ISRs void isrTimeUp(void); void isrTimeDn(void); void isrStart(void); void isrStop(void); void isrDoor(void); int main(void){ debounceTimer.start(); //interrupts irptTimeUp.rise(&isrTimeUp); irptTimeDn.rise(&isrTimeDn); irptStart.rise(&isrStart); irptStop.rise(&isrStop); irptDoor.rise(&isrDoor); //debounce everything except for the door Thread t1(thread_state); Thread t2(thread_temp); Thread t3(thread_sound); Thread t4(thread_lcd); Thread t5(thread_led); Thread t6(thread_timer); proxy_state = &t1; proxy_temp = &t2; proxy_sound = &t3; proxy_lcd = &t4; proxy_led = &t5; proxy_timer = &t6; t4.set_priority(osPriorityRealtime); while(1){ Thread::wait(250); } } //function for a global debounce on the isrstick bool debounce(void){ if(debounceTimer.read_ms() > DEBOUNCE_TIME_MS){ debounceTimer.reset(); return true; }else{ return false; } } //ISRs void isrTimeUp(void){ if(debounce()){ proxy_state->signal_set(TIMEUP); //left } } void isrTimeDn(void){ if(debounce()){ proxy_state->signal_set(TIMEDN); //right } } void isrStart(void){ if(debounce()){ proxy_state->signal_set(START); //up } } void isrStop(void){ if(debounce()){ proxy_state->signal_set(STOP); //down } } void isrDoor(void){ //no debounce this is most important function! proxy_state->signal_set(DOOR); } //Threads void thread_lcd(void const *args){ osEvent evt; int32_t sig; state_t state; while(1){ evt = Thread::signal_wait(0); sig = evt.value.signals; switch(sig){ case WAITING: state = WAITING; break; case COOKING: state = COOKING; break; case DONE: state = DONE; break; } //print the state lcd.locate(70,0); lcd.printf("State: %s ",stateStr[state]); //call the queue } } void thread_temp(void const *args){ while(1){ Thread::wait(100); } } void thread_sound(void const *args){ while(1){ Thread::wait(100); } } //helper function to send all the threads the current state except for thread* passed in void send_state(state_t state, thread_t pthr){ short i; for(i=0; i<PROXIES_SIZE;i++){ if(i != pthr){ //if you don't match the Thread* then send a signal to that thread proxies[pthr]->signal_set(state); }else{ lcd.locate(0,20); lcd.printf("send: %s, %s",stateStr[state],threadStr[i]); } } } //State thread to do most of the main state machine logic void thread_state(void const *args){ osEvent evt; int32_t mask; bool openDoor = false; //start with door closed state_t state = WAITING; //WAITING, COOKING, DONE while(1){ evt = Thread::signal_wait(0); mask = evt.value.signals; switch(mask){ case WAITING: state = WAITING; //send_state((void*)WAITING); //send state to all threads send_state(state,STATE); break; case COOKING: state = COOKING; send_state(state,STATE); break; case DONE: //timer can signal this state = WAITING; send_state(state,STATE); //send signal to timer, led and pwm break; case TIMEUP: //change the timer up if(state == WAITING) proxy_timer->signal_set(TIMEUP); break; case TIMEDN: //change the timer down if(state == WAITING) proxy_timer->signal_set(TIMEDN); break; case START: if(state == WAITING) proxy_state->signal_set(COOKING); break; case STOP: if(state == COOKING) proxy_state->signal_set(DONE); break; case DOOR: //door changed state openDoor = !openDoor; state = (openDoor == true) ? DONE : WAITING; //open door then done else state back to waiting led1 = led2 = led3 =led4 = openDoor; send_state(state,ALL); //signal back to state thread //proxy_lcd->signal_set(openDoor); break; } } } //helper function to thread_led used to blink led void blink_led(void const *args){ led1 = !led1; } //Thread led to blink the light when cooking and stop when done void thread_led(void const *args){ RtosTimer timer(blink_led, osTimerPeriodic); osEvent evt; int32_t sig; while(1){ //may need to sleep somewhere to give up thread check to see if signal_wait equiv of wait evt = Thread::signal_wait(0); //will time out then loop not needed sig = evt.value.signals; switch(sig){ case COOKING: timer.start(250); break; case DONE: timer.stop(); led1 = 0; break; default: //Thread::wait(2000); if wait can miss signal break; } } } //helper function for the timer thread void send_time(const void *args){ int time = (*((int*)args))--; //have the time in seconds send to lcd now //lcd.locate(0,10); //lcd.printf("ELPS %d",time); if(time == 0) send_state(DONE,TIMER); //tell all threads cooking time up } void thread_timer(void const *args){ int time; int *ptime = &time; RtosTimer timer(send_time, osTimerPeriodic,(void*)ptime); osEvent evt; int32_t sig; state_t state; while(1){ evt = Thread::signal_wait(0); //will time out then loop not needed sig = evt.value.signals; switch(sig){ case WAITING: state = WAITING; break; case COOKING: state = COOKING; timer.start(1000); //this is the increments of the timer 1s break; case DONE: state = DONE; time = INIT_COOK_TIME_S; //default time //send request time to lcd queue reset //lcd.locate(0,0); //lcd.printf("RQST %d",time); timer.stop(); break; case TIMEUP: if(state == WAITING){ time = (++time) > MAX_COOK_TIME_S ? MAX_COOK_TIME_S : time; //check limits //send request time to lcd queue //lcd.locate(0,0); //lcd.printf("RQST %d",time); } break; case TIMEDN: if(state == WAITING){ time = (--time) < 0 ? 0 : time; //check limits //send request time to lcd //lcd.locate(0,0); //lcd.printf("RQST %d",time); } break; default: //Thread::wait(2000); if wait can miss signal break; } } }