coffee.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. /*
  2. * coffee.cpp
  3. *
  4. * Created on: Sep 25, 2017
  5. * Author: sebastian
  6. */
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <errno.h>
  11. #include <stdint.h>
  12. #include <wiringPi.h>
  13. #include <pthread.h>
  14. #include <unistd.h>
  15. #include <iostream>
  16. #include <csignal>
  17. #include <time.h>
  18. #include "coffee.h"
  19. #include "hal.h"
  20. #include "logger.h"
  21. #include "timer.h"
  22. int state;
  23. int sigValue;
  24. int brewTime; //Brew time in ms
  25. timer brewTimer(&brewTimeHandler);
  26. /**
  27. * Thread for the finite state machine
  28. * It represents the current state of the machine and handles signals coming from
  29. * the pressure control, buttons, the brew switch and the proximity sensor
  30. * @param threadid the ID of the thread
  31. */
  32. void *coffeeThread(void *threadid) {
  33. logger(V_BASIC, "Initializing coffee thread...\n");
  34. //installing new Signal handler for coffeethread
  35. struct sigaction action;
  36. sigemptyset(&action.sa_mask);
  37. action.sa_flags = SA_SIGINFO;
  38. action.sa_sigaction = coffeeHandler;
  39. sigaction(SIGUSR2, &action, NULL);
  40. brewTimer.setDivider(4);
  41. brewTimer.stop();
  42. brewTime = 0;
  43. state = STATE_OFF;
  44. logger(V_BREW, "Determining inital state\n");
  45. //determine inital state
  46. if (halGetRelaisState(RELAIS_POWER) && halGetRelaisState(RELAIS_HEAT) && !halGetRelaisState(RELAIS_PUMP)) {
  47. //wait for heat relais to switch
  48. sleep(1);
  49. if (halIsHeating()) { //Heating is on
  50. changeState(STATE_INITALHEATING);
  51. } else {
  52. changeState(STATE_IDLE);
  53. }
  54. } else if (halGetRelaisState(RELAIS_PUMP)) {
  55. logger_error("Whoops, why is the pump running...\n");
  56. changeState(STATE_ERROR);
  57. }
  58. logger(V_BREW, "Start Coffee FSM\n");
  59. //begin FSM
  60. while(1){
  61. switch(state){
  62. case STATE_OFF:
  63. pause();
  64. if (getSigValue() == SigInt0Rls) {
  65. if (halProxSensorCovered()) { //Check Waterlevel
  66. //turn machine on
  67. logger(V_BREW, "Turn machine on\n");
  68. halRelaisOn(RELAIS_HEAT);
  69. halRelaisOff(RELAIS_PUMP);
  70. halRelaisOn(RELAIS_POWER);
  71. sleep(1);
  72. if (halIsHeating()) { //check if System starts to heat when turned on
  73. changeState(STATE_INITALHEATING);
  74. } else {
  75. changeState(STATE_IDLE);
  76. }
  77. } else {
  78. changeState(STATE_ERROR);
  79. }
  80. break;
  81. }
  82. break;
  83. case STATE_INITALHEATING:
  84. pause();
  85. switch (getSigValue()) {
  86. case SigInt1Rls:
  87. //Turn machine off again
  88. logger(V_BREW, "Turn machine off\n");
  89. halRelaisOff(RELAIS_HEAT);
  90. halRelaisOff(RELAIS_PUMP);
  91. halRelaisOff(RELAIS_POWER);
  92. changeState(STATE_OFF);
  93. break;
  94. case SigPressOpn:
  95. //Inital heating finished
  96. changeState(STATE_IDLE);
  97. break;
  98. }
  99. break;
  100. case STATE_HEATING:
  101. pause();
  102. switch(getSigValue()){
  103. case SigInt1Rls:
  104. //Turn machine off again
  105. logger(V_BREW, "Turn machine off\n");
  106. halRelaisOff(RELAIS_HEAT);
  107. halRelaisOff(RELAIS_PUMP);
  108. halRelaisOff(RELAIS_POWER);
  109. changeState(STATE_OFF);
  110. break;
  111. case SigPressOpn:
  112. logger(V_BREW, "Change state: IDLE\n");
  113. changeState(STATE_IDLE);
  114. break;
  115. case SigInt0Psh:
  116. //start to brew a delicious coffee
  117. changeState(STATE_BREW);
  118. break;
  119. case SigBrewOn:
  120. //someone brews manually
  121. changeState(STATE_BREWMANUAL);
  122. break;
  123. }
  124. break;
  125. case STATE_IDLE:
  126. pause();
  127. switch(getSigValue()){
  128. case SigInt1Rls:
  129. //Turn machine off again
  130. logger(V_BREW, "Turn machine off\n");
  131. halRelaisOff(RELAIS_HEAT);
  132. halRelaisOff(RELAIS_PUMP);
  133. halRelaisOff(RELAIS_POWER);
  134. changeState(STATE_OFF);
  135. break;
  136. case SigPressCls:
  137. changeState(STATE_HEATING);
  138. break;
  139. case SigInt0Psh:
  140. //start to brew a delicious coffee
  141. changeState(STATE_BREW);
  142. break;
  143. case SigBrewOn:
  144. //someone brews manually
  145. changeState(STATE_BREWMANUAL);
  146. break;
  147. }
  148. break;
  149. case STATE_BREW:
  150. //Preinfusion
  151. logger(V_BREW, "Starting preinfusion...\n");
  152. halRelaisOn(RELAIS_PUMP);
  153. brewTime = 0;
  154. brewTimer.start();
  155. while(brewTime < TIME_PREINFUSION){
  156. usleep(100000);
  157. }
  158. brewTimer.stop();
  159. brewTime = 0;
  160. halRelaisOff(RELAIS_PUMP);
  161. sleep(TIME_SOAK/1000);
  162. logger(V_BREW, "Starting infusion...\n");
  163. halResetFlow();
  164. halRelaisOn(RELAIS_PUMP);
  165. brewTimer.start();
  166. while(brewTime < TIME_INFUSION && halGetFlow() < TIME_DBLESPRESSO){
  167. usleep(100000);
  168. }
  169. halRelaisOff(RELAIS_PUMP);
  170. brewTimer.stop();
  171. brewTime = 0;
  172. logger(V_BREW, "Finish brewing\n");
  173. changeState(STATE_IDLE);
  174. break;
  175. case STATE_BREWMANUAL:
  176. pause();
  177. break;
  178. case STATE_CLEANING:
  179. pause();
  180. break;
  181. case STATE_ERROR:
  182. pause();
  183. break;
  184. }
  185. }
  186. pthread_exit(EXIT_SUCCESS);
  187. }
  188. /**
  189. * Handler for the Signal send to this thread
  190. * It safes a value sent with the signal in sigValue
  191. * @param signum
  192. * @param siginfo
  193. * @param context
  194. */
  195. void coffeeHandler(int signum, siginfo_t *siginfo, void *context) {
  196. sigval_t sigVal = (siginfo->si_value);
  197. sigValue = sigVal.sival_int;
  198. logger(V_BREW, "CoffeeHandler called with %d\n", sigValue);
  199. }
  200. /**
  201. * returns the Signal value from the last received Signal and clears the variable
  202. * @return value sent with the last signal
  203. */
  204. int getSigValue(void){
  205. int tmp = sigValue;
  206. sigValue = 0;
  207. return tmp;
  208. }
  209. /**
  210. * Changes the state of the machine to newState
  211. * prints the change to the logger
  212. * @param newState
  213. */
  214. void changeState(int newState){
  215. logger(V_BREW, "Change state to %d\n", newState);
  216. state = newState;
  217. }
  218. /**
  219. * Counter for the brew time
  220. * refresh every 200ms
  221. */
  222. void brewTimeHandler (void){
  223. brewTime += 200;
  224. }