#include #include #include #include #include "hardware.h" #define SIMULATE 1 #define DEBUG 0 #define TIMEOUT_TIME 7000 #define BUTTON_HOLD_TIME 500 #define BUTTON_PRESS_TIME 20 #define UP_BUTTON 31 #define ENTER_BUTTON 30 #define DOWN_BUTTON 27 #define PRESSURE_SENSOR_PIN A0 Adafruit_FeatherOLED oled = Adafruit_FeatherOLED(); static const unsigned char PROGMEM arrow[] = { B10000000, B11000000, B11100000, B11000000, B10000000}; //oled.drawBitmap(0, 1, arrow, 8, 5, 1); enum buttonStates { OPEN, CLOSED, CHECK_PRESSED, PRESSED, HELD, NUM_BUTTONSTATES }; enum screenStates { BOOT_UP, PRESSURE, SET_POINT, INIT_RUN, BEGIN_RUN, MEASURING, RUNNING, SAY_DONE, SAY_CANCEL, SAY_HOLD, SAY_TIMEOUT, SETTINGS, NUM_SCREENSTATES }; enum buttonStates upButton = OPEN; enum buttonStates enterButton = OPEN; enum buttonStates downButton = OPEN; float pressureValue = 0.0; int debounceValue(float value) { static int prevValue = (int) value; if (abs(prevValue - value) > 0.4) { prevValue = (int) value; } return prevValue; } void setup() { randomSeed(analogRead(A1)); Serial.begin(115200); oled.init(); pinMode(UP_BUTTON, INPUT_PULLUP); pinMode(ENTER_BUTTON, INPUT); // Has external pullup pinMode(DOWN_BUTTON, INPUT_PULLUP); #ifdef SIMULATE initSimulation(); #endif resamplePressure(pressureValue, PRESSURE_SENSOR_PIN); } void loop() { measurePressure(pressureValue, PRESSURE_SENSOR_PIN); pollButtons(); runUI(); #ifdef SIMULATE tickSimulation(); #endif } void runUI() { static enum screenStates screenState = BOOT_UP; static enum screenStates nextState = BOOT_UP; static unsigned long timer = millis(); static int pressureSetPoint = 0; static unsigned long startTime = millis(); //static float initialPressure = 0.0; //static float runningPressure = 0.0; static float sampledPressure = 0.0; static bool isInflating = false; static bool isDeflating = false; int num_dots = 0; int debouncedPressureValue = debounceValue(pressureValue); oled.clearDisplay(); Serial.print("pressure: "); Serial.print(pressureValue); Serial.print(", sampled: "); Serial.print(sampledPressure); Serial.print(", setpoint: "); Serial.print(pressureSetPoint); Serial.println(""); switch (screenState) { case BOOT_UP: if (millis() >= timer + 2000) { screenState = PRESSURE; } oled.setCursor(0,0); oled.setTextSize(2); oled.println("STC TECH"); oled.setTextSize(1); oled.println(""); oled.print(" INITIALIZING"); oled.display(); break; case PRESSURE: if (enterButton == PRESSED) { screenState = SAY_HOLD; nextState = PRESSURE; timer = millis(); } else if (enterButton == HELD) { ; // settings? } else if (upButton == PRESSED) { screenState = SET_POINT; pressureSetPoint = debouncedPressureValue+1; timer = millis(); } else if (downButton == PRESSED) { screenState = SET_POINT; pressureSetPoint = debouncedPressureValue-1; timer = millis(); } else if (upButton == HELD) { screenState = SET_POINT; pressureSetPoint = debouncedPressureValue+1; timer = millis(); } else if (downButton == HELD) { screenState = SET_POINT; pressureSetPoint = debouncedPressureValue-1; timer = millis(); } oled.setCursor(0,0); oled.setTextSize(3); oled.print(debouncedPressureValue); oled.print(" PSI"); oled.display(); break; case SET_POINT: if (enterButton == PRESSED) { screenState = SAY_HOLD; nextState = SET_POINT; timer = millis(); } else if (enterButton == HELD) { timer = millis(); screenState = INIT_RUN; } else if (upButton == PRESSED) { timer = millis(); pressureSetPoint++; } else if (downButton == PRESSED) { timer = millis(); pressureSetPoint--; } else if (upButton == HELD) { timer = millis(); pressureSetPoint++; delay(75); } else if (downButton == HELD) { timer = millis(); pressureSetPoint--; delay(75); } else if (millis() >= timer + TIMEOUT_TIME) { screenState = SAY_TIMEOUT; nextState = PRESSURE; timer = millis(); } oled.setCursor(0,0); oled.setTextSize(3); oled.print(pressureSetPoint); oled.println(" PSI"); oled.setTextSize(1); oled.println("TARGET"); oled.display(); break; case INIT_RUN: //initialPressure = pressureValue; startTime = millis(); timer = millis(); screenState = BEGIN_RUN; oled.setCursor(0,0); oled.setTextSize(1); oled.println(""); oled.setTextSize(2); if (pressureSetPoint > debouncedPressureValue) { oled.print("INFLATING"); setSoleniod(SOLENOID_INFLATE); isInflating = true; isDeflating = false; } else if (pressureSetPoint < debouncedPressureValue) { oled.print("DEFLATING"); setSoleniod(SOLENOID_DEFLATE); isDeflating = true; isInflating = false; } else { setSoleniod(SOLENOID_STOP); screenState = SAY_DONE; nextState = PRESSURE; } oled.display(); break; case BEGIN_RUN: if (millis() >= timer + 5000) { //runningPressure = pressureValue; setSoleniod(SOLENOID_STOP); screenState = MEASURING; timer = millis(); } break; case MEASURING: if (millis() >= timer + 3000) { sampledPressure = pressureValue; if (isInflating && (int) sampledPressure >= pressureSetPoint) { screenState = SAY_DONE; nextState = PRESSURE; } else if (isDeflating && (int) sampledPressure <= pressureSetPoint) { screenState = SAY_DONE; nextState = PRESSURE; } else { screenState = RUNNING; } timer = millis(); } if (millis() < timer + 500) { // wait for solenoids to settle before averaging resamplePressure(pressureValue, PRESSURE_SENSOR_PIN); } setSoleniod(SOLENOID_STOP); oled.setCursor(0,0); oled.setTextSize(1); oled.println(""); oled.setTextSize(2); oled.print("MEASURING"); oled.display(); break; case RUNNING: if (enterButton == PRESSED) { screenState = SAY_CANCEL; nextState = PRESSURE; timer = millis(); } else if (upButton == PRESSED) { screenState = SAY_CANCEL; nextState = PRESSURE; timer = millis(); } else if (downButton == PRESSED) { screenState = SAY_CANCEL; nextState = PRESSURE; timer = millis(); } if (isInflating && millis() >= timer + 20000) { screenState = MEASURING; timer = millis(); } else if (isDeflating && millis() >= timer + 10000) { screenState = MEASURING; timer = millis(); } if (isInflating) { setSoleniod(SOLENOID_INFLATE); } else if (isDeflating) { setSoleniod(SOLENOID_DEFLATE); } oled.setCursor(0,0); oled.setTextSize(3); oled.print((int) sampledPressure); oled.println(" PSI"); oled.setTextSize(1); if (isInflating) { oled.print("INFLATING"); } else if (isDeflating) { oled.print("DEFLATING"); } num_dots = (int) ((millis() - startTime) / 400) % 4; for (int i = 0; i < num_dots; i++) { oled.print("."); } oled.display(); break; case SAY_DONE: if (millis() >= timer + 3000) { screenState = nextState; timer = millis(); } oled.setCursor(0,0); oled.setTextSize(3); oled.print("DONE"); oled.display(); break; case SAY_CANCEL: if (millis() >= timer + 1000) { screenState = nextState; timer = millis(); } oled.setCursor(0,0); oled.setTextSize(3); oled.print("CANCEL"); oled.display(); break; case SAY_HOLD: if (millis() >= timer + 500) { screenState = nextState; timer = millis(); } oled.setCursor(0,0); oled.setTextSize(3); oled.print("HOLD"); oled.display(); break; case SAY_TIMEOUT: if (millis() >= timer + 1000) { screenState = nextState; timer = millis(); } oled.setCursor(0,0); oled.setTextSize(3); oled.print("TIMEOUT"); oled.display(); break; } } void pollButtons() { static unsigned long upButtonTime = 0; static unsigned long enterButtonTime = 0; static unsigned long downButtonTime = 0; processButtonState(UP_BUTTON, upButton, upButtonTime); processButtonState(ENTER_BUTTON, enterButton, enterButtonTime); processButtonState(DOWN_BUTTON, downButton, downButtonTime); if (DEBUG) { if (upButton == PRESSED) { Serial.println("up button pressed"); } else if (upButton == HELD) { Serial.println("up button held"); } if (enterButton == PRESSED) { Serial.println("enter button pressed"); } else if (enterButton == HELD) { Serial.println("enter button held"); } if (downButton == PRESSED) { Serial.println("down button pressed"); } else if (downButton == HELD) { Serial.println("down button held"); } } } void processButtonState(int buttonPin, buttonStates &buttonState, unsigned long &buttonTime) { bool pinState = !digitalRead(buttonPin); switch(buttonState) { case OPEN: if (pinState) { buttonState = CLOSED; buttonTime = millis(); } break; case CLOSED: if (millis() >= buttonTime + BUTTON_HOLD_TIME) { buttonState = HELD; } if (pinState) { ; } else { buttonState = CHECK_PRESSED; } break; case CHECK_PRESSED: if (millis() >= buttonTime + BUTTON_PRESS_TIME) { buttonState = PRESSED; } else { buttonState = OPEN; } break; case PRESSED: buttonState = OPEN; break; case HELD: if (!pinState) { buttonState = OPEN; } break; default: break; } }