Explorar o código

implementation of the menu pages as FSM

Sebastian %!s(int64=7) %!d(string=hai) anos
pai
achega
e48a7edd12
Modificáronse 3 ficheiros con 330 adicións e 67 borrados
  1. 1 1
      CoffeeCode/buildno
  2. 304 63
      CoffeeCode/coffee.cpp
  3. 25 3
      CoffeeCode/coffee.h

+ 1 - 1
CoffeeCode/buildno

@@ -1 +1 @@
-216
+219

+ 304 - 63
CoffeeCode/coffee.cpp

@@ -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;
 }
 
 

+ 25 - 3
CoffeeCode/coffee.h

@@ -25,23 +25,45 @@ typedef enum {
 	STATE_FULLTANK
 } coffee_status_t;
 
+typedef enum {
+	MODE_STATE,
+	MODE_MENU
+} coffee_mode_t;
+
+typedef enum {
+	PAGE_SOFTOFF,
+	PAGE_KILL,
+	PAGE_STATS,
+	PAGE_TEMP,
+	PAGE_CLEAN,
+	PAGE_DEMO,
+	PAGE_EXIT
+} coffee_menuPage_t;
+
 extern const char* StateName[];
+extern const char* PageName[];
 
-#define AMOUNT_PREINFUSION	25 //Preinfusion amount in ml
-#define TIME_SOAK			5000 //Time between preinfusion and infusion in ms
+#define AMOUNT_PREINFUSION	25 		//Preinfusion amount in ml
+#define TIME_SOAK			5000 	//Time between preinfusion and infusion in ms
 #define TIME_INFUSION 		25000	//Infusion time in ms
 #define AMOUNT_DBLESPRESSO	59.0	//Size of a double espresso in ml
+#define DIRTY_ESPRESSO		35		//Number of espressos till the next cleaning
 void *coffeeThread(void *threadid);
 
 void coffeeHandler(int signum, siginfo_t *siginfo, void *context);
-int getSigValue(void);
 bool SigValueEmpty(void);
 void changeState(coffee_status_t newState);
+void changeMode(coffee_mode_t mode);
+void changePage(coffee_menuPage_t newPage);
+void leaveMenu(void);
 coffee_status_t getState(void);
+int getSigValue(coffee_mode_t mode);
 void brewTimeHandler(void);
 void writeBackCache(void);
 void coffeeTerminate(event_t *event);
 void coffeeBrew(void);
+void coffeeClean(void);
+void stopBrewing(void);
 void coffeeIncreaseBrewCounter(void);
 void coffeeIncreaseHeatingTime(uint64_t heatingTime);