/* * hal.cpp * * Created on: Aug 3, 2016 * Author: Philipp Hinz, Sebastian Vendt */ #include #include #include #include #include #include #include "hal.h" #include "global.h" #include "logger.h" #include "timer.h" volatile int flowcnt = 0; int Int0Time, Int1Time; bool flagIgnoreRlsInt0, flagIgnoreRlsInt1; //storage for the last state of the buttons and the proximity sensor int pinState[3] = {0, 0, 0}; timer Int0Timer(&halInt0TimerHandler); timer Int1Timer(&halInt1TimerHandler); clock_t heatingCycle[2] = {0, 0}; //delay of the debounce in milliseconds #define DELAY_DEBOUNCE 50 /** * Initializes HAL */ void halInit(void) { pinMode(RELAIS_HEAT, OUTPUT); pinMode(RELAIS_PUMP, OUTPUT); pinMode(RELAIS_POWER, OUTPUT); pinMode(PIN_PRESSURE_CTRL, INPUT); pinMode(PIN_PROXIMITY_SENSOR, INPUT); pinMode(PIN_INT0, INPUT); pinMode(PIN_INT1, INPUT); pinMode(PIN_FLOW, INPUT); pinMode(PIN_DISP, OUTPUT); if (optPower) { halMachineOn(); } else { halMachineOff(); } Int0Timer.setDivider(4); //200ms Int1Timer.setDivider(4); Int0Time = 0; Int1Time = 0; flagIgnoreRlsInt0 = false; flagIgnoreRlsInt1 = false; if (wiringPiISR(PIN_INT0, INT_EDGE_BOTH, &halInt0) < 0) { logger_error("Unable to setup ISR0: %s\n", strerror(errno)); return; } if (wiringPiISR(PIN_INT1, INT_EDGE_BOTH, &halInt1) < 0) { logger_error("Unable to setup ISR1: %s\n", strerror(errno)); return; } if (wiringPiISR(PIN_FLOW, INT_EDGE_FALLING, &halIntFlow) < 0) { logger_error("Unable to setup ISRFLOW: %s\n", strerror(errno)); return; } if (wiringPiISR(PIN_PRESSURE_CTRL, INT_EDGE_BOTH, &halIntPressure) < 0) { logger_error("Unable to setup ISRPressure: %s\n", strerror(errno)); return; } if (wiringPiISR(PIN_PROXIMITY_SENSOR, INT_EDGE_BOTH, &halIntProximity) < 0) { logger_error("Unable to setup ISRProximity: %s\n", strerror(errno)); return; } } /** * Switches relais on * @param relais Relais ID */ void halRelaisOn(int relais) { halRelaisSet(relais, LOW); } /** * Turn the display off */ void halDisplayOff(){ digitalWrite(PIN_DISP, LOW); } /** * Turn the display on */ void halDisplayOn(){ digitalWrite(PIN_DISP, HIGH); } /** * Switches relais off * @param relais Relais ID */ void halRelaisOff(int relais) { halRelaisSet(relais, HIGH); } /** * Switches relais to state * @param relais Relais ID * @param state LOW(0) or HIGH(1) */ void halRelaisSet(int relais, int state) { if (state != HIGH && state != LOW) return; switch (relais) { case RELAIS_POWER: case RELAIS_HEAT: case RELAIS_PUMP: digitalWrite(relais, state); break; } } /** * Returns the state of the relais relais * Returns HIGH when Relais is ON * @param relais Relais ID */ int halGetRelaisState(int relais) { switch (relais) { case RELAIS_POWER: case RELAIS_HEAT: case RELAIS_PUMP: return !digitalRead(relais); break; } return -1; } /** * Interrupt routine for Int0 (Top button) */ void halInt0(void) { //wait for a debounce delay(DELAY_DEBOUNCE); if (halGetInt0() && !pinState[0]) { //released logger(V_HAL, "Int0 released\n"); pinState[0] = 1; if (flagIgnoreRlsInt0) { flagIgnoreRlsInt0 = false; } else { Int0Time = 0; Int0Timer.stop(); halSendSignal(SigInt0Rls); } } else if(!halGetInt0() && pinState[0]) { //pressed logger(V_HAL, "Int0 pushed\n"); pinState[0] = 0; halSendSignal(SigInt0Psh); Int0Time = 0; Int0Timer.start(); } } /** * */ void halInt0TimerHandler(void) { Int0Time += 200; if (Int0Time >= (TIME_BUTTONLONGPRESS * 1000)) { halSendSignal(SigInt0RlsLong); flagIgnoreRlsInt0 = true; Int0Time = 0; Int0Timer.stop(); } } /** * Interrupt routine for Int1 (Bottom button) */ void halInt1(void) { delay(DELAY_DEBOUNCE); if (halGetInt1() && !pinState[1]) { logger(V_HAL, "Int1 released\n"); pinState[1] = 1; if (flagIgnoreRlsInt1) { flagIgnoreRlsInt1 = false; } else { Int0Time = 0; Int0Timer.stop(); halSendSignal(SigInt1Rls); } } else if(!halGetInt1() && pinState[1]) { logger(V_HAL, "Int1 pushed\n"); pinState[1] = 0; halSendSignal(SigInt1Psh); Int1Time = 0; Int1Timer.start(); } } /* * */ void halInt1TimerHandler(void) { Int1Time += 200; if (Int1Time >= (TIME_BUTTONLONGPRESS * 1000)) { halSendSignal(SigInt1RlsLong); flagIgnoreRlsInt1 = true; Int1Time = 0; Int1Timer.stop(); } } /** * Interrupt routine for the flow sensor * It counts the edgdes and stores the value in flowcnt */ void halIntFlow(void) { //halRelaisOff(RELAIS_POWER); logger(V_HAL, "IntFlow triggered #%d total: %.2fml\n", flowcnt, halGetFlow()); if (flowcnt == 99) { halRelaisOff(RELAIS_PUMP); } flowcnt++; } /** * Interrupt routine for the pressure control * It captures the time at closing point and opening point * Reading heating time via the getHeatingTime function */ void halIntPressure(void) { logger(V_HAL, "IntPressure Control triggered\n"); if (halIsHeating()) { heatingCycle[0] = clock(); halSendSignal(SigPressCls); } else { heatingCycle[1] = clock(); halSendSignal(SigPressOpn); } } /** * Function to read the heating time in sec * If called during a heating process, it returns the time elapsed since the heating started * If called after a heating process, it returns the total time elapes during the heating cycle */ double halgetHeatingTime(void){ if (halIsHeating()) { return (double)(clock() - heatingCycle[0]) / CLOCKS_PER_SEC; } else { return (double)(heatingCycle[1] - heatingCycle[0]) / CLOCKS_PER_SEC; } } /** * Method to handle toggle of the proximity sensor */ void halIntProximity(void) { delay(DELAY_DEBOUNCE); if (halProxSensorCovered() && !pinState[2]) { logger(V_HAL, "IntProximity triggered\n"); pinState[2] = 1; halSendSignal(SigProxCvrd); } else if(!halProxSensorCovered() && pinState[2]){ logger(V_HAL, "IntProximity triggered\n"); pinState[2] = 0; halSendSignal(SigProxOpn); } } /** * Returns total flow trough sensor in ml */ float halGetFlow(void) { return flowcnt * FLOW_ML_PULSE; } /** * Resets the Flow counter */ void halResetFlow(void) { logger(V_HAL, "Flow counter reset, amount so far: %.2f ml\n", halGetFlow()); flowcnt = 0; } /** * Reads the status of the Pressure Control * @return 1 (true) for closed Pressure Control(heating) and 0 (false) for open */ bool halIsHeating(void) { if (digitalRead(PIN_PRESSURE_CTRL) == 0) { return true; } else { return false; } } /** * Returns status of the proximity switch * @return 1 if the proximity switch is covered and 0 if uncovered */ bool halProxSensorCovered(void) { if(digitalRead(PIN_PROXIMITY_SENSOR) == 0){ return false; } else { return true; } } /** * Returns the value of the top button Int0 (low active) * @return LOW or HIGH */ int halGetInt0(void) { return digitalRead(PIN_INT0); } /** * Returns the value of the bottom button Int1 (low active) * @return LOW or HIGH */ int halGetInt1(void) { return digitalRead(PIN_INT1); } /** * send Signal to coffee thread * @param val Integer value assigned to signal */ void halSendSignal(HalSig val) { sigval value = { 0 }; value.sival_int = (int) val; try { if (pthread_sigqueue(thread[THREAD_COFFEE], SIGUSR2, value)) { logger_error("hal.cpp: Failed to queue signal %d %s\n", val, strerror(errno)); //No Signals reach the state machine anymore... exit(EXIT_FAILURE); } } catch (int e) { logger_error("Whoops.. %d\n", e); } } /** * Turn machine on */ void halMachineOn(void) { halRelaisOn(RELAIS_HEAT); halRelaisOff(RELAIS_PUMP); halRelaisOn(RELAIS_POWER); logger(V_HAL, "Turning machine on\n"); } /** * Turn machine off */ void halMachineOff(void) { halRelaisOff(RELAIS_HEAT); halRelaisOff(RELAIS_PUMP); halRelaisOff(RELAIS_POWER); logger(V_HAL, "Turning machine off\n"); }