|
@@ -25,6 +25,9 @@
|
|
|
|
|
|
|
|
|
coffee_status_t state;
|
|
|
+coffee_menuPage_t page;
|
|
|
+coffee_mode_t mode;
|
|
|
+
|
|
|
int sigValue;
|
|
|
int brewTime; //Brew time in ms
|
|
|
timer brewTimer(&brewTimeHandler);
|
|
@@ -32,8 +35,11 @@ timer brewTimer(&brewTimeHandler);
|
|
|
uint64_t totalHeatingTime; //local copies of the corresponding database entries
|
|
|
uint16_t brewCounter;
|
|
|
bool initalHeating;
|
|
|
+bool descaling; //flag to indicate descaling and cleaning
|
|
|
+
|
|
|
|
|
|
|
|
|
+const char* PageName[] = {"SoftOff", "Kill", "Stats", "Temp", "Clean", "Demo", "Exit"};
|
|
|
const char* StateName[] = {"OFF", "HEATING", "INITHEAT", "IDLE", "BREW", "BREWMAN", "CLEAN", "ERROR", "WAITOFF"};
|
|
|
|
|
|
/**
|
|
@@ -57,8 +63,10 @@ void *coffeeThread(void *threadid) {
|
|
|
brewTimer.stop();
|
|
|
brewTime = 0;
|
|
|
|
|
|
- lastState = STATE_OFF;
|
|
|
initalHeating = true;
|
|
|
+ mode = MODE_STATE; //Unless we enter the menu we start in state mode
|
|
|
+ page = PAGE_SOFTOFF;
|
|
|
+ descaling = false;
|
|
|
|
|
|
//read the database values
|
|
|
if(!(totalHeatingTime = sqlGetConf(CFGHeatingTime))){
|
|
@@ -96,6 +104,131 @@ void *coffeeThread(void *threadid) {
|
|
|
logger(V_BREW, "Starting Coffee FSM\n");
|
|
|
//begin FSM
|
|
|
while (1) {
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Menue FSM
|
|
|
+ */
|
|
|
+ switch (page) {
|
|
|
+ case PAGE_SOFTOFF: //this page is only available when the machine is on
|
|
|
+ if (SigValueEmpty() && mode == MODE_MENU)
|
|
|
+ pause();
|
|
|
+
|
|
|
+ switch (getSigValue(MODE_MENU)) {
|
|
|
+ case SigInt0Psh:
|
|
|
+ changeState(STATE_WAIT_OFF);
|
|
|
+ leaveMenu();
|
|
|
+ break;
|
|
|
+
|
|
|
+ case SigInt1Psh:
|
|
|
+ changePage(PAGE_KILL);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case PAGE_KILL: //this page is only available when the machine is on
|
|
|
+ if (SigValueEmpty() && mode == MODE_MENU)
|
|
|
+ pause();
|
|
|
+
|
|
|
+ switch (getSigValue(MODE_MENU)) {
|
|
|
+ case SigInt0Psh:
|
|
|
+ if(halIsHeating()){
|
|
|
+ coffeeIncreaseHeatingTime(halgetHeatingTime());
|
|
|
+ }
|
|
|
+ changeState(STATE_OFF);
|
|
|
+ leaveMenu();
|
|
|
+ break;
|
|
|
+
|
|
|
+ case SigInt1Psh:
|
|
|
+ if(state == STATE_IDLE || state == STATE_HEATING){
|
|
|
+ changePage(PAGE_CLEAN);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ changePage(PAGE_DEMO);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case PAGE_CLEAN: //this page is only be available when the machine is hot
|
|
|
+ if (SigValueEmpty() && mode == MODE_MENU)
|
|
|
+ pause();
|
|
|
+
|
|
|
+ switch (getSigValue(MODE_MENU)) {
|
|
|
+ case SigInt0Psh:
|
|
|
+ changeMode(MODE_STATE);
|
|
|
+ if(!halProxSensorCovered()){
|
|
|
+ changeState(STATE_CLEANING);
|
|
|
+ leaveMenu();
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ changeState(STATE_FULLTANK);
|
|
|
+ leaveMenu();
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case SigInt1Psh:
|
|
|
+ changePage(PAGE_DEMO);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case PAGE_DEMO:
|
|
|
+ if (SigValueEmpty() && mode == MODE_MENU)
|
|
|
+ pause();
|
|
|
+
|
|
|
+ switch (getSigValue(MODE_MENU)) {
|
|
|
+ case SigInt1Psh:
|
|
|
+ changePage(PAGE_TEMP);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case PAGE_TEMP:
|
|
|
+ if (SigValueEmpty() && mode == MODE_MENU)
|
|
|
+ pause();
|
|
|
+
|
|
|
+ switch (getSigValue(MODE_MENU)) {
|
|
|
+ case SigInt1Psh:
|
|
|
+ changePage(PAGE_STATS);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case PAGE_STATS:
|
|
|
+ if (SigValueEmpty() && mode == MODE_MENU)
|
|
|
+ pause();
|
|
|
+
|
|
|
+ switch (getSigValue(MODE_MENU)) {
|
|
|
+ case SigInt1Psh:
|
|
|
+ changePage(PAGE_EXIT);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case PAGE_EXIT:
|
|
|
+ if (SigValueEmpty() && mode == MODE_MENU)
|
|
|
+ pause();
|
|
|
+
|
|
|
+ switch (getSigValue(MODE_MENU)) {
|
|
|
+ case SigInt0Psh:
|
|
|
+ leaveMenu();
|
|
|
+ break;
|
|
|
+
|
|
|
+ case SigInt1Psh:
|
|
|
+ if(state == STATE_HEATING || state == STATE_ERROR || state == STATE_IDLE || state == STATE_INITALHEATING){
|
|
|
+ changePage(PAGE_SOFTOFF);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ changePage(PAGE_DEMO);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ } //end switch (page)
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Hardware FSM
|
|
|
+ */
|
|
|
switch (state) {
|
|
|
/*
|
|
|
*
|
|
@@ -103,34 +236,42 @@ void *coffeeThread(void *threadid) {
|
|
|
case STATE_OFF:
|
|
|
halMachineOff();
|
|
|
writeBackCache();
|
|
|
+ page = PAGE_DEMO; //machine is off, the menu starts with the demo page
|
|
|
|
|
|
- if (SigValueEmpty())
|
|
|
+ if (SigValueEmpty() && mode == MODE_STATE)
|
|
|
pause();
|
|
|
- if (getSigValue() == SigInt0Rls) {
|
|
|
+ switch (getSigValue(MODE_STATE)) {
|
|
|
+ case SigInt0Rls:
|
|
|
//Check waterlevel in gray water tank
|
|
|
//turn machine on
|
|
|
halMachineOn();
|
|
|
sleep(1);
|
|
|
- if (halIsHeating()) { //check if System starts to heat when turned on
|
|
|
- initalHeating = true;
|
|
|
+ if (halIsHeating() && !halProxSensorCovered()) { //check if System starts to heat when turned on
|
|
|
changeState(STATE_INITALHEATING);
|
|
|
- } else {
|
|
|
+ } else if (!halIsHeating() && !halProxSensorCovered()){
|
|
|
changeState(STATE_IDLE);
|
|
|
}
|
|
|
- if (halProxSensorCovered()) {
|
|
|
- logger_error("Empty Tank please!\n");//change the state again to go back to the last state afterwards
|
|
|
+ else if (halProxSensorCovered()) {
|
|
|
+ logger_error("Empty Tank please!\n");
|
|
|
changeState(STATE_FULLTANK);
|
|
|
}
|
|
|
+ page = PAGE_SOFTOFF; //the machine is on, the menu starts with the turning off page
|
|
|
+ break;
|
|
|
+
|
|
|
+ case SigInt1Psh:
|
|
|
+ //Enter the menu
|
|
|
+ changeMode(MODE_MENU);
|
|
|
break;
|
|
|
}
|
|
|
break;
|
|
|
+
|
|
|
/*
|
|
|
*
|
|
|
*/
|
|
|
case STATE_WAIT_OFF:
|
|
|
- if (SigValueEmpty())
|
|
|
+ if (SigValueEmpty() && mode == MODE_STATE)
|
|
|
pause();
|
|
|
- switch (getSigValue()) {
|
|
|
+ switch (getSigValue(MODE_STATE)) {
|
|
|
case SigPressOpn:
|
|
|
usleep(100000);//wait so no load will be switched
|
|
|
coffeeIncreaseHeatingTime(halgetHeatingTime());
|
|
@@ -149,24 +290,25 @@ void *coffeeThread(void *threadid) {
|
|
|
break;
|
|
|
}
|
|
|
break;
|
|
|
+
|
|
|
/*
|
|
|
*
|
|
|
*/
|
|
|
case STATE_INITALHEATING:
|
|
|
initalHeating = true;
|
|
|
|
|
|
- if (SigValueEmpty())
|
|
|
+ if (SigValueEmpty() && mode == MODE_STATE)
|
|
|
pause();
|
|
|
- switch (getSigValue()) {
|
|
|
- case SigInt1RlsLong:
|
|
|
- //Turn machine off again
|
|
|
- coffeeIncreaseHeatingTime(halgetHeatingTime());
|
|
|
- changeState(STATE_OFF);
|
|
|
- break;
|
|
|
-
|
|
|
- case SigInt1Rls:
|
|
|
- changeState(STATE_WAIT_OFF);
|
|
|
- break;
|
|
|
+ switch (getSigValue(MODE_STATE)) {
|
|
|
+// case SigInt0RlsLong:
|
|
|
+// //Turn machine off again
|
|
|
+// coffeeIncreaseHeatingTime(halgetHeatingTime());
|
|
|
+// changeState(STATE_OFF);
|
|
|
+// break;
|
|
|
+//
|
|
|
+// case SigInt0Rls:
|
|
|
+// changeState(STATE_WAIT_OFF);
|
|
|
+// break;
|
|
|
|
|
|
case SigProxCvrd:
|
|
|
changeState(STATE_FULLTANK);
|
|
@@ -178,6 +320,10 @@ void *coffeeThread(void *threadid) {
|
|
|
coffeeIncreaseHeatingTime(halgetHeatingTime());
|
|
|
changeState(STATE_IDLE);
|
|
|
break;
|
|
|
+
|
|
|
+ case SigInt1Psh:
|
|
|
+ changeMode(MODE_MENU);
|
|
|
+ break;
|
|
|
}
|
|
|
break;
|
|
|
|
|
@@ -185,19 +331,19 @@ void *coffeeThread(void *threadid) {
|
|
|
*
|
|
|
*/
|
|
|
case STATE_HEATING:
|
|
|
- if (SigValueEmpty())
|
|
|
+ if (SigValueEmpty() && mode == MODE_STATE)
|
|
|
pause();
|
|
|
- switch (getSigValue()) {
|
|
|
- case SigInt1RlsLong:
|
|
|
- //Turn machine _immediately_ off again
|
|
|
- coffeeIncreaseHeatingTime(halgetHeatingTime());
|
|
|
- changeState(STATE_OFF);
|
|
|
- break;
|
|
|
-
|
|
|
- case SigInt1Rls:
|
|
|
- //turn machine off when heating is finished
|
|
|
- changeState(STATE_WAIT_OFF);
|
|
|
- break;
|
|
|
+ switch (getSigValue(MODE_STATE)) {
|
|
|
+// case SigInt1RlsLong:
|
|
|
+// //Turn machine _immediately_ off again
|
|
|
+// coffeeIncreaseHeatingTime(halgetHeatingTime());
|
|
|
+// changeState(STATE_OFF);
|
|
|
+// break;
|
|
|
+//
|
|
|
+// case SigInt1Rls:
|
|
|
+// //turn machine off when heating is finished
|
|
|
+// changeState(STATE_WAIT_OFF);
|
|
|
+// break;
|
|
|
|
|
|
case SigPressOpn:
|
|
|
coffeeIncreaseHeatingTime(halgetHeatingTime());
|
|
@@ -217,23 +363,29 @@ void *coffeeThread(void *threadid) {
|
|
|
//someone brews manually
|
|
|
changeState(STATE_BREWMANUAL);
|
|
|
break;
|
|
|
+
|
|
|
+ case SigInt1Psh:
|
|
|
+ //Enter the menu
|
|
|
+ changeMode(MODE_MENU);
|
|
|
+ break;
|
|
|
}
|
|
|
break;
|
|
|
+
|
|
|
/*
|
|
|
*
|
|
|
*/
|
|
|
case STATE_IDLE:
|
|
|
- if (SigValueEmpty())
|
|
|
+ if (SigValueEmpty() && mode == MODE_STATE)
|
|
|
pause();
|
|
|
- switch (getSigValue()) {
|
|
|
- case SigInt1RlsLong:
|
|
|
- //turn machine _immediately_ off
|
|
|
- changeState(STATE_OFF);
|
|
|
- break;
|
|
|
-
|
|
|
- case SigInt1Rls:
|
|
|
- changeState(STATE_OFF);
|
|
|
- break;
|
|
|
+ switch (getSigValue(MODE_STATE)) {
|
|
|
+// case SigInt1RlsLong:
|
|
|
+// //turn machine _immediately_ off
|
|
|
+// changeState(STATE_OFF);
|
|
|
+// break;
|
|
|
+//
|
|
|
+// case SigInt1Rls:
|
|
|
+// changeState(STATE_OFF);
|
|
|
+// break;
|
|
|
|
|
|
case SigPressCls:
|
|
|
changeState(STATE_HEATING);
|
|
@@ -251,8 +403,14 @@ void *coffeeThread(void *threadid) {
|
|
|
//someone brews manually
|
|
|
changeState(STATE_BREWMANUAL);
|
|
|
break;
|
|
|
+
|
|
|
+ case SigInt1Psh:
|
|
|
+ //Enter the menu
|
|
|
+ changeMode(MODE_MENU);
|
|
|
+ break;
|
|
|
}
|
|
|
break;
|
|
|
+
|
|
|
/*
|
|
|
*
|
|
|
*/
|
|
@@ -280,16 +438,27 @@ void *coffeeThread(void *threadid) {
|
|
|
*
|
|
|
*/
|
|
|
case STATE_BREWMANUAL:
|
|
|
- if (SigValueEmpty())
|
|
|
+ if (SigValueEmpty() && mode == MODE_STATE)
|
|
|
pause();
|
|
|
break;
|
|
|
|
|
|
/*
|
|
|
*
|
|
|
*/
|
|
|
- case STATE_CLEANING:
|
|
|
- if (SigValueEmpty())
|
|
|
+ case STATE_CLEANING: //this can only be executed once the machine is hot!
|
|
|
+ if (SigValueEmpty() && mode == MODE_STATE)
|
|
|
pause();
|
|
|
+ if (!halProxSensorCovered()) {
|
|
|
+ //execute the cleaning procedure
|
|
|
+ coffeeClean();
|
|
|
+ if (halIsHeating()) {
|
|
|
+ changeState(STATE_HEATING);
|
|
|
+ } else {
|
|
|
+ changeState(STATE_IDLE);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ changeState(STATE_FULLTANK);
|
|
|
+ }
|
|
|
break;
|
|
|
|
|
|
/*
|
|
@@ -297,9 +466,9 @@ void *coffeeThread(void *threadid) {
|
|
|
* idle times, initial heating and heating
|
|
|
*/
|
|
|
case STATE_FULLTANK:
|
|
|
- if (SigValueEmpty())
|
|
|
+ if (SigValueEmpty() && mode == MODE_STATE)
|
|
|
pause();
|
|
|
- switch (getSigValue()) {
|
|
|
+ switch (getSigValue(MODE_STATE)) {
|
|
|
case SigInt1Psh:
|
|
|
case SigInt0Psh:
|
|
|
if(halIsHeating() && initalHeating){
|
|
@@ -317,9 +486,9 @@ void *coffeeThread(void *threadid) {
|
|
|
*
|
|
|
*/
|
|
|
case STATE_ERROR:
|
|
|
- if (SigValueEmpty())
|
|
|
+ if (SigValueEmpty() && mode == MODE_STATE)
|
|
|
pause();
|
|
|
- switch (getSigValue()) {
|
|
|
+ switch (getSigValue(MODE_STATE)) {
|
|
|
case SigInt1RlsLong:
|
|
|
case SigInt0RlsLong:
|
|
|
if(halIsHeating()){
|
|
@@ -347,10 +516,29 @@ void coffeeHandler(int signum, siginfo_t *siginfo, void *context) {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * returns the Signal value from the last received Signal and clears the variable
|
|
|
+ * returns the Signal value from the last received Signal for the given mode and clears the variable
|
|
|
* @return value sent with the last signal
|
|
|
*/
|
|
|
-int getSigValue(void) {
|
|
|
+int getSigValue(coffee_mode_t mode) {
|
|
|
+ if(mode == MODE_MENU) {
|
|
|
+ switch (sigValue){
|
|
|
+ case SigInt0Psh:
|
|
|
+ case SigInt0Rls:
|
|
|
+ case SigInt0RlsLong:
|
|
|
+ case SigInt1Psh:
|
|
|
+ case SigInt1Rls:
|
|
|
+ case SigInt1RlsLong:
|
|
|
+ int tmp = sigValue;
|
|
|
+ sigValue = 0;
|
|
|
+ return tmp;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else { //State Mode
|
|
|
+ int tmp = sigValue;
|
|
|
+ sigValue = 0;
|
|
|
+ return tmp;
|
|
|
+ }
|
|
|
int tmp = sigValue;
|
|
|
sigValue = 0;
|
|
|
return tmp;
|
|
@@ -374,6 +562,36 @@ void changeState(coffee_status_t newState) {
|
|
|
event_trigger("statechange", &state, sizeof(state));
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * Change Page to new menu page
|
|
|
+ */
|
|
|
+void changePage(coffee_menuPage_t newPage){
|
|
|
+ logger(V_BREW, "Change Page to %s", PageName[newPage]);
|
|
|
+ page = newPage;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Changes the mode of the machine to the given mode
|
|
|
+ */
|
|
|
+void changeMode(coffee_mode_t newmode){
|
|
|
+ if(mode == MODE_MENU)
|
|
|
+ logger(V_BREW, "Changing to menu mode\n");
|
|
|
+ else
|
|
|
+ logger(V_BREW, "Changing to state mode\n");
|
|
|
+
|
|
|
+ mode = newmode;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * leaving the menu
|
|
|
+ */
|
|
|
+void leaveMenu(){
|
|
|
+ logger(V_BREW, "Leaving the menu again...\n");
|
|
|
+ //leave the menu again
|
|
|
+ changeMode(MODE_STATE);
|
|
|
+ //change page to initial page
|
|
|
+ changePage(PAGE_SOFTOFF);
|
|
|
+}
|
|
|
/**
|
|
|
* Returns the current state of the FSM
|
|
|
*/
|
|
@@ -416,6 +634,20 @@ void writeBackCache(void){
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * Procedure for cleaning the machine
|
|
|
+ */
|
|
|
+void coffeeClean(void){
|
|
|
+ logger(V_BREW, "Cleaning...\n");
|
|
|
+ for(int i = 0; i < 20; i++){
|
|
|
+ halRelaisOn(RELAIS_PUMP);
|
|
|
+ sleep(3);
|
|
|
+ halRelaisOff(RELAIS_PUMP);
|
|
|
+ sleep(15);
|
|
|
+ }
|
|
|
+ descaling = false;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* Brewing process
|
|
|
*/
|
|
@@ -431,12 +663,11 @@ void coffeeBrew(void) {
|
|
|
brewTimer.start();
|
|
|
while (halGetFlow() < AMOUNT_PREINFUSION) {
|
|
|
usleep(50000);
|
|
|
- if (getSigValue() == SigInt1Psh)
|
|
|
+ if (getSigValue(MODE_STATE) == SigInt0Psh)
|
|
|
+ stopBrewing();
|
|
|
return;
|
|
|
}
|
|
|
- brewTimer.stop();
|
|
|
- brewTime = 0;
|
|
|
- halRelaisOff(RELAIS_PUMP);
|
|
|
+ stopBrewing();
|
|
|
|
|
|
/*
|
|
|
* Wait for coffee to soak in infused water
|
|
@@ -444,12 +675,11 @@ void coffeeBrew(void) {
|
|
|
brewTimer.start();
|
|
|
while (brewTime < TIME_SOAK) {
|
|
|
usleep(100000);
|
|
|
- if (getSigValue() == SigInt1Psh)
|
|
|
+ if (getSigValue(MODE_STATE) == SigInt0Psh)
|
|
|
+ stopBrewing();
|
|
|
return;
|
|
|
}
|
|
|
- brewTimer.stop();
|
|
|
- brewTime = 0;
|
|
|
- halResetFlow();
|
|
|
+ stopBrewing();
|
|
|
|
|
|
/*
|
|
|
* Brewing the actual espresso
|
|
@@ -459,14 +689,23 @@ void coffeeBrew(void) {
|
|
|
brewTimer.start();
|
|
|
while (brewTime < TIME_INFUSION && halGetFlow() < AMOUNT_DBLESPRESSO) {
|
|
|
usleep(100000);
|
|
|
- if (getSigValue() == SigInt1Psh)
|
|
|
+ if (getSigValue(MODE_STATE) == SigInt0Psh)
|
|
|
+ stopBrewing();
|
|
|
return;
|
|
|
}
|
|
|
+ stopBrewing();
|
|
|
+ return;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Wrapper function for the end of a brewing process
|
|
|
+ * this function stops the pump, brewtimer and resets the flow and brew time to zero
|
|
|
+ */
|
|
|
+void stopBrewing(){
|
|
|
halRelaisOff(RELAIS_PUMP);
|
|
|
- halResetFlow();
|
|
|
brewTimer.stop();
|
|
|
brewTime = 0;
|
|
|
- return;
|
|
|
+ halResetFlow();
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -474,6 +713,8 @@ void coffeeBrew(void) {
|
|
|
*/
|
|
|
void coffeeIncreaseBrewCounter(void) {
|
|
|
brewCounter++;
|
|
|
+ if((brewCounter % DIRTY_ESPRESSO) == 0)
|
|
|
+ descaling = true;
|
|
|
}
|
|
|
|
|
|
|