|
@@ -0,0 +1,224 @@
|
|
|
+/*
|
|
|
+ * coffee.cpp
|
|
|
+ *
|
|
|
+ * Created on: Sep 25, 2017
|
|
|
+ * Author: sebastian
|
|
|
+ */
|
|
|
+
|
|
|
+#include <stdio.h>
|
|
|
+#include <stdlib.h>
|
|
|
+#include <string.h>
|
|
|
+#include <errno.h>
|
|
|
+#include <stdint.h>
|
|
|
+#include <wiringPi.h>
|
|
|
+#include <pthread.h>
|
|
|
+#include <unistd.h>
|
|
|
+#include <iostream>
|
|
|
+#include <csignal>
|
|
|
+#include <time.h>
|
|
|
+#include "coffee.h"
|
|
|
+#include "hal.h"
|
|
|
+#include "logger.h"
|
|
|
+#include "timer.h"
|
|
|
+
|
|
|
+
|
|
|
+int state;
|
|
|
+int sigValue;
|
|
|
+int brewTime; //Brew time in ms
|
|
|
+timer brewTimer(&brewTimeHandler);
|
|
|
+
|
|
|
+void *coffeeThread(void *threadid) {
|
|
|
+ logger(V_BREW, "Initializing coffee thread...\n");
|
|
|
+
|
|
|
+ //installing new Signal handler for coffeethread
|
|
|
+ struct sigaction action;
|
|
|
+ sigemptyset(&action.sa_mask);
|
|
|
+ action.sa_flags = SA_SIGINFO;
|
|
|
+ action.sa_sigaction = coffeeHandler;
|
|
|
+ sigaction(SIGUSR2, &action, NULL);
|
|
|
+
|
|
|
+ brewTimer.setDivider(4);
|
|
|
+ brewTimer.stop();
|
|
|
+ brewTime = 0;
|
|
|
+
|
|
|
+ state = STATE_OFF;
|
|
|
+ logger(V_BREW, "Determining inital state\n");
|
|
|
+ //determine inital state
|
|
|
+ if (halGetRelaisState(RELAIS_POWER) && halGetRelaisState(RELAIS_HEAT) && !halGetRelaisState(RELAIS_PUMP)) {
|
|
|
+ //wait for heat relais to switch
|
|
|
+ sleep(1);
|
|
|
+ if (halIsHeating()) { //Heating is on
|
|
|
+ logger(V_BREW, "Change state: INITALHEATING\n");
|
|
|
+ state = STATE_INITALHEATING;
|
|
|
+ } else {
|
|
|
+ logger(V_BREW, "Change state: IDLE\n");
|
|
|
+ state = STATE_IDLE;
|
|
|
+ }
|
|
|
+ } else if (halGetRelaisState(RELAIS_PUMP)) {
|
|
|
+ logger_error("Whoops, why is the pump running...\n");
|
|
|
+ state = STATE_ERROR;
|
|
|
+ }
|
|
|
+
|
|
|
+ logger(V_BREW, "Start Coffee FSM\n");
|
|
|
+ //begin FSM
|
|
|
+ while(1){
|
|
|
+ switch(state){
|
|
|
+ case STATE_OFF:
|
|
|
+ pause();
|
|
|
+ if (getSigValue() == SigInt0Rls) {
|
|
|
+ if (halProxSensorCovered()) { //Check Waterlevel
|
|
|
+ //turn machine on
|
|
|
+ logger(V_BREW, "Turn machine on\n");
|
|
|
+ halRelaisOn(RELAIS_HEAT);
|
|
|
+ halRelaisOff(RELAIS_PUMP);
|
|
|
+ halRelaisOn(RELAIS_POWER);
|
|
|
+ sleep(1);
|
|
|
+ if (halIsHeating()) { //check if System starts to heat when turned on
|
|
|
+ logger(V_BREW, "Change state: INITALHEATING\n");
|
|
|
+ state = STATE_INITALHEATING;
|
|
|
+ } else {
|
|
|
+ logger(V_BREW, "Change state: IDLE\n");
|
|
|
+ state = STATE_IDLE;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ logger(V_BREW, "Change state: ERROR\n");
|
|
|
+ state = STATE_ERROR;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case STATE_INITALHEATING:
|
|
|
+ pause();
|
|
|
+ switch (getSigValue()) {
|
|
|
+ case SigInt1Rls:
|
|
|
+ //Turn machine off again
|
|
|
+ halRelaisOff(RELAIS_HEAT);
|
|
|
+ halRelaisOff(RELAIS_PUMP);
|
|
|
+ halRelaisOff(RELAIS_POWER);
|
|
|
+ logger(V_BREW, "Change state: OFF\n");
|
|
|
+ state = STATE_OFF;
|
|
|
+ break;
|
|
|
+ case SigPressOpn:
|
|
|
+ //Inital heating finished
|
|
|
+ logger(V_BREW, "Change state: IDLE\n");
|
|
|
+ state = STATE_IDLE;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case STATE_HEATING:
|
|
|
+ pause();
|
|
|
+ switch(getSigValue()){
|
|
|
+ case SigInt1Rls:
|
|
|
+ //Turn machine off again
|
|
|
+ halRelaisOff(RELAIS_HEAT);
|
|
|
+ halRelaisOff(RELAIS_PUMP);
|
|
|
+ halRelaisOff(RELAIS_POWER);
|
|
|
+ logger(V_BREW, "Change state: OFF\n");
|
|
|
+ state = STATE_OFF;
|
|
|
+ break;
|
|
|
+ case SigPressOpn:
|
|
|
+ logger(V_BREW, "Change state: IDLE\n");
|
|
|
+ state = STATE_IDLE;
|
|
|
+ break;
|
|
|
+ case SigInt0Psh:
|
|
|
+ //start to brew a delicious coffee
|
|
|
+ logger(V_BREW, "Change state: BREW\n");
|
|
|
+ state = STATE_BREW;
|
|
|
+ break;
|
|
|
+ case SigBrewOn:
|
|
|
+ //someone brews manually
|
|
|
+ logger(V_BREW, "Change state: BREWMANUAL\n");
|
|
|
+ state = STATE_BREWMANUAL;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case STATE_IDLE:
|
|
|
+ pause();
|
|
|
+ switch(getSigValue()){
|
|
|
+ case SigInt1Rls:
|
|
|
+ //Turn machine off again
|
|
|
+ halRelaisOff(RELAIS_HEAT);
|
|
|
+ halRelaisOff(RELAIS_PUMP);
|
|
|
+ halRelaisOff(RELAIS_POWER);
|
|
|
+ logger(V_BREW, "Change state: OFF\n");
|
|
|
+ state = STATE_OFF;
|
|
|
+ break;
|
|
|
+ case SigPressCls:
|
|
|
+ logger(V_BREW, "Change state: HEATING\n");
|
|
|
+ state = STATE_HEATING;
|
|
|
+ break;
|
|
|
+ case SigInt0Psh:
|
|
|
+ //start to brew a delicious coffee
|
|
|
+ logger(V_BREW, "Change state: BREW\n");
|
|
|
+ state = STATE_BREW;
|
|
|
+ break;
|
|
|
+ case SigBrewOn:
|
|
|
+ //someone brews manually
|
|
|
+ logger(V_BREW, "Change state: BREWMANUAL\n");
|
|
|
+ state = STATE_BREWMANUAL;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case STATE_BREW:
|
|
|
+ //Preinfusion
|
|
|
+ logger(V_BREW, "Starting preinfusion...\n");
|
|
|
+ halRelaisOn(RELAIS_PUMP);
|
|
|
+ brewTime = 0;
|
|
|
+ brewTimer.start();
|
|
|
+ while(brewTime < TIME_PREINFUSION){
|
|
|
+ usleep(100000);
|
|
|
+ }
|
|
|
+ brewTimer.stop();
|
|
|
+ brewTime = 0;
|
|
|
+ halRelaisOff(RELAIS_PUMP);
|
|
|
+ sleep(TIME_SOAK/1000);
|
|
|
+ logger(V_BREW, "Starting infusion...\n");
|
|
|
+ halResetFlow();
|
|
|
+ halRelaisOn(RELAIS_PUMP);
|
|
|
+ brewTimer.start();
|
|
|
+ while(brewTime < TIME_INFUSION && halGetFlow() < TIME_DBLESPRESSO){
|
|
|
+ usleep(100000);
|
|
|
+ }
|
|
|
+ halRelaisOff(RELAIS_PUMP);
|
|
|
+ brewTimer.stop();
|
|
|
+ brewTime = 0;
|
|
|
+ logger(V_BREW, "Finish brewing\n");
|
|
|
+ logger(V_BREW, "Change state: IDLE\n");
|
|
|
+ state = STATE_IDLE;
|
|
|
+ break;
|
|
|
+ case STATE_BREWMANUAL:
|
|
|
+ pause();
|
|
|
+ break;
|
|
|
+ case STATE_CLEANING:
|
|
|
+ pause();
|
|
|
+ break;
|
|
|
+ case STATE_ERROR:
|
|
|
+ pause();
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ pthread_exit(EXIT_SUCCESS);
|
|
|
+}
|
|
|
+/*
|
|
|
+ * Saves value delivered by the signal
|
|
|
+ */
|
|
|
+void coffeeHandler(int signum, siginfo_t *siginfo, void *context) {
|
|
|
+ sigval_t sigVal = (siginfo->si_value);
|
|
|
+ sigValue = sigVal.sival_int;
|
|
|
+ logger(V_BREW, "CoffeeHandler called with %d\n", sigValue);
|
|
|
+}
|
|
|
+/*
|
|
|
+ * returns the Signal value from the last received Signal and clears the variable
|
|
|
+ */
|
|
|
+int getSigValue(void){
|
|
|
+ int tmp = sigValue;
|
|
|
+ sigValue = 0;
|
|
|
+ return tmp;
|
|
|
+}
|
|
|
+/*
|
|
|
+ * Counter for the brew time
|
|
|
+ * refresh every 200ms
|
|
|
+ */
|
|
|
+void brewTimeHandler (void){
|
|
|
+ brewTime += 200;
|
|
|
+}
|