123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524 |
- /*
- * hal.cpp
- *
- * Created on: Aug 3, 2016
- * Author: Philipp Hinz, Sebastian Vendt
- */
- #include <wiringPi.h>
- #include <stdlib.h>
- #include <errno.h>
- #include <string.h>
- #include <signal.h>
- #include <ctime>
- #include <time.h>
- #include <unistd.h>
- #include "hal.h"
- #include "global.h"
- #include "logger.h"
- #include "timer.h"
- typedef struct timespec timespec;
- volatile int flowcnt = 0;
- int Int0Time, Int1Time;
- int idleCounter;
- bool idle;
- bool flagIgnoreRlsInt0, flagIgnoreRlsInt1;
- //storage for the last state of the buttons, the proximity sensor and the pressure sensor
- int pinState[4] = {1, 1, 1, 0};
- timer Int0Timer(&halInt0TimerHandler);
- timer Int1Timer(&halInt1TimerHandler);
- timer idleTimer(&halIdleTimerHandler);
- time_t heatingCycle[] = {0, 0};
- timespec pumpCycle[] = {{0,0},{0,0}};
- //delay of the debounce in milliseconds
- #define DELAY_DEBOUNCE 50
- //display turn off after idle time in min
- //minimal time is 2min
- #define IDLE_TIME 10
- /**
- * 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);
- idleTimer.setDivider(1200); //1 min
- idleCounter = 0;
- idle = false;
- halDisplayOn();
- if (optPower) {
- halMachineOn();
- } else {
- halMachineOff();
- }
- sleep(1); //wait till the machine eventually turned on when optPower
- pinState[3] = halIsHeating();
- 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();
- }
- }
- /**
- *
- */
- void halIdleTimerHandler(void) {
- if(++idleCounter == IDLE_TIME){
- halEnterIdle();
- }
- }
- /**
- * 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 {
- Int1Time = 0;
- Int1Timer.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());
- 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() && !pinState[3]) {
- pinState[3] = 1;
- time(&heatingCycle[0]);
- halSendSignal(SigPressCls);
- } else if(!halIsHeating() && pinState[3]) {
- pinState[3] = 0;
- time(&heatingCycle[1]);
- 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 elapsed during the heating cycle
- */
- double halgetHeatingTime(void){
- //TODO check return value on negative times
- if (halIsHeating()) {
- logger(V_HAL, "Hot Heating Time: %f\n", difftime(time(NULL), heatingCycle[0]));
- return difftime(time(0), heatingCycle[0]);
- }
- else {
- logger(V_HAL, "Heating time: %f\n", difftime(heatingCycle[1], heatingCycle[0]));
- return difftime(heatingCycle[1], heatingCycle[0]);
- }
- }
- /**
- * 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) {
- //catch if machine is idle and drop button event
- switch (val) {
- case SigInt0Psh:
- case SigInt1Psh:
- if (idle) {
- return;
- }
- break;
- case SigInt0Rls:
- case SigInt0RlsLong:
- case SigInt1Rls:
- case SigInt1RlsLong:
- if (idle) {
- halLeaveIdle();
- return;
- }
- break;
- default:
- break;
- }
- 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);
- idleTimer.stop();
- logger(V_HAL, "Turning machine on\n");
- }
- /**
- * Turn machine off
- */
- void halMachineOff(void) {
- halRelaisOff(RELAIS_HEAT);
- halRelaisOff(RELAIS_PUMP);
- halRelaisOff(RELAIS_POWER);
- idleCounter = 0;
- idleTimer.start();
- logger(V_HAL, "Turning machine off\n");
- }
- /**
- *
- */
- void halEnterIdle(void){
- logger(V_HAL, "Entering Idle Mode\n");
- idleTimer.stop();
- halDisplayOff();
- idle = true;
- }
- /**
- *
- */
- void halLeaveIdle(void){
- idleCounter = 0;
- logger(V_HAL, "Leaving Idle Mode\n");
- halDisplayOn();
- idleTimer.start();
- idle = false;
- }
- /**
- * Wrapper function to turn the pump on
- * and is used for time measurements on how long the pump is running
- */
- void halPumpOn(void){
- halRelaisOn(RELAIS_PUMP);
- clock_gettime(CLOCK_REALTIME, &pumpCycle[0]);
- }
- /**
- * Wrapper function to turn the pump off
- * and is used for time measurements on how long the pump is running
- */
- void halPumpOff(void){
- halRelaisOff(RELAIS_PUMP);
- clock_gettime(CLOCK_REALTIME, &pumpCycle[1]);
- }
- /**
- * Function to get the elapsed time the pump is running in ms
- * when the pump is on, this function returns the time between turning the pump on and the call
- * when the pump is off, this function returns the last
- */
- double halGetPumpTime(void){
- timespec now;
- timespec diff = {0,0};
- if(halGetRelaisState(RELAIS_PUMP) == HIGH){//pump is on
- clock_gettime(CLOCK_REALTIME, &now);
- timespec_diff(&pumpCycle[0], &now, &diff);
- }
- else {
- timespec_diff(&pumpCycle[0], &pumpCycle[1], &diff);
- }
- return diff.tv_sec * 1000 + diff.tv_nsec/1000000;
- }
- /**
- * Function to calculate the difference between two timespecs
- */
- void timespec_diff(timespec *start, timespec *stop, timespec *result) {
- long int secDiff = stop->tv_sec - start->tv_sec;
- long int nsecDiff = stop->tv_nsec - start->tv_nsec;
- if (secDiff > 0) {
- if (nsecDiff >= 0) {
- result->tv_sec = secDiff;
- result->tv_nsec = nsecDiff;
- } else if (nsecDiff < 0) {
- result->tv_sec = --secDiff;
- result->tv_nsec = 1000000000 + nsecDiff;
- }
- } else if (secDiff < 0) {
- if (nsecDiff >= 0) {
- result->tv_sec = ++secDiff;
- result->tv_nsec = -(1000000000 - nsecDiff);
- } else if (nsecDiff < 0) {
- result->tv_sec = secDiff;
- result->tv_nsec = nsecDiff;
- }
- } else if (secDiff == 0){
- result->tv_sec = secDiff;
- result->tv_nsec = nsecDiff;
- }
- return;
- }
|