coffee.cpp 5.6 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_BREW, "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. logger(V_BREW, "Change state: INITALHEATING\n");
  51. state = STATE_INITALHEATING;
  52. } else {
  53. logger(V_BREW, "Change state: IDLE\n");
  54. state = STATE_IDLE;
  55. }
  56. } else if (halGetRelaisState(RELAIS_PUMP)) {
  57. logger_error("Whoops, why is the pump running...\n");
  58. state = STATE_ERROR;
  59. }
  60. logger(V_BREW, "Start Coffee FSM\n");
  61. //begin FSM
  62. while(1){
  63. switch(state){
  64. case STATE_OFF:
  65. pause();
  66. if (getSigValue() == SigInt0Rls) {
  67. if (halProxSensorCovered()) { //Check Waterlevel
  68. //turn machine on
  69. logger(V_BREW, "Turn machine on\n");
  70. halRelaisOn(RELAIS_HEAT);
  71. halRelaisOff(RELAIS_PUMP);
  72. halRelaisOn(RELAIS_POWER);
  73. sleep(1);
  74. if (halIsHeating()) { //check if System starts to heat when turned on
  75. logger(V_BREW, "Change state: INITALHEATING\n");
  76. state = STATE_INITALHEATING;
  77. } else {
  78. logger(V_BREW, "Change state: IDLE\n");
  79. state = STATE_IDLE;
  80. }
  81. } else {
  82. logger(V_BREW, "Change state: ERROR\n");
  83. state = STATE_ERROR;
  84. }
  85. break;
  86. }
  87. break;
  88. case STATE_INITALHEATING:
  89. pause();
  90. switch (getSigValue()) {
  91. case SigInt1Rls:
  92. //Turn machine off again
  93. halRelaisOff(RELAIS_HEAT);
  94. halRelaisOff(RELAIS_PUMP);
  95. halRelaisOff(RELAIS_POWER);
  96. logger(V_BREW, "Change state: OFF\n");
  97. state = STATE_OFF;
  98. break;
  99. case SigPressOpn:
  100. //Inital heating finished
  101. logger(V_BREW, "Change state: IDLE\n");
  102. state = STATE_IDLE;
  103. break;
  104. }
  105. break;
  106. case STATE_HEATING:
  107. pause();
  108. switch(getSigValue()){
  109. case SigInt1Rls:
  110. //Turn machine off again
  111. halRelaisOff(RELAIS_HEAT);
  112. halRelaisOff(RELAIS_PUMP);
  113. halRelaisOff(RELAIS_POWER);
  114. logger(V_BREW, "Change state: OFF\n");
  115. state = STATE_OFF;
  116. break;
  117. case SigPressOpn:
  118. logger(V_BREW, "Change state: IDLE\n");
  119. state = STATE_IDLE;
  120. break;
  121. case SigInt0Psh:
  122. //start to brew a delicious coffee
  123. logger(V_BREW, "Change state: BREW\n");
  124. state = STATE_BREW;
  125. break;
  126. case SigBrewOn:
  127. //someone brews manually
  128. logger(V_BREW, "Change state: BREWMANUAL\n");
  129. state = STATE_BREWMANUAL;
  130. break;
  131. }
  132. break;
  133. case STATE_IDLE:
  134. pause();
  135. switch(getSigValue()){
  136. case SigInt1Rls:
  137. //Turn machine off again
  138. halRelaisOff(RELAIS_HEAT);
  139. halRelaisOff(RELAIS_PUMP);
  140. halRelaisOff(RELAIS_POWER);
  141. logger(V_BREW, "Change state: OFF\n");
  142. state = STATE_OFF;
  143. break;
  144. case SigPressCls:
  145. logger(V_BREW, "Change state: HEATING\n");
  146. state = STATE_HEATING;
  147. break;
  148. case SigInt0Psh:
  149. //start to brew a delicious coffee
  150. logger(V_BREW, "Change state: BREW\n");
  151. state = STATE_BREW;
  152. break;
  153. case SigBrewOn:
  154. //someone brews manually
  155. logger(V_BREW, "Change state: BREWMANUAL\n");
  156. state = STATE_BREWMANUAL;
  157. break;
  158. }
  159. break;
  160. case STATE_BREW:
  161. //Preinfusion
  162. logger(V_BREW, "Starting preinfusion...\n");
  163. halRelaisOn(RELAIS_PUMP);
  164. brewTime = 0;
  165. brewTimer.start();
  166. while(brewTime < TIME_PREINFUSION){
  167. usleep(100000);
  168. }
  169. brewTimer.stop();
  170. brewTime = 0;
  171. halRelaisOff(RELAIS_PUMP);
  172. sleep(TIME_SOAK/1000);
  173. logger(V_BREW, "Starting infusion...\n");
  174. halResetFlow();
  175. halRelaisOn(RELAIS_PUMP);
  176. brewTimer.start();
  177. while(brewTime < TIME_INFUSION && halGetFlow() < TIME_DBLESPRESSO){
  178. usleep(100000);
  179. }
  180. halRelaisOff(RELAIS_PUMP);
  181. brewTimer.stop();
  182. brewTime = 0;
  183. logger(V_BREW, "Finish brewing\n");
  184. logger(V_BREW, "Change state: IDLE\n");
  185. state = STATE_IDLE;
  186. break;
  187. case STATE_BREWMANUAL:
  188. pause();
  189. break;
  190. case STATE_CLEANING:
  191. pause();
  192. break;
  193. case STATE_ERROR:
  194. pause();
  195. break;
  196. }
  197. }
  198. pthread_exit(EXIT_SUCCESS);
  199. }
  200. /**
  201. * Handler for the Signal send to this thread
  202. * It safes a value sent with the signal in sigValue
  203. * @param signum
  204. * @param siginfo
  205. * @param context
  206. */
  207. void coffeeHandler(int signum, siginfo_t *siginfo, void *context) {
  208. sigval_t sigVal = (siginfo->si_value);
  209. sigValue = sigVal.sival_int;
  210. logger(V_BREW, "CoffeeHandler called with %d\n", sigValue);
  211. }
  212. /**
  213. * returns the Signal value from the last received Signal and clears the variable
  214. * @return value sent with the last signal
  215. */
  216. int getSigValue(void){
  217. int tmp = sigValue;
  218. sigValue = 0;
  219. return tmp;
  220. }
  221. /**
  222. * Counter for the brew time
  223. * refresh every 200ms
  224. */
  225. void brewTimeHandler (void){
  226. brewTime += 200;
  227. }