From c6db26a910cf7e14bf0ab30f2d547dee0a500d82 Mon Sep 17 00:00:00 2001 From: Lorenz Uhlig <98092139+LoQue90@users.noreply.github.com> Date: Sat, 28 Sep 2024 18:10:04 +0200 Subject: [PATCH] add manual flush as own function take manual flush out of checkbrewswitch manual flush reset standby time and ends standby remove any brew stuff out of checkbrewswitch() rename brewState and brewswitchstate --- src/brewHandler.h | 325 ++++++++++++++++++++---------------- src/display/displayCommon.h | 10 +- src/main.cpp | 3 +- 3 files changed, 184 insertions(+), 154 deletions(-) diff --git a/src/brewHandler.h b/src/brewHandler.h index b32dec61..6b8d8fdf 100644 --- a/src/brewHandler.h +++ b/src/brewHandler.h @@ -4,16 +4,13 @@ * @brief Handler for brewing * */ -// TODO: Clean up brew() -// move flush out of checkbrewswitch -// flush should trigger standby timer -// flush should stop standby +// TODO: // move brewPIDDisabled to kBrew? -// add flush to display templates, SHOTTIMER 0 +// add flush to display templates, SHOTTIMER 0 still to do // check all Scale stuff -// add shot time log info output +// add shot time log info output ??? // check params website -// ... +// check MQTT/HASSIO for all brew stuff #pragma once @@ -21,9 +18,9 @@ enum BrewSwitchState { kBrewSwitchIdle = 10, - kBrewSwitchBrew = 20, - kBrewSwitchActive = 30, - kBrewSwitchFlush = 40, + kBrewSwitchPressed = 20, + kBrewSwitchShortPressed = 30, + kBrewSwitchLongPressed = 40, kBrewSwitchWaitForRelease = 50 }; @@ -36,7 +33,11 @@ enum BrewState { kBrewRunning = 40, kWaitBrew = 41, kBrewFinished = 42, - kWaitBrewOff = 43 +}; + +enum ManualFlushState { + kManualFlushIdle = 10, + kManualFlushRunning = 20, }; enum BackflushState { @@ -48,15 +49,17 @@ enum BackflushState { kBackflushWaitBrewswitchOff = 43 }; -// Normal Brew +// Brew control states +BrewSwitchState currBrewSwitchState = kBrewSwitchIdle; BrewState currBrewState = kBrewIdle; +ManualFlushState currManualFlushState = kManualFlushIdle; -uint8_t currStateBrewSwitch = LOW; -uint8_t currBrewSwitchStateMomentary = LOW; -int brewSwitchState = kBrewSwitchIdle; +uint8_t brewSwitchReading = LOW; +uint8_t currReadingBrewSwitch = LOW; boolean brewSwitchWasOff = false; int brewOn = 0; // flag is set if brew was detected +int manualFlushOn = 0; // flag is set if manual flush is detected double totalBrewTime = 0; // total brewtime set in software double timeBrewed = 0; // total brewed time double lastBrewTimeMillis = 0; // for shottimer delay after brew is finished @@ -87,66 +90,65 @@ HX711_ADC LoadCell2(PIN_HXDAT2, PIN_HXCLK); * @brief Toggle or momentary input for Brew Switch */ void checkbrewswitch() { - uint8_t brewSwitchReading = brewSwitch->isPressed(); + brewSwitchReading = brewSwitch->isPressed(); if (BREWSWITCH_TYPE == Switch::TOGGLE) { - currStateBrewSwitch = brewSwitchReading; + if (brewSwitchReading == HIGH && currBrewSwitchState != kBrewSwitchShortPressed) { + currBrewSwitchState = kBrewSwitchShortPressed; + LOG(DEBUG, "Toggle Brew switch is ON -> got to currBrewSwitchState = kBrewSwitchShortPressed"); + } + else if (brewSwitchReading == LOW && currBrewSwitchState != kBrewSwitchIdle) { + currBrewSwitchState = kBrewSwitchIdle; + LOG(DEBUG, "Toggle Brew switch is OFF -> got to currBrewSwitchState = kBrewSwitchIdle"); + } } else if (BREWSWITCH_TYPE == Switch::MOMENTARY) { - if (currBrewSwitchStateMomentary != brewSwitchReading) { - currBrewSwitchStateMomentary = brewSwitchReading; + if (currReadingBrewSwitch != brewSwitchReading) { + currReadingBrewSwitch = brewSwitchReading; } // Convert momentary brew switch input to brew switch state - switch (brewSwitchState) { + switch (currBrewSwitchState) { case kBrewSwitchIdle: - if (currBrewSwitchStateMomentary == HIGH && machineState != kWaterEmpty) { - brewSwitchState = kBrewSwitchBrew; - LOG(DEBUG, "brewSwitchState = kBrewSwitchIdle; waiting for brew switch input"); + if (currReadingBrewSwitch == HIGH) { + currBrewSwitchState = kBrewSwitchPressed; + LOG(DEBUG, "Brew switch press detected -> got to currBrewSwitchState = kBrewSwitchPressed"); } break; - case kBrewSwitchBrew: // Brew switch short pressed - start brew - if (currBrewSwitchStateMomentary == LOW && currStateBrewSwitch == LOW) { - currStateBrewSwitch = HIGH; - brewSwitchState = kBrewSwitchActive; - LOG(DEBUG, "brewSwitchState = kBrewSwitchBrew; brew switch short pressed - start Brew"); + case kBrewSwitchPressed: // Brew switch pressed - check for short or long press + if (currReadingBrewSwitch == LOW) { // Brew switch short press detected + currBrewSwitchState = kBrewSwitchShortPressed; + LOG(DEBUG, "Brew switch short press detected -> got to currBrewSwitchState = kBrewSwitchShortPressed; start brew"); } - else if (currBrewSwitchStateMomentary == HIGH && brewSwitch->longPressDetected() && machineState != kWaterEmpty) { // Brew switch more than brewSwitchMomentaryLongPress pressed - start flushing - valveRelay.on(); - pumpRelay.on(); - startingTime = millis(); - brewSwitchState = kBrewSwitchFlush; - LOG(DEBUG, "brewSwitchState = kBrewSwitchBrew: brew switch long pressed - start flushing"); + else if (currReadingBrewSwitch == HIGH && brewSwitch->longPressDetected()) { // Brew switch long press detected + currBrewSwitchState = kBrewSwitchLongPressed; + LOG(DEBUG, "Brew switch long press detected -> got to currBrewSwitchState = kBrewSwitchLongPressed; start manual flush"); } break; - case kBrewSwitchActive: - if (currBrewSwitchStateMomentary == HIGH && currStateBrewSwitch == HIGH) { // Brew switch got short pressed while brew is running - abort brew - currStateBrewSwitch = LOW; - brewSwitchState = kBrewSwitchWaitForRelease; - LOG(DEBUG, "brewSwitchState = kBrewSwitchActive: brew switch short pressed - stop brew"); + case kBrewSwitchShortPressed: + if (currReadingBrewSwitch == HIGH) { // Brew switch short press detected while brew is running - abort brew + currBrewSwitchState = kBrewSwitchWaitForRelease; + LOG(DEBUG, "Brew switch short press detected -> got to currBrewSwitchState = kBrewSwitchWaitForRelease; brew stopped manually"); } else if ((currBrewState == kBrewFinished) || (backflushState == kBackflushWaitBrewswitchOff)) { // Brew reached target and stopped or blackflush cycle done - currStateBrewSwitch = LOW; - brewSwitchState = kBrewSwitchWaitForRelease; - LOG(DEBUG, "brewSwitchState = kBrewSwitchActive: brew reached target or backflush done - reset brew switch"); + currBrewSwitchState = kBrewSwitchWaitForRelease; + LOG(DEBUG, "Brew reached target or backflush done -> got to currBrewSwitchState = kBrewSwitchWaitForRelease"); } break; - case kBrewSwitchFlush: // Brew switch got released after long press detected - stop flushing - if (currBrewSwitchStateMomentary == LOW) { - valveRelay.off(); - pumpRelay.off(); - brewSwitchState = kBrewSwitchWaitForRelease; - LOG(DEBUG, "brewswitchState = kBrewSwitchFlush: brew switch long press released - stop flushing"); + case kBrewSwitchLongPressed: + if (currReadingBrewSwitch == LOW) { // Brew switch got released after long press detected - reset brewswitch + currBrewSwitchState = kBrewSwitchWaitForRelease; + LOG(DEBUG, "Brew switch long press released -> got to currBrewSwitchState = kBrewSwitchWaitForRelease; stop manual flush"); } break; case kBrewSwitchWaitForRelease: // wait for brew switch got released - if (currBrewSwitchStateMomentary == LOW) { - brewSwitchState = kBrewSwitchIdle; - LOG(DEBUG, "brewSwitchState = kBrewSwitchWaitForRelease: brew switch released - go to kBrewSwitchIdle"); + if (currReadingBrewSwitch == LOW) { + currBrewSwitchState = kBrewSwitchIdle; + LOG(DEBUG, "Brew switch reset -> got to currBrewSwitchState = kBrewSwitchIdle"); } break; } @@ -162,7 +164,7 @@ void brewTimer() { checkbrewswitch(); // Start the timer when the brew switch is turned on - if (currStateBrewSwitch == HIGH && currBrewState == kBrewIdle) { + if (brewSwitchReading == HIGH && currBrewState == kBrewIdle) { brewOn = 1; startingTime = currentMillisTemp; timeBrewed = 0; // reset timeBrewed, last brew is still stored @@ -171,12 +173,12 @@ void brewTimer() { } // Update the brewed time if the brew switch is still on - if (currStateBrewSwitch == HIGH && currBrewState == kBrewRunning) { + if (brewSwitchReading == HIGH && currBrewState == kBrewRunning) { timeBrewed = currentMillisTemp - startingTime; } // Stop the timer when the brew switch is turned off - if (currStateBrewSwitch == LOW && currBrewState == kBrewRunning) { + if (brewSwitchReading == LOW && currBrewState == kBrewRunning) { LOG(INFO, "Brew timer stopped"); brewOn = 0; lastBrewTimeMillis = millis(); // time brew finished for shottimer delay @@ -187,6 +189,90 @@ void brewTimer() { #endif #if (FEATURE_BREWCONTROL == 1) +/** + * @brief Backflush + */ +void backflush() { + if (backflushState != kBackflushWaitBrewswitchOn && backflushOn == 0) { + backflushState = kBackflushWaitBrewswitchOff; // Force reset in case backflushOn is reset during backflush! + LOG(INFO, "Backflush: Disabled via Webinterface"); + } + else if (offlineMode == 1 || currBrewState > kBrewIdle || maxflushCycles <= 0 || backflushOn == 0) { + return; + } + + if (bPID.GetMode() == 1) { // Deactivate PID + bPID.SetMode(0); + pidOutput = 0; + } + + heaterRelay.off(); // Stop heating + + checkbrewswitch(); + + if (currBrewSwitchState == kBrewSwitchIdle && backflushState != kBackflushWaitBrewswitchOn) { // Abort function for state machine from every state + backflushState = kBackflushWaitBrewswitchOff; + } + + // State machine for backflush + switch (backflushState) { + case kBackflushWaitBrewswitchOn: + if (currBrewSwitchState == kBrewSwitchShortPressed && backflushOn && machineState != kWaterEmpty) { + startingTime = millis(); + backflushState = kBackflushFillingStart; + } + + break; + + case kBackflushFillingStart: + LOG(INFO, "Backflush: Portafilter filling..."); + valveRelay.on(); + pumpRelay.on(); + backflushState = kBackflushFilling; + + break; + + case kBackflushFilling: + if (millis() - startingTime > FILLTIME) { + startingTime = millis(); + backflushState = kBackflushFlushingStart; + } + + break; + + case kBackflushFlushingStart: + LOG(INFO, "Backflush: Flushing to drip tray..."); + valveRelay.off(); + pumpRelay.off(); + flushCycles++; + backflushState = kBackflushFlushing; + + break; + + case kBackflushFlushing: + if (millis() - startingTime > flushTime && flushCycles < maxflushCycles) { + startingTime = millis(); + backflushState = kBackflushFillingStart; + } + else if (flushCycles >= maxflushCycles) { + backflushState = kBackflushWaitBrewswitchOff; + } + + break; + + case kBackflushWaitBrewswitchOff: + if (currBrewSwitchState == kBrewSwitchIdle) { + LOG(INFO, "Backflush: Finished!"); + valveRelay.off(); + pumpRelay.off(); + flushCycles = 0; + backflushState = kBackflushWaitBrewswitchOn; + } + + break; + } +} + /** * @brief Time or weight based brew mode */ @@ -194,22 +280,21 @@ void brew() { unsigned long currentMillisTemp = millis(); checkbrewswitch(); - if (currStateBrewSwitch == LOW && currBrewState > kBrewIdle) { + if (currBrewSwitchState == kBrewSwitchIdle && currBrewState > kBrewIdle && currBrewState < kBrewFinished) { // abort function for state machine from every state LOG(INFO, "Brew stopped manually"); - brewOn = 0; - currBrewState = kWaitBrewOff; - } - - if (currBrewState > kBrewIdle && currBrewState < kWaitBrewOff || brewSwitchState == kBrewSwitchFlush) { - timeBrewed = currentMillisTemp - startingTime; + currBrewState = kBrewFinished; } - if (currStateBrewSwitch == LOW) { + if (brewSwitchReading == LOW) { // check if brewswitch was turned off at least once, last time, brewSwitchWasOff = true; } + if (currBrewState > kBrewIdle && currBrewState < kBrewFinished) { + timeBrewed = currentMillisTemp - startingTime; + } + if (brewTime > 0) { totalBrewTime = (preinfusion * 1000) + (preinfusionPause * 1000) + (brewTime * 1000); // running every cycle, in case changes are done during brew } @@ -221,7 +306,7 @@ void brew() { // state machine for brew switch (currBrewState) { case kBrewIdle: // waiting step for brew switch turning on - if (currStateBrewSwitch == HIGH && backflushState == 10 && backflushOn == 0 && brewSwitchWasOff && machineState != kWaterEmpty) { + if (currBrewSwitchState == kBrewSwitchShortPressed && backflushState == 10 && backflushOn == 0 && brewSwitchWasOff && machineState != kWaterEmpty) { startingTime = millis(); timeBrewed = 0; @@ -282,11 +367,13 @@ void brew() { // stop brew if target-time is reached --> No stop if stop by time is deactivated via Parameter (0) if ((timeBrewed > totalBrewTime) && ((brewTime > 0))) { + LOG(INFO, "Brew reached time target"); currBrewState = kBrewFinished; } #if (FEATURE_SCALE == 1) // stop brew if target-weight is reached --> No stop if stop by weight is deactivated via Parameter (0) else if (((FEATURE_SCALE == 1) && (weightBrew > weightSetpoint)) && (weightSetpoint > 0)) { + LOG(INFO, "Brew reached weight target"); currBrewState = kBrewFinished; } #endif @@ -294,109 +381,51 @@ void brew() { break; case kBrewFinished: // brew finished - brewOn = 0; - LOG(INFO, "Brew stopped"); valveRelay.off(); pumpRelay.off(); - currBrewState = kWaitBrewOff; - - break; - - case kWaitBrewOff: // waiting for brewswitch off position - if (currStateBrewSwitch == LOW) { - valveRelay.off(); - pumpRelay.off(); - - // disarmed button - currentMillisTemp = 0; - lastBrewTimeMillis = millis(); // time brew finished for shottimer delay - currBrewState = kBrewIdle; - LOGF(INFO, "Shot time: %4.1f s", timeBrewed / 1000); - } + brewOn = 0; + LOGF(INFO, "Shot time: %4.1f s", timeBrewed / 1000); + currentMillisTemp = 0; + lastBrewTimeMillis = millis(); // time brew finished for shottimer delay + brewSwitchWasOff = false; + currBrewState = kBrewIdle; break; } } + /** - * @brief Backflush + * @brief manual grouphead flush */ -void backflush() { - if (backflushState != kBackflushWaitBrewswitchOn && backflushOn == 0) { - backflushState = kBackflushWaitBrewswitchOff; // Force reset in case backflushOn is reset during backflush! - LOG(INFO, "Backflush: Disabled via Webinterface"); - } - else if (offlineMode == 1 || currBrewState > kBrewIdle || maxflushCycles <= 0 || backflushOn == 0) { - return; - } - - if (bPID.GetMode() == 1) { // Deactivate PID - bPID.SetMode(0); - pidOutput = 0; - } - - heaterRelay.off(); // Stop heating - +void manualFlush() { + unsigned long currentMillisTemp = millis(); checkbrewswitch(); - - if (currStateBrewSwitch == LOW && backflushState != kBackflushWaitBrewswitchOn) { // Abort function for state machine from every state - backflushState = kBackflushWaitBrewswitchOff; + if (currManualFlushState == kManualFlushRunning) { + timeBrewed = currentMillisTemp - startingTime; } - // State machine for backflush - switch (backflushState) { - case kBackflushWaitBrewswitchOn: - if (currStateBrewSwitch == HIGH && backflushOn) { - startingTime = millis(); - backflushState = kBackflushFillingStart; - } - - break; - - case kBackflushFillingStart: - LOG(INFO, "Backflush: Portafilter filling..."); - valveRelay.on(); - pumpRelay.on(); - backflushState = kBackflushFilling; - - break; - - case kBackflushFilling: - if (millis() - startingTime > FILLTIME) { - startingTime = millis(); - backflushState = kBackflushFlushingStart; - } - - break; - - case kBackflushFlushingStart: - LOG(INFO, "Backflush: Flushing to drip tray..."); - valveRelay.off(); - pumpRelay.off(); - flushCycles++; - backflushState = kBackflushFlushing; - - break; - - case kBackflushFlushing: - if (millis() - startingTime > flushTime && flushCycles < maxflushCycles) { + switch (currManualFlushState) { + case kManualFlushIdle: + if (currBrewSwitchState == kBrewSwitchLongPressed && machineState != kWaterEmpty) { + LOG(INFO, "Manual flush started"); startingTime = millis(); - backflushState = kBackflushFillingStart; + manualFlushOn = 1; + valveRelay.on(); + pumpRelay.on(); + resetStandbyTimer(); + currManualFlushState = kManualFlushRunning; } - else if (flushCycles >= maxflushCycles) { - backflushState = kBackflushWaitBrewswitchOff; - } - break; - case kBackflushWaitBrewswitchOff: - if (currStateBrewSwitch == LOW) { - LOG(INFO, "Backflush: Finished!"); + case kManualFlushRunning: + if (currBrewSwitchState != kBrewSwitchLongPressed) { + LOG(INFO, "Manual flush stopped"); + manualFlushOn = 0; valveRelay.off(); pumpRelay.off(); - flushCycles = 0; - backflushState = kBackflushWaitBrewswitchOn; + LOGF(INFO, "Manual flush time: %4.1f s", timeBrewed / 1000); + currManualFlushState = kManualFlushIdle; } - break; } } diff --git a/src/display/displayCommon.h b/src/display/displayCommon.h index 1b2a2e05..dd1b55d4 100644 --- a/src/display/displayCommon.h +++ b/src/display/displayCommon.h @@ -241,10 +241,10 @@ bool displayShottimer() { return false; } - if (machineState == kBrew || (millis() - lastBrewTimeMillis) < SHOTTIMERDISPLAYDELAY || brewSwitchState == kBrewSwitchFlush) { + if (machineState == kBrew || (millis() - lastBrewTimeMillis) < SHOTTIMERDISPLAYDELAY || currManualFlushState == kManualFlushRunning) { u8g2.clearBuffer(); - if (brewSwitchState != kBrewSwitchFlush) { + if (currManualFlushState != kManualFlushRunning) { u8g2.drawXBMP(-1, 11, Brew_Cup_Logo_width, Brew_Cup_Logo_height, Brew_Cup_Logo); } else { @@ -277,7 +277,7 @@ bool displayShottimer() { */ bool displayMachineState() { // Show the heating logo when we are in regular PID mode and more than 5degC below the set point - if (FEATURE_HEATINGLOGO > 0 && machineState == kPidNormal && (setpoint - temperature) > 5. && brewSwitchState != kBrewSwitchFlush) { + if (FEATURE_HEATINGLOGO > 0 && machineState == kPidNormal && (setpoint - temperature) > 5. && currManualFlushState != kManualFlushRunning) { // For status info u8g2.clearBuffer(); @@ -314,7 +314,7 @@ bool displayMachineState() { return true; } // Steam - else if (machineState == kSteam && brewSwitchState != kBrewSwitchFlush) { + else if (machineState == kSteam && currManualFlushState != kManualFlushRunning) { u8g2.clearBuffer(); u8g2.drawXBMP(-1, 12, Steam_Logo_width, Steam_Logo_height, Steam_Logo); @@ -325,7 +325,7 @@ bool displayMachineState() { return true; } // Water empty - else if (machineState == kWaterEmpty && brewSwitchState != kBrewSwitchFlush) { + else if (machineState == kWaterEmpty && currManualFlushState != kManualFlushRunning) { u8g2.clearBuffer(); u8g2.drawXBMP(45, 0, Water_Empty_Logo_width, Water_Empty_Logo_height, Water_Empty_Logo); u8g2.setFont(u8g2_font_profont11_tf); diff --git a/src/main.cpp b/src/main.cpp index b9671485..c6558e6a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -720,7 +720,7 @@ void handleMachineState() { #endif } - if (pidON || steamON || brewOn) { + if (pidON || steamON || brewOn || manualFlushOn) { pidON = 1; resetStandbyTimer(); #if OLED_DISPLAY != 0 @@ -1515,6 +1515,7 @@ void looppid() { #if (FEATURE_BREWSWITCH == 1 && FEATURE_BREWCONTROL == 1) brew(); + manualFlush(); #endif #if (FEATURE_PRESSURESENSOR == 1)