hal.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. /*
  2. * hal.cpp
  3. *
  4. * Created on: Aug 3, 2016
  5. * Author: Philipp Hinz, Sebastian Vendt
  6. */
  7. #include <wiringPi.h>
  8. #include <stdlib.h>
  9. #include <errno.h>
  10. #include <string.h>
  11. #include <signal.h>
  12. #include <ctime>
  13. #include "hal.h"
  14. #include "global.h"
  15. #include "logger.h"
  16. #include "timer.h"
  17. volatile int flowcnt = 0;
  18. int Int0Time, Int1Time;
  19. bool flagIgnoreRlsInt0, flagIgnoreRlsInt1;
  20. //storage for the last state of the buttons and the proximity sensor
  21. int pinState[3] = {0, 0, 0};
  22. timer Int0Timer(&halInt0TimerHandler);
  23. timer Int1Timer(&halInt1TimerHandler);
  24. clock_t heatingCycle[2] = {0, 0};
  25. //delay of the debounce in milliseconds
  26. #define DELAY_DEBOUNCE 50
  27. /**
  28. * Initializes HAL
  29. */
  30. void halInit(void) {
  31. pinMode(RELAIS_HEAT, OUTPUT);
  32. pinMode(RELAIS_PUMP, OUTPUT);
  33. pinMode(RELAIS_POWER, OUTPUT);
  34. pinMode(PIN_PRESSURE_CTRL, INPUT);
  35. pinMode(PIN_PROXIMITY_SENSOR, INPUT);
  36. pinMode(PIN_INT0, INPUT);
  37. pinMode(PIN_INT1, INPUT);
  38. pinMode(PIN_FLOW, INPUT);
  39. pinMode(PIN_DISP, OUTPUT);
  40. if (optPower) {
  41. halMachineOn();
  42. } else {
  43. halMachineOff();
  44. }
  45. Int0Timer.setDivider(4); //200ms
  46. Int1Timer.setDivider(4);
  47. Int0Time = 0;
  48. Int1Time = 0;
  49. flagIgnoreRlsInt0 = false;
  50. flagIgnoreRlsInt1 = false;
  51. if (wiringPiISR(PIN_INT0, INT_EDGE_BOTH, &halInt0) < 0) {
  52. logger_error("Unable to setup ISR0: %s\n", strerror(errno));
  53. return;
  54. }
  55. if (wiringPiISR(PIN_INT1, INT_EDGE_BOTH, &halInt1) < 0) {
  56. logger_error("Unable to setup ISR1: %s\n", strerror(errno));
  57. return;
  58. }
  59. if (wiringPiISR(PIN_FLOW, INT_EDGE_FALLING, &halIntFlow) < 0) {
  60. logger_error("Unable to setup ISRFLOW: %s\n", strerror(errno));
  61. return;
  62. }
  63. if (wiringPiISR(PIN_PRESSURE_CTRL, INT_EDGE_BOTH, &halIntPressure) < 0) {
  64. logger_error("Unable to setup ISRPressure: %s\n", strerror(errno));
  65. return;
  66. }
  67. if (wiringPiISR(PIN_PROXIMITY_SENSOR, INT_EDGE_BOTH, &halIntProximity) < 0) {
  68. logger_error("Unable to setup ISRProximity: %s\n", strerror(errno));
  69. return;
  70. }
  71. }
  72. /**
  73. * Switches relais on
  74. * @param relais Relais ID
  75. */
  76. void halRelaisOn(int relais) {
  77. halRelaisSet(relais, LOW);
  78. }
  79. /**
  80. * Turn the display off
  81. */
  82. void halDisplayOff(){
  83. digitalWrite(PIN_DISP, LOW);
  84. }
  85. /**
  86. * Turn the display on
  87. */
  88. void halDisplayOn(){
  89. digitalWrite(PIN_DISP, HIGH);
  90. }
  91. /**
  92. * Switches relais off
  93. * @param relais Relais ID
  94. */
  95. void halRelaisOff(int relais) {
  96. halRelaisSet(relais, HIGH);
  97. }
  98. /**
  99. * Switches relais to state
  100. * @param relais Relais ID
  101. * @param state LOW(0) or HIGH(1)
  102. */
  103. void halRelaisSet(int relais, int state) {
  104. if (state != HIGH && state != LOW)
  105. return;
  106. switch (relais) {
  107. case RELAIS_POWER:
  108. case RELAIS_HEAT:
  109. case RELAIS_PUMP:
  110. digitalWrite(relais, state);
  111. break;
  112. }
  113. }
  114. /**
  115. * Returns the state of the relais relais
  116. * Returns HIGH when Relais is ON
  117. * @param relais Relais ID
  118. */
  119. int halGetRelaisState(int relais) {
  120. switch (relais) {
  121. case RELAIS_POWER:
  122. case RELAIS_HEAT:
  123. case RELAIS_PUMP:
  124. return !digitalRead(relais);
  125. break;
  126. }
  127. return -1;
  128. }
  129. /**
  130. * Interrupt routine for Int0 (Top button)
  131. */
  132. void halInt0(void) {
  133. //wait for a debounce
  134. delay(DELAY_DEBOUNCE);
  135. if (halGetInt0() && !pinState[0]) { //released
  136. logger(V_HAL, "Int0 released\n");
  137. pinState[0] = 1;
  138. if (flagIgnoreRlsInt0) {
  139. flagIgnoreRlsInt0 = false;
  140. } else {
  141. Int0Time = 0;
  142. Int0Timer.stop();
  143. halSendSignal(SigInt0Rls);
  144. }
  145. } else if(!halGetInt0() && pinState[0]) { //pressed
  146. logger(V_HAL, "Int0 pushed\n");
  147. pinState[0] = 0;
  148. halSendSignal(SigInt0Psh);
  149. Int0Time = 0;
  150. Int0Timer.start();
  151. }
  152. }
  153. /**
  154. *
  155. */
  156. void halInt0TimerHandler(void) {
  157. Int0Time += 200;
  158. if (Int0Time >= (TIME_BUTTONLONGPRESS * 1000)) {
  159. halSendSignal(SigInt0RlsLong);
  160. flagIgnoreRlsInt0 = true;
  161. Int0Time = 0;
  162. Int0Timer.stop();
  163. }
  164. }
  165. /**
  166. * Interrupt routine for Int1 (Bottom button)
  167. */
  168. void halInt1(void) {
  169. delay(DELAY_DEBOUNCE);
  170. if (halGetInt1() && !pinState[1]) {
  171. logger(V_HAL, "Int1 released\n");
  172. pinState[1] = 1;
  173. if (flagIgnoreRlsInt1) {
  174. flagIgnoreRlsInt1 = false;
  175. } else {
  176. Int0Time = 0;
  177. Int0Timer.stop();
  178. halSendSignal(SigInt1Rls);
  179. }
  180. } else if(!halGetInt1() && pinState[1]) {
  181. logger(V_HAL, "Int1 pushed\n");
  182. pinState[1] = 0;
  183. halSendSignal(SigInt1Psh);
  184. Int1Time = 0;
  185. Int1Timer.start();
  186. }
  187. }
  188. /*
  189. *
  190. */
  191. void halInt1TimerHandler(void) {
  192. Int1Time += 200;
  193. if (Int1Time >= (TIME_BUTTONLONGPRESS * 1000)) {
  194. halSendSignal(SigInt1RlsLong);
  195. flagIgnoreRlsInt1 = true;
  196. Int1Time = 0;
  197. Int1Timer.stop();
  198. }
  199. }
  200. /**
  201. * Interrupt routine for the flow sensor
  202. * It counts the edgdes and stores the value in flowcnt
  203. */
  204. void halIntFlow(void) {
  205. //halRelaisOff(RELAIS_POWER);
  206. logger(V_HAL, "IntFlow triggered #%d total: %.2fml\n", flowcnt, halGetFlow());
  207. if (flowcnt == 99) {
  208. halRelaisOff(RELAIS_PUMP);
  209. }
  210. flowcnt++;
  211. }
  212. /**
  213. * Interrupt routine for the pressure control
  214. * It captures the time at closing point and opening point
  215. * Reading heating time via the getHeatingTime function
  216. */
  217. void halIntPressure(void) {
  218. logger(V_HAL, "IntPressure Control triggered\n");
  219. if (halIsHeating()) {
  220. heatingCycle[0] = clock();
  221. halSendSignal(SigPressCls);
  222. } else {
  223. heatingCycle[1] = clock();
  224. halSendSignal(SigPressOpn);
  225. }
  226. }
  227. /**
  228. * Function to read the heating time in sec
  229. * If called during a heating process, it returns the time elapsed since the heating started
  230. * If called after a heating process, it returns the total time elapes during the heating cycle
  231. */
  232. double halgetHeatingTime(void){
  233. if (halIsHeating()) {
  234. return (double)(clock() - heatingCycle[0]) / CLOCKS_PER_SEC;
  235. }
  236. else {
  237. return (double)(heatingCycle[1] - heatingCycle[0]) / CLOCKS_PER_SEC;
  238. }
  239. }
  240. /**
  241. * Method to handle toggle of the proximity sensor
  242. */
  243. void halIntProximity(void) {
  244. delay(DELAY_DEBOUNCE);
  245. if (halProxSensorCovered() && !pinState[2]) {
  246. logger(V_HAL, "IntProximity triggered\n");
  247. pinState[2] = 1;
  248. halSendSignal(SigProxCvrd);
  249. } else if(!halProxSensorCovered() && pinState[2]){
  250. logger(V_HAL, "IntProximity triggered\n");
  251. pinState[2] = 0;
  252. halSendSignal(SigProxOpn);
  253. }
  254. }
  255. /**
  256. * Returns total flow trough sensor in ml
  257. */
  258. float halGetFlow(void) {
  259. return flowcnt * FLOW_ML_PULSE;
  260. }
  261. /**
  262. * Resets the Flow counter
  263. */
  264. void halResetFlow(void) {
  265. logger(V_HAL, "Flow counter reset, amount so far: %.2f ml\n", halGetFlow());
  266. flowcnt = 0;
  267. }
  268. /**
  269. * Reads the status of the Pressure Control
  270. * @return 1 (true) for closed Pressure Control(heating) and 0 (false) for open
  271. */
  272. bool halIsHeating(void) {
  273. if (digitalRead(PIN_PRESSURE_CTRL) == 0) {
  274. return true;
  275. } else {
  276. return false;
  277. }
  278. }
  279. /**
  280. * Returns status of the proximity switch
  281. * @return 1 if the proximity switch is covered and 0 if uncovered
  282. */
  283. bool halProxSensorCovered(void) {
  284. if(digitalRead(PIN_PROXIMITY_SENSOR) == 0){
  285. return false;
  286. } else {
  287. return true;
  288. }
  289. }
  290. /**
  291. * Returns the value of the top button Int0 (low active)
  292. * @return LOW or HIGH
  293. */
  294. int halGetInt0(void) {
  295. return digitalRead(PIN_INT0);
  296. }
  297. /**
  298. * Returns the value of the bottom button Int1 (low active)
  299. * @return LOW or HIGH
  300. */
  301. int halGetInt1(void) {
  302. return digitalRead(PIN_INT1);
  303. }
  304. /**
  305. * send Signal to coffee thread
  306. * @param val Integer value assigned to signal
  307. */
  308. void halSendSignal(HalSig val) {
  309. sigval value = { 0 };
  310. value.sival_int = (int) val;
  311. try {
  312. if (pthread_sigqueue(thread[THREAD_COFFEE], SIGUSR2, value)) {
  313. logger_error("hal.cpp: Failed to queue signal %d %s\n", val,
  314. strerror(errno));
  315. //No Signals reach the state machine anymore...
  316. exit(EXIT_FAILURE);
  317. }
  318. } catch (int e) {
  319. logger_error("Whoops.. %d\n", e);
  320. }
  321. }
  322. /**
  323. * Turn machine on
  324. */
  325. void halMachineOn(void) {
  326. halRelaisOn(RELAIS_HEAT);
  327. halRelaisOff(RELAIS_PUMP);
  328. halRelaisOn(RELAIS_POWER);
  329. logger(V_HAL, "Turning machine on\n");
  330. }
  331. /**
  332. * Turn machine off
  333. */
  334. void halMachineOff(void) {
  335. halRelaisOff(RELAIS_HEAT);
  336. halRelaisOff(RELAIS_PUMP);
  337. halRelaisOff(RELAIS_POWER);
  338. logger(V_HAL, "Turning machine off\n");
  339. }