From 31f7264131055e66250e7f1e62df52c43a3937f2 Mon Sep 17 00:00:00 2001 From: Lorenz Uhlig <98092139+LoQue90@users.noreply.github.com> Date: Wed, 21 Aug 2024 01:12:55 +0200 Subject: [PATCH 01/23] remove brewdetection remove brewdetection works only with brewcontrol rename isbrewdetected to brewOn --- src/brewHandler.h | 5 +- src/main.cpp | 319 +++++----------------------------------- src/steamHandler.h | 14 -- src/userConfig_sample.h | 2 - 4 files changed, 44 insertions(+), 296 deletions(-) diff --git a/src/brewHandler.h b/src/brewHandler.h index 58e6007b8..257687e86 100644 --- a/src/brewHandler.h +++ b/src/brewHandler.h @@ -46,6 +46,7 @@ uint8_t currBrewSwitchStateMomentary = LOW; int brewSwitchState = kBrewSwitchIdle; boolean brewSwitchWasOff = false; +int isBrewDetected = 0; // flag is set if brew was detected double totalBrewTime = 0; // total brewtime set in software double timeBrewed = 0; // total brewed time double lastBrewTimeMillis = 0; // for shottimer delay after disarmed button @@ -101,6 +102,7 @@ void checkbrewswitch() { if (currBrewSwitchStateMomentary == LOW) { // Brew trigger currStateBrewSwitch = HIGH; + isBrewDetected = 1; brewSwitchState = kBrewSwitchBrewAbort; LOG(DEBUG, "brewSwitchState = kBrewSwitchBrew; brew switch short pressed - start Brew"); } @@ -120,6 +122,7 @@ void checkbrewswitch() { if ((currBrewSwitchStateMomentary == HIGH && currStateBrewSwitch == HIGH) || (machineState == kShotTimerAfterBrew) || (backflushState == kBackflushWaitBrewswitchOff)) { currStateBrewSwitch = LOW; brewSwitchState = kBrewSwitchReset; + isBrewDetected = 0; LOG(DEBUG, "brewSwitchState = kBrewSwitchBrewAbort: brew switch short pressed - stop brew"); } break; @@ -128,6 +131,7 @@ void checkbrewswitch() { // Brew switch got released - stop flushing if (currBrewSwitchStateMomentary == LOW && currStateBrewSwitch == LOW) { brewSwitchState = kBrewSwitchReset; + isBrewDetected = 0; LOG(DEBUG, "brewswitchTriggerCase = kBrewSwitchFlushOff: brew switch long press released - stop flushing"); valveRelay.off(); pumpRelay.off(); @@ -348,7 +352,6 @@ void brew() { // disarmed button currentMillisTemp = 0; - brewDetected = 0; // rearm brewDetection currBrewState = kBrewIdle; lastBrewTime = timeBrewed; // store brewtime to show in Shottimer after brew is finished timeBrewed = 0; diff --git a/src/main.cpp b/src/main.cpp index d9f6df9bf..b444d65d6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -101,8 +101,6 @@ int lastmachinestatepid = -1; int connectmode = CONNECTMODE; int offlineMode = 0; -const int brewDetectionMode = BREWDETECTION_TYPE; -const int optocouplerType = OPTOCOUPLER_TYPE; const boolean ota = OTA; // Display @@ -129,20 +127,6 @@ int backflushOn = 0; int backflushState = 10; int currBackflushCycles = 0; // number of active flush cycles -// Optocoupler -unsigned long previousMillisOptocouplerReading = millis(); -const unsigned long intervalOptocoupler = 200; -int optocouplerOn, optocouplerOff; - -// QuickMill thermoblock steam-mode (only for BREWDETECTION_TYPE = 3) -const int maxBrewDurationForSteamModeQM_ON = 200; // if brewtime is shorter steam-mode starts -const int minOptocouplerOffTimedForSteamModeQM_Off = 1500; // if optocoupler-off-time is longer steam-mode ends -unsigned long timeOptocouplerOn = 0; // time optocoupler switched to ON -unsigned long lastTimeOptocouplerOn = 0; // last time optocoupler was ON -bool steamQM_active = false; // steam-mode is active -bool brewSteamDetectedQM = false; // brew/steam detected, not sure yet what it is -bool coolingFlushDetectedQM = false; - // Pressure sensor #if (FEATURE_PRESSURESENSOR == 1) float inputPressure = 0; @@ -190,8 +174,6 @@ void loopLED(); void checkWater(); void printMachineState(); char const* machinestateEnumToString(MachineState machineState); -void initSteamQM(); -boolean checkSteamOffQM(); char* number2string(double in); char* number2string(float in); char* number2string(int in); @@ -283,7 +265,6 @@ SysPara sysParaBackflushFlushTime(&backflushFlushTime, BACKFLUSH_FLUSH_T boolean emergencyStop = false; // Emergency stop if temperature is too high const double EmergencyStopTemp = 145; // Temp EmergencyStopTemp float inX = 0, inY = 0, inOld = 0, inSum = 0; // used for filterPressureValue() -boolean brewDetected = 0; boolean setupDone = false; // Water sensor @@ -292,10 +273,6 @@ Timer loopWater(&checkWater, 200); // Check water level every 200 ms int waterCheckConsecutiveReads = 0; // Counter for consecutive readings of water sensor const int waterCountsNeeded = 3; // Number of same readings to change water sensing -// Moving average for software brew detection -unsigned long timeBrewDetection = 0; -int isBrewDetected = 0; // flag is set if brew was detected - // PID controller unsigned long previousMillistemp; // initialisation at the end of init() @@ -325,8 +302,6 @@ PID bPID(&temperature, &pidOutput, &setpoint, aggKp, aggKi, aggKd, 1, DIRECT); #include "brewHandler.h" -Timer logbrew([&]() { LOGF(DEBUG, "(tB,T,hra) --> %5.2f %6.2f %8.2f", (double)(millis() - startingTime) / 1000, temperature, tempSensor->getAverageTemperatureRate()); }, 500); - // Embedded HTTP Server #include "embeddedWebserver.h" @@ -545,126 +520,6 @@ char* number2string(unsigned int in) { return number2string_uint; } -/** - * @brief detect if a brew is running - */ -void brewDetection() { - if (brewDetectionMode == 1 && brewSensitivity == 0) return; // abort brewdetection if deactivated - - // Brew detection: 1 = software solution, 2 = hardware, 3 = voltage sensor - if (brewDetectionMode == 1) { - if (isBrewDetected == 1) { - timeBrewed = millis() - timeBrewDetection; - } - - // deactivate brewtimer after end of brewdetection pid - if (millis() - timeBrewDetection > brewtimesoftware * 1000 && isBrewDetected == 1) { - isBrewDetected = 0; // rearm brewDetection - timeBrewed = 0; - } - } - else if (brewDetectionMode == 2) { - if (millis() - timeBrewDetection > brewtimesoftware * 1000 && isBrewDetected == 1) { - isBrewDetected = 0; // rearm brewDetection - } - } - else if (brewDetectionMode == 3) { - // timeBrewed counter - if ((digitalRead(PIN_BREWSWITCH) == optocouplerOn) && brewDetected == 1) { - timeBrewed = millis() - startingTime; - lastBrewTime = timeBrewed; - } - - // OFF: reset brew - if ((digitalRead(PIN_BREWSWITCH) == optocouplerOff) && (brewDetected == 1 || coolingFlushDetectedQM == true)) { - isBrewDetected = 0; // rearm brewDetection - brewDetected = 0; - timeOptocouplerOn = timeBrewed; // for QuickMill - timeBrewed = 0; - startingTime = 0; - coolingFlushDetectedQM = false; - LOG(DEBUG, "HW Brew - optocoupler - End"); - } - } - - // Activate brew detection - if (brewDetectionMode == 1) { // SW BD - // BD PID only +/- 4 °C, no detection if HW was active - if (tempSensor->getAverageTemperatureRate() <= -brewSensitivity && isBrewDetected == 0 && (fabs(temperature - brewSetpoint) < 5)) { - LOG(DEBUG, "SW Brew detected"); - timeBrewDetection = millis(); - isBrewDetected = 1; - } - } - else if (brewDetectionMode == 2) { // HW BD - if (currBrewState > kBrewIdle && brewDetected == 0) { - LOG(DEBUG, "HW Brew detected"); - timeBrewDetection = millis(); - isBrewDetected = 1; - brewDetected = 1; - } - } - else if (brewDetectionMode == 3) { // voltage sensor - switch (machine) { - case QuickMill: - if (!coolingFlushDetectedQM) { - int pvs = digitalRead(PIN_BREWSWITCH); - - if (pvs == optocouplerOn && brewDetected == 0 && brewSteamDetectedQM == 0 && !steamQM_active) { - timeBrewDetection = millis(); - timeOptocouplerOn = millis(); - isBrewDetected = 1; - brewDetected = 0; - brewSteamDetectedQM = 1; - LOG(DEBUG, "Quick Mill: setting brewSteamDetectedQM = 1"); - logbrew.reset(); - } - - const unsigned long minBrewDurationForSteamModeQM_ON = 50; - if (brewSteamDetectedQM == 1 && millis() - timeOptocouplerOn > minBrewDurationForSteamModeQM_ON) { - if (pvs == optocouplerOff) { - brewSteamDetectedQM = 0; - - if (millis() - timeOptocouplerOn < maxBrewDurationForSteamModeQM_ON) { - LOG(DEBUG, "Quick Mill: steam-mode detected"); - initSteamQM(); - } - else { - LOG(ERROR, "QuickMill: neither brew nor steam"); - } - } - else if (millis() - timeOptocouplerOn > maxBrewDurationForSteamModeQM_ON) { - if (temperature < brewSetpoint + 2) { - LOG(DEBUG, "Quick Mill: brew-mode detected"); - startingTime = timeOptocouplerOn; - brewDetected = 1; - brewSteamDetectedQM = 0; - } - else { - LOG(DEBUG, "Quick Mill: cooling-flush detected"); - coolingFlushDetectedQM = true; - brewSteamDetectedQM = 0; - } - } - } - } - break; - - // no Quickmill: - default: - previousMillisOptocouplerReading = millis(); - - if (digitalRead(PIN_BREWSWITCH) == optocouplerOn && brewDetected == 0) { - LOG(DEBUG, "HW Brew - Voltage Sensor - Start"); - timeBrewDetection = millis(); - startingTime = millis(); - isBrewDetected = 1; - brewDetected = 1; - } - } - } -} - /** * @brief Filter input value using exponential moving average filter (using fixed coefficients) * After ~28 cycles the input is set to 99,66% if the real input value sum of inX and inY @@ -679,32 +534,6 @@ float filterPressureValue(float input) { return inSum; } -void initSteamQM() { - // Initialize monitoring for steam switch off for QuickMill thermoblock - lastTimeOptocouplerOn = millis(); // time when optocoupler changes from ON to OFF - steamQM_active = true; - timeOptocouplerOn = 0; - steamON = 1; -} - -boolean checkSteamOffQM() { - /* Monitor optocoupler during active steam mode of QuickMill - * thermoblock. Once the optocoupler remains OFF for longer than a - * pump-pulse time peride the switch is turned off and steam mode finished. - */ - if (digitalRead(PIN_BREWSWITCH) == optocouplerOn) { - lastTimeOptocouplerOn = millis(); - } - - if ((millis() - lastTimeOptocouplerOn) > minOptocouplerOffTimedForSteamModeQM_Off) { - lastTimeOptocouplerOn = 0; - - return true; - } - - return false; -} - /** * @brief Handle the different states of the machine */ @@ -729,9 +558,8 @@ void handleMachineState() { break; case kPidNormal: - brewDetection(); - if ((timeBrewed > 0 && FEATURE_BREWCONTROL == 0) || (FEATURE_BREWCONTROL == 1 && currBrewState > kBrewIdle && currBrewState <= kBrewFinished)) { + if (brewOn == 1) { machineState = kBrew; if (standbyModeOn) { @@ -779,24 +607,13 @@ void handleMachineState() { break; case kBrew: - brewDetection(); - - // Output brew time, temp and tempRateAverage during brew (used for SW BD only) - if (FEATURE_BREWDETECTION == 1 && BREWDETECTION_TYPE == 1) { - logbrew(); - } - if ((timeBrewed == 0 && brewDetectionMode == 3 && FEATURE_BREWCONTROL == 0) || // PID + optocoupler: optocoupler BD timeBrewed == 0 -> switch is off again - ((currBrewState == kBrewIdle || currBrewState == kWaitBrewOff) && FEATURE_BREWCONTROL == 1)) // Hardware BD + if (currBrewState == kBrewIdle || currBrewState == kWaitBrewOff) { // delay shot timer display for voltage sensor or hw brew toggle switch (brew counter) machineState = kShotTimerAfterBrew; lastBrewTimeMillis = millis(); // for delay } - else if (brewDetectionMode == 1 && FEATURE_BREWCONTROL == 0 && isBrewDetected == 0) { // SW BD, kBrew was active for set time - // when Software brew is finished, direct to PID BD - machineState = kBrewDetectionTrailing; - } if (steamON == 1) { machineState = kSteam; @@ -816,48 +633,18 @@ void handleMachineState() { break; case kShotTimerAfterBrew: - brewDetection(); if (millis() - lastBrewTimeMillis > SHOTTIMERDISPLAYDELAY) { LOGF(INFO, "Shot time: %4.1f s", lastBrewTime / 1000); - machineState = kBrewDetectionTrailing; - } - - if (steamON == 1) { - machineState = kSteam; - } - - if (backflushOn || backflushState > kBackflushWaitBrewswitchOn) { - machineState = kBackflush; - } - - if (emergencyStop) { - machineState = kEmergencyStop; - } - - if (pidON == 0) { - machineState = kPidDisabled; - } - - if (!waterFull) { - machineState = kWaterEmpty; - } - - if (tempSensor->hasError()) { - machineState = kSensorError; - } - break; - - case kBrewDetectionTrailing: - brewDetection(); - - if (isBrewDetected == 0) { machineState = kPidNormal; } - if ((timeBrewed > 0 && FEATURE_BREWCONTROL == 0 && brewDetectionMode == 3) || // Allow brew directly after BD only when using FEATURE_BREWCONTROL 0 AND hardware brew switch detection - (FEATURE_BREWCONTROL == 1 && currBrewState > kBrewIdle && currBrewState <= kBrewFinished)) { + if (brewOn == 1) { machineState = kBrew; + + if (standbyModeOn) { + resetStandbyTimer(); + } } if (steamON == 1) { @@ -984,9 +771,7 @@ void handleMachineState() { #endif } - brewDetection(); - - if (pidON || steamON || isBrewDetected) { + if (pidON || steamON || brewOn) { pidON = 1; resetStandbyTimer(); #if OLED_DISPLAY != 0 @@ -996,7 +781,7 @@ void handleMachineState() { if (steamON) { machineState = kSteam; } - else if (isBrewDetected) { + else if (brewOn) { machineState = kBrew; } else { @@ -1457,32 +1242,33 @@ void setup() { .maxValue = BREW_SW_TIME_MAX, .ptr = (void*)&brewtimesoftware}; - editableVars["PID_BD_SENSITIVITY"] = {.displayName = F("PID BD Sensitivity"), - .hasHelpText = true, - .helpText = F("Software brew detection sensitivity that looks at " - "average temperature, Details. " - "Needs to be >0 also for Hardware switch detection."), - .type = kDouble, - .section = sBDSection, - .position = 27, - .show = [] { return true && BREWDETECTION_TYPE == 1; }, - .minValue = BD_THRESHOLD_MIN, - .maxValue = BD_THRESHOLD_MAX, - .ptr = (void*)&brewSensitivity}; - - editableVars["STEAM_MODE"] = { - .displayName = F("Steam Mode"), .hasHelpText = false, .helpText = "", .type = kUInt8, .section = sOtherSection, .position = 28, .show = [] { return false; }, .minValue = 0, .maxValue = 1, .ptr = (void*)&steamON}; - - editableVars["BACKFLUSH_ON"] = { - .displayName = F("Backflush"), .hasHelpText = false, .helpText = "", .type = kUInt8, .section = sOtherSection, .position = 29, .show = [] { return false; }, .minValue = 0, .maxValue = 1, .ptr = (void*)&backflushOn}; + editableVars["STEAM_MODE"] = {.displayName = F("Steam Mode"), + .hasHelpText = false, + .helpText = "", + .type = kUInt8, + .section = sOtherSection, + .position = 27, .show = [] { return false; }, + .minValue = 0, + .maxValue = 1, + .ptr = (void*)&steamON}; + + editableVars["BACKFLUSH_ON"] = {.displayName = F("Backflush"), + .hasHelpText = false, + .helpText = "", + .type = kUInt8, + .section = sOtherSection, + .position = 28, + .show = [] { return false; }, + .minValue = 0, + .maxValue = 1, + .ptr = (void*)&backflushOn}; editableVars["STANDBY_MODE_ON"] = {.displayName = F("Enable Standby Timer"), .hasHelpText = true, .helpText = F("Turn heater off after standby time has elapsed."), .type = kUInt8, .section = sPowerSection, - .position = 30, + .position = 29, .show = [] { return true; }, .minValue = 0, .maxValue = 1, @@ -1493,7 +1279,7 @@ void setup() { .helpText = F("Time in minutes until the heater is turned off. Timer is reset by brew detection."), .type = kDouble, .section = sPowerSection, - .position = 31, + .position = 30, .show = [] { return true; }, .minValue = STANDBY_MODE_TIME_MIN, .maxValue = STANDBY_MODE_TIME_MAX, @@ -1501,14 +1287,14 @@ void setup() { #if FEATURE_SCALE == 1 editableVars["TARE_ON"] = { - .displayName = F("Tare"), .hasHelpText = false, .helpText = "", .type = kUInt8, .section = sScaleSection, .position = 32, .show = [] { return false; }, .minValue = 0, .maxValue = 1, .ptr = (void*)&scaleTareOn}; + .displayName = F("Tare"), .hasHelpText = false, .helpText = "", .type = kUInt8, .section = sScaleSection, .position = 31, .show = [] { return false; }, .minValue = 0, .maxValue = 1, .ptr = (void*)&scaleTareOn}; editableVars["CALIBRATION_ON"] = {.displayName = F("Calibration"), .hasHelpText = false, .helpText = "", .type = kUInt8, .section = sScaleSection, - .position = 33, + .position = 32, .show = [] { return false; }, .minValue = 0, .maxValue = 1, @@ -1519,7 +1305,7 @@ void setup() { .helpText = "", .type = kFloat, .section = sScaleSection, - .position = 34, + .position = 33, .show = [] { return true; }, .minValue = 0, .maxValue = 2000, @@ -1530,7 +1316,7 @@ void setup() { .helpText = "", .type = kFloat, .section = sScaleSection, - .position = 35, + .position = 34, .show = [] { return true; }, .minValue = -100000, .maxValue = 100000, @@ -1541,7 +1327,7 @@ void setup() { .helpText = "", .type = kFloat, .section = sScaleSection, - .position = 36, + .position = 35, .show = [] { return SCALE_TYPE == 0; }, .minValue = -100000, .maxValue = 100000, @@ -1549,7 +1335,7 @@ void setup() { #endif editableVars["VERSION"] = { - .displayName = F("Version"), .hasHelpText = false, .helpText = "", .type = kCString, .section = sOtherSection, .position = 33, .show = [] { return false; }, .minValue = 0, .maxValue = 1, .ptr = (void*)sysVersion}; + .displayName = F("Version"), .hasHelpText = false, .helpText = "", .type = kCString, .section = sOtherSection, .position = 36, .show = [] { return false; }, .minValue = 0, .maxValue = 1, .ptr = (void*)sysVersion}; // when adding parameters, set EDITABLE_VARS_LEN to max of .position #if (FEATURE_PRESSURESENSOR == 1) @@ -1594,16 +1380,11 @@ void setup() { mqttVars["scaleCalibrationOn"] = [] { return &editableVars.at("CALIBRATION_ON"); }; } - if (FEATURE_BREWDETECTION == 1) { + if (FEATURE_BREWSWITCH == 1) { mqttVars["pidUseBD"] = [] { return &editableVars.at("PID_BD_ON"); }; mqttVars["aggbKp"] = [] { return &editableVars.at("PID_BD_KP"); }; mqttVars["aggbTn"] = [] { return &editableVars.at("PID_BD_TN"); }; mqttVars["aggbTv"] = [] { return &editableVars.at("PID_BD_TV"); }; - - if (BREWDETECTION_TYPE == 1) { - mqttVars["brewTimer"] = [] { return &editableVars.at("PID_BD_TIME"); }; - mqttVars["brewLimit"] = [] { return &editableVars.at("PID_BD_SENSITIVITY"); }; - } } // Values reported to MQTT @@ -1627,15 +1408,6 @@ void setup() { storageSetup(); - if (optocouplerType == HIGH) { - optocouplerOn = HIGH; - optocouplerOff = LOW; - } - else { - optocouplerOn = LOW; - optocouplerOff = HIGH; - } - heaterRelay.off(); valveRelay.off(); pumpRelay.off(); @@ -1648,16 +1420,7 @@ void setup() { steamSwitch = new IOSwitch(PIN_STEAMSWITCH, GPIOPin::IN_HARDWARE, STEAMSWITCH_TYPE, STEAMSWITCH_MODE); } - // IF optocoupler selected - if (BREWDETECTION_TYPE == 3) { - if (optocouplerType == HIGH) { - pinMode(PIN_BREWSWITCH, INPUT_PULLDOWN); - } - else { - pinMode(PIN_BREWSWITCH, INPUT_PULLUP); - } - } - else if (FEATURE_BREWSWITCH) { + if (FEATURE_BREWSWITCH) { brewSwitch = new IOSwitch(PIN_BREWSWITCH, GPIOPin::IN_HARDWARE, BREWSWITCH_TYPE, BREWSWITCH_MODE); } @@ -1747,7 +1510,6 @@ void setup() { previousMillistemp = currentTime; windowStartTime = currentTime; previousMillisMQTT = currentTime; - previousMillisOptocouplerReading = currentTime; lastMQTTConnectionAttempt = currentTime; #if FEATURE_SCALE == 1 @@ -1855,8 +1617,7 @@ void looppid() { LOGF(TRACE, "Current Machinestate: %s", machinestateEnumToString(machineState)); LOGF(TRACE, "timeBrewed %f", timeBrewed); LOGF(TRACE, "brewtimesoftware %f", brewtimesoftware); - LOGF(TRACE, "isBrewDetected %i", isBrewDetected); - LOGF(TRACE, "brewDetectionMode %i", brewDetectionMode); + LOGF(TRACE, "Brew detected %i", brewOn); } } diff --git a/src/steamHandler.h b/src/steamHandler.h index 9dcff5a54..ef56b5aaa 100644 --- a/src/steamHandler.h +++ b/src/steamHandler.h @@ -20,20 +20,6 @@ void checkSteamSwitch() { if (steamSwitchReading == LOW && !steamFirstON) { steamON = 0; } - - // monitor QuickMill thermoblock steam-mode - if (machine == QuickMill) { - if (steamQM_active == true) { - if (checkSteamOffQM() == true) { // if true: steam-mode can be turned off - steamON = 0; - steamQM_active = false; - lastTimeOptocouplerOn = 0; - } - else { - steamON = 1; - } - } - } } else if (STEAMSWITCH_TYPE == Switch::MOMENTARY) { if (steamSwitchReading != currStateSteamSwitch) { diff --git a/src/userConfig_sample.h b/src/userConfig_sample.h index 7849f7f52..2bd59e002 100644 --- a/src/userConfig_sample.h +++ b/src/userConfig_sample.h @@ -51,8 +51,6 @@ enum MACHINE { // PID & Hardware #define FEATURE_BREWCONTROL 0 // 0 = deactivated, 1 = activated -#define FEATURE_BREWDETECTION 1 // 0 = deactivated, 1 = activated -#define BREWDETECTION_TYPE 1 // 1 = Software (FEATURE_BREWCONTROL 0), 2 = Hardware (FEATURE_BREWCONTROL 1), 3 = Optocoupler (FEATURE_BREWCONTROL 0) #define FEATURE_POWERSWITCH 0 // 0 = deactivated, 1 = activated #define POWERSWITCH_TYPE Switch::TOGGLE // Switch::TOGGLE or Switch::MOMENTARY (trigger) #define POWERSWITCH_MODE Switch::NORMALLY_OPEN // Switch::NORMALLY_OPEN or Switch::NORMALLY_CLOSED From a40552949308f9f36fa0ba609185b749e4d48a84 Mon Sep 17 00:00:00 2001 From: Lorenz Uhlig <98092139+LoQue90@users.noreply.github.com> Date: Sun, 8 Sep 2024 00:50:59 +0200 Subject: [PATCH 02/23] adding brewtimer adds brewtimer without controlling pump/valve --- src/brewHandler.h | 39 +++++++++++++++++++++++++++++++++++---- src/main.cpp | 6 +++++- 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/src/brewHandler.h b/src/brewHandler.h index 257687e86..d79f3f18a 100644 --- a/src/brewHandler.h +++ b/src/brewHandler.h @@ -46,7 +46,7 @@ uint8_t currBrewSwitchStateMomentary = LOW; int brewSwitchState = kBrewSwitchIdle; boolean brewSwitchWasOff = false; -int isBrewDetected = 0; // flag is set if brew was detected +int brewOn = 0; // flag is set if brew was detected double totalBrewTime = 0; // total brewtime set in software double timeBrewed = 0; // total brewed time double lastBrewTimeMillis = 0; // for shottimer delay after disarmed button @@ -102,7 +102,7 @@ void checkbrewswitch() { if (currBrewSwitchStateMomentary == LOW) { // Brew trigger currStateBrewSwitch = HIGH; - isBrewDetected = 1; + brewOn = 1; brewSwitchState = kBrewSwitchBrewAbort; LOG(DEBUG, "brewSwitchState = kBrewSwitchBrew; brew switch short pressed - start Brew"); } @@ -122,7 +122,7 @@ void checkbrewswitch() { if ((currBrewSwitchStateMomentary == HIGH && currStateBrewSwitch == HIGH) || (machineState == kShotTimerAfterBrew) || (backflushState == kBackflushWaitBrewswitchOff)) { currStateBrewSwitch = LOW; brewSwitchState = kBrewSwitchReset; - isBrewDetected = 0; + brewOn = 0; LOG(DEBUG, "brewSwitchState = kBrewSwitchBrewAbort: brew switch short pressed - stop brew"); } break; @@ -131,7 +131,7 @@ void checkbrewswitch() { // Brew switch got released - stop flushing if (currBrewSwitchStateMomentary == LOW && currStateBrewSwitch == LOW) { brewSwitchState = kBrewSwitchReset; - isBrewDetected = 0; + brewOn = 0; LOG(DEBUG, "brewswitchTriggerCase = kBrewSwitchFlushOff: brew switch long press released - stop flushing"); valveRelay.off(); pumpRelay.off(); @@ -233,6 +233,37 @@ void backflush() { } } +#if (FEATURE_BREWCONTROL == 0) +/** + * @brief Brew timer + */ +void brewTimer() { + unsigned long currentMillisTemp = millis(); + checkbrewswitch(); + + // Start the timer when the brew switch is turned on + if (currStateBrewSwitch == HIGH && currBrewState == kBrewIdle) { + startingTime = currentMillisTemp; + currBrewState = kBrewRunning; + LOG(INFO, "Brew timer started"); + } + + // Update the brewed time if the brew switch is still on + if (currStateBrewSwitch == HIGH && currBrewState == kBrewRunning) { + timeBrewed = currentMillisTemp - startingTime; + } + + // Stop the timer when the brew switch is turned off + if (currStateBrewSwitch == LOW && currBrewState == kBrewRunning) { + LOG(INFO, "Brew timer stopped"); + currBrewState = kBrewIdle; + lastBrewTime = timeBrewed; // store brewtime to show in Shottimer after brew is finished + timeBrewed = 0; + } +} +#endif + + #if (FEATURE_BREWCONTROL == 1) /** * @brief Time base brew mode diff --git a/src/main.cpp b/src/main.cpp index b444d65d6..3e9c6b59f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1626,8 +1626,12 @@ void looppid() { shottimerscale(); // Calculation of weight of shot while brew is running #endif -#if (FEATURE_BREWCONTROL == 1) +#if (FEATURE_BREWSWITCH == 1) + #if (FEATURE_BREWCONTROLL == 0) + brewTimer(); + #elif brew(); + #endif #endif #if (FEATURE_PRESSURESENSOR == 1) From 977a44a0048e47b3f954f3295fca12edb6489f07 Mon Sep 17 00:00:00 2001 From: Lorenz Uhlig <98092139+LoQue90@users.noreply.github.com> Date: Sun, 8 Sep 2024 01:03:32 +0200 Subject: [PATCH 03/23] remove more SW Brew detection and cleanup remove more SW brew detection stuff rename brewtimesoftware to brewPidTime to clarify its function fix debug log output for disable PID while brew is running clang formated --- src/brewHandler.h | 3 +- src/defaults.h | 5 +--- src/display/displayTemplateStandard.h | 8 +----- src/embeddedWebserver.h | 2 +- src/main.cpp | 29 ++++++++----------- src/storage.h | 22 ++++++--------- src/userConfig_sample.h | 40 +++++++++++++-------------- 7 files changed, 44 insertions(+), 65 deletions(-) diff --git a/src/brewHandler.h b/src/brewHandler.h index d79f3f18a..7ce1634b9 100644 --- a/src/brewHandler.h +++ b/src/brewHandler.h @@ -46,7 +46,7 @@ uint8_t currBrewSwitchStateMomentary = LOW; int brewSwitchState = kBrewSwitchIdle; boolean brewSwitchWasOff = false; -int brewOn = 0; // flag is set if brew was detected +int brewOn = 0; // flag is set if brew was detected double totalBrewTime = 0; // total brewtime set in software double timeBrewed = 0; // total brewed time double lastBrewTimeMillis = 0; // for shottimer delay after disarmed button @@ -263,7 +263,6 @@ void brewTimer() { } #endif - #if (FEATURE_BREWCONTROL == 1) /** * @brief Time base brew mode diff --git a/src/defaults.h b/src/defaults.h index 978f3e83c..eb8261caa 100644 --- a/src/defaults.h +++ b/src/defaults.h @@ -37,9 +37,8 @@ int writeSysParamsToStorage(void); #define AGGBTN 0 // PID Tn (brew detection phase) #define AGGBTV 20 // PID Tv (brew detection phase) #define BREW_TIME 25 // brew time in seconds (only used if pump is being controlled) -#define BREW_SW_TIME 25 // keep brew PID params for this many seconds after detection (only for software BD) +#define BREW_PID_TIME 25 // keep brew PID params for this many seconds after detection #define BREW_PID_DELAY 10 // delay until enabling PID controller during brew (no heating during this time) -#define BD_SENSITIVITY 120 // brew detection sensitivity, be careful: if too low, then there is the risk of wrong brew detection and rising temperature #define PRE_INFUSION_TIME 2 // pre-infusion time in seconds #define PRE_INFUSION_PAUSE_TIME 5 // pre-infusion pause time in seconds #define SCALE_WEIGHTSETPOINT 30 // Target weight in grams @@ -82,8 +81,6 @@ int writeSysParamsToStorage(void); #define BREW_PID_DELAY_MAX 60 #define BREW_SW_TIME_MIN 1 #define BREW_SW_TIME_MAX 180 -#define BD_THRESHOLD_MIN 0 -#define BD_THRESHOLD_MAX 999 #define PRE_INFUSION_TIME_MIN 0 #define PRE_INFUSION_TIME_MAX 60 #define PRE_INFUSION_PAUSE_MIN 0 diff --git a/src/display/displayTemplateStandard.h b/src/display/displayTemplateStandard.h index 0d481e6d4..a408edc69 100644 --- a/src/display/displayTemplateStandard.h +++ b/src/display/displayTemplateStandard.h @@ -68,13 +68,7 @@ void printScreen() { u8g2.setCursor(84, 36); u8g2.print(timeBrewed / 1000, 0); u8g2.print("/"); - - if (FEATURE_BREWCONTROL == 0) { - u8g2.print(brewtimesoftware, 0); - } - else { - u8g2.print(totalBrewTime / 1000, 1); - } + u8g2.print(totalBrewTime / 1000, 1); } // PID values over heat bar diff --git a/src/embeddedWebserver.h b/src/embeddedWebserver.h index 310390678..5c312cf10 100644 --- a/src/embeddedWebserver.h +++ b/src/embeddedWebserver.h @@ -58,7 +58,7 @@ void serverSetup(); void setEepromWriteFcn(int (*fcnPtr)(void)); // editable vars are specified in main.cpp -#define EDITABLE_VARS_LEN 36 +#define EDITABLE_VARS_LEN 35 extern std::map editableVars; // EEPROM diff --git a/src/main.cpp b/src/main.cpp index 3e9c6b59f..b05ef0610 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -218,9 +218,8 @@ double aggbKi = aggbKp / aggbTn; #endif double aggbKd = aggbTv * aggbKp; -double brewtimesoftware = BREW_SW_TIME; // use userConfig time until disabling BD PID -double brewSensitivity = BD_SENSITIVITY; // use userConfig brew detection sensitivity -double brewPIDDelay = BREW_PID_DELAY; // use userConfig brew detection PID delay +double brewPidTime = BREW_PID_TIME; // Time while Brew PID is running +double brewPIDDelay = BREW_PID_DELAY; // Time PID will be disabled after brew started uint8_t standbyModeOn = 0; double standbyModeTime = STANDBY_MODE_TIME; @@ -244,8 +243,7 @@ SysPara sysParaTempOffset(&brewTempOffset, BREW_TEMP_OFFSET_MIN, BREW_TE SysPara sysParaBrewPIDDelay(&brewPIDDelay, BREW_PID_DELAY_MIN, BREW_PID_DELAY_MAX, STO_ITEM_BREW_PID_DELAY); SysPara sysParaUseBDPID(&useBDPID, 0, 1, STO_ITEM_USE_BD_PID); SysPara sysParaBrewTime(&brewTime, BREW_TIME_MIN, BREW_TIME_MAX, STO_ITEM_BREW_TIME); -SysPara sysParaBrewSwTime(&brewtimesoftware, BREW_SW_TIME_MIN, BREW_SW_TIME_MAX, STO_ITEM_BREW_SW_TIME); -SysPara sysParaBrewThresh(&brewSensitivity, BD_THRESHOLD_MIN, BD_THRESHOLD_MAX, STO_ITEM_BD_THRESHOLD); +SysPara sysParaBrewPidTime(&brewPidTime, BREW_PID_TIME_MIN, BREW_PID_TIME_MAX, STO_ITEM_BREW_PID_TIME); SysPara sysParaWifiCredentialsSaved(&wifiCredentialsSaved, 0, 1, STO_ITEM_WIFI_CREDENTIALS_SAVED); SysPara sysParaPreInfTime(&preinfusion, PRE_INFUSION_TIME_MIN, PRE_INFUSION_TIME_MAX, STO_ITEM_PRE_INFUSION_TIME); SysPara sysParaPreInfPause(&preinfusionPause, PRE_INFUSION_PAUSE_MIN, PRE_INFUSION_PAUSE_MAX, STO_ITEM_PRE_INFUSION_PAUSE); @@ -608,11 +606,10 @@ void handleMachineState() { case kBrew: - if (currBrewState == kBrewIdle || currBrewState == kWaitBrewOff) - { + if (currBrewState == kBrewIdle || currBrewState == kWaitBrewOff) { // delay shot timer display for voltage sensor or hw brew toggle switch (brew counter) machineState = kShotTimerAfterBrew; - lastBrewTimeMillis = millis(); // for delay + lastBrewTimeMillis = millis(); // for delay } if (steamON == 1) { @@ -1616,7 +1613,7 @@ void looppid() { LOGF(TRACE, "Current PID Output: %f", pidOutput); LOGF(TRACE, "Current Machinestate: %s", machinestateEnumToString(machineState)); LOGF(TRACE, "timeBrewed %f", timeBrewed); - LOGF(TRACE, "brewtimesoftware %f", brewtimesoftware); + LOGF(TRACE, "Brew PID time %f", brewPidTime); LOGF(TRACE, "Brew detected %i", brewOn); } } @@ -1627,11 +1624,11 @@ void looppid() { #endif #if (FEATURE_BREWSWITCH == 1) - #if (FEATURE_BREWCONTROLL == 0) +#if (FEATURE_BREWCONTROLL == 0) brewTimer(); - #elif +#elif brew(); - #endif +#endif #endif #if (FEATURE_PRESSURESENSOR == 1) @@ -1707,7 +1704,7 @@ void looppid() { if (!brewPIDDisabled) { brewPIDDisabled = true; bPID.SetMode(MANUAL); - LOGF(DEBUG, "disabled PID, waiting for %d seconds before enabling PID again", brewPIDDelay); + LOGF(DEBUG, "disabled PID, waiting for %.0f seconds before enabling PID again", brewPIDDelay); } } else { @@ -1870,8 +1867,7 @@ int readSysParamsFromStorage(void) { if (sysParaPidTnBd.getStorage() != 0) return -1; if (sysParaPidTvBd.getStorage() != 0) return -1; if (sysParaBrewTime.getStorage() != 0) return -1; - if (sysParaBrewSwTime.getStorage() != 0) return -1; - if (sysParaBrewThresh.getStorage() != 0) return -1; + if (sysParaBrewPidTime.getStorage() != 0) return -1; if (sysParaPreInfTime.getStorage() != 0) return -1; if (sysParaPreInfPause.getStorage() != 0) return -1; if (sysParaPidKpSteam.getStorage() != 0) return -1; @@ -1912,8 +1908,7 @@ int writeSysParamsToStorage(void) { if (sysParaPidTnBd.setStorage() != 0) return -1; if (sysParaPidTvBd.setStorage() != 0) return -1; if (sysParaBrewTime.setStorage() != 0) return -1; - if (sysParaBrewSwTime.setStorage() != 0) return -1; - if (sysParaBrewThresh.setStorage() != 0) return -1; + if (sysParaBrewPidTime.setStorage() != 0) return -1; if (sysParaPreInfTime.setStorage() != 0) return -1; if (sysParaPreInfPause.setStorage() != 0) return -1; if (sysParaPidKpSteam.setStorage() != 0) return -1; diff --git a/src/storage.h b/src/storage.h index 71ab26c97..ca0691c20 100644 --- a/src/storage.h +++ b/src/storage.h @@ -24,9 +24,8 @@ typedef enum { STO_ITEM_BREW_TEMP_OFFSET, // brew temp offset STO_ITEM_USE_BD_PID, // use separate PID for brew detection (otherwise continue with regular PID) STO_ITEM_BREW_TIME, // brew time - STO_ITEM_BREW_SW_TIME, // brew software time + STO_ITEM_BREW_PID_TIME, // brew PID time STO_ITEM_BREW_PID_DELAY, // brew PID delay - STO_ITEM_BD_THRESHOLD, // brew detection limit STO_ITEM_WIFI_CREDENTIALS_SAVED, // flag for wifisetup STO_ITEM_PRE_INFUSION_TIME, // pre-infusion time STO_ITEM_PRE_INFUSION_PAUSE, // pre-infusion pause @@ -94,10 +93,10 @@ typedef struct __attribute__((packed)) { uint8_t freeToUse8[2]; double pidTvBd; uint8_t freeToUse9[2]; - double brewSwTimeSec; + double brewPidTimeSec; double brewPIDDelaySec; uint8_t freeToUse10; - double brewDetectionThreshold; + double freeToUse11; uint8_t wifiCredentialsSaved; uint8_t useStartPonM; double pidKpStart; @@ -145,10 +144,10 @@ static const sto_data_t itemDefaults PROGMEM = { {0xFF, 0xFF}, // free to use AGGBTV, // STO_ITEM_PID_TV_BD {0xFF, 0xFF}, // free to use - BREW_SW_TIME, // STO_ITEM_BREW_SW_TIME + BREW_PID_TIME, // STO_ITEM_BREW_PID_TIME BREW_PID_DELAY, // STO_ITEM_BREW_PID_DELAY 0xFF, // free to use - BD_SENSITIVITY, // STO_ITEM_BD_THRESHOLD + 0xFF, // free to use WIFI_CREDENTIALS_SAVED, // STO_ITEM_WIFI_CREDENTIALS_SAVED 0, // STO_ITEM_USE_START_PON_M STARTKP, // STO_ITEM_PID_KP_START @@ -254,14 +253,9 @@ static inline int32_t getItemAddr(sto_item_id_t itemId, uint16_t* maxItemSize = size = STRUCT_MEMBER_SIZE(sto_data_t, pidTvBd); break; - case STO_ITEM_BREW_SW_TIME: - addr = offsetof(sto_data_t, brewSwTimeSec); - size = STRUCT_MEMBER_SIZE(sto_data_t, brewSwTimeSec); - break; - - case STO_ITEM_BD_THRESHOLD: - addr = offsetof(sto_data_t, brewDetectionThreshold); - size = STRUCT_MEMBER_SIZE(sto_data_t, brewDetectionThreshold); + case STO_ITEM_BREW_PID_TIME: + addr = offsetof(sto_data_t, brewPidTimeSec); + size = STRUCT_MEMBER_SIZE(sto_data_t, brewPidTimeSec); break; case STO_ITEM_WIFI_CREDENTIALS_SAVED: diff --git a/src/userConfig_sample.h b/src/userConfig_sample.h index 2bd59e002..3cdd72f4e 100644 --- a/src/userConfig_sample.h +++ b/src/userConfig_sample.h @@ -50,26 +50,26 @@ enum MACHINE { #define WIFICONNECTIONDELAY 10000 // delay between reconnects in ms // PID & Hardware -#define FEATURE_BREWCONTROL 0 // 0 = deactivated, 1 = activated -#define FEATURE_POWERSWITCH 0 // 0 = deactivated, 1 = activated -#define POWERSWITCH_TYPE Switch::TOGGLE // Switch::TOGGLE or Switch::MOMENTARY (trigger) -#define POWERSWITCH_MODE Switch::NORMALLY_OPEN // Switch::NORMALLY_OPEN or Switch::NORMALLY_CLOSED -#define FEATURE_BREWSWITCH 0 // 0 = deactivated, 1 = activated -#define BREWSWITCH_TYPE Switch::TOGGLE // Switch::TOGGLE or Switch::MOMENTARY (trigger) -#define BREWSWITCH_MODE Switch::NORMALLY_OPEN // Switch::NORMALLY_OPEN or Switch::NORMALLY_CLOSED -#define FEATURE_STEAMSWITCH 0 // 0 = deactivated, 1 = activated -#define STEAMSWITCH_TYPE Switch::TOGGLE // Switch::TOGGLE or Switch::MOMENTARY (trigger) -#define OPTOCOUPLER_TYPE HIGH // BREWDETECTION 3 configuration; HIGH or LOW trigger optocoupler -#define STEAMSWITCH_MODE Switch::NORMALLY_OPEN // Switch::NORMALLY_OPEN or Switch::NORMALLY_CLOSED -#define HEATER_SSR_TYPE Relay::HIGH_TRIGGER // HIGH_TRIGGER = relay switches when input is HIGH, vice versa for LOW_TRIGGER -#define PUMP_VALVE_SSR_TYPE Relay::HIGH_TRIGGER // HIGH_TRIGGER = relay switches when input is HIGH, vice versa for LOW_TRIGGER -#define FEATURE_STATUS_LED 0 // Blink status LED when temp is in range, 0 = deactivated, 1 = activated -#define FEATURE_BREW_LED 0 // Turn on brew LED when brew is started, 0 = deactivated, 1 = activated -#define LED_TYPE LED::STANDARD // STANDARD_LED for an LED connected to a GPIO pin, WS2812 for adressable LEDs -#define FEATURE_WATER_SENS 0 // 0 = deactivated, 1 = activated -#define WATER_SENS_TYPE Switch::NORMALLY_CLOSED // Switch::NORMALLY_CLOSED for sensor XKC-Y25-NPN or Switch::NORMALLY_OPEN for XKC-Y25-PNP - -#define FEATURE_PRESSURESENSOR 0 // 0 = deactivated, 1 = activated +#define FEATURE_BREWCONTROL 0 // 0 = deactivated, 1 = activated +#define FEATURE_POWERSWITCH 0 // 0 = deactivated, 1 = activated +#define POWERSWITCH_TYPE Switch::TOGGLE // Switch::TOGGLE or Switch::MOMENTARY (trigger) +#define POWERSWITCH_MODE Switch::NORMALLY_OPEN // Switch::NORMALLY_OPEN or Switch::NORMALLY_CLOSED +#define FEATURE_BREWSWITCH 0 // 0 = deactivated, 1 = activated +#define BREWSWITCH_TYPE Switch::TOGGLE // Switch::TOGGLE or Switch::MOMENTARY (trigger) +#define BREWSWITCH_MODE Switch::NORMALLY_OPEN // Switch::NORMALLY_OPEN or Switch::NORMALLY_CLOSED +#define FEATURE_STEAMSWITCH 0 // 0 = deactivated, 1 = activated +#define STEAMSWITCH_TYPE Switch::TOGGLE // Switch::TOGGLE or Switch::MOMENTARY (trigger) +#define OPTOCOUPLER_TYPE HIGH // BREWDETECTION 3 configuration; HIGH or LOW trigger optocoupler +#define STEAMSWITCH_MODE Switch::NORMALLY_OPEN // Switch::NORMALLY_OPEN or Switch::NORMALLY_CLOSED +#define HEATER_SSR_TYPE Relay::HIGH_TRIGGER // HIGH_TRIGGER = relay switches when input is HIGH, vice versa for LOW_TRIGGER +#define PUMP_VALVE_SSR_TYPE Relay::HIGH_TRIGGER // HIGH_TRIGGER = relay switches when input is HIGH, vice versa for LOW_TRIGGER +#define FEATURE_STATUS_LED 0 // Blink status LED when temp is in range, 0 = deactivated, 1 = activated +#define FEATURE_BREW_LED 0 // Turn on brew LED when brew is started, 0 = deactivated, 1 = activated +#define LED_TYPE LED::STANDARD // STANDARD_LED for an LED connected to a GPIO pin, WS2812 for adressable LEDs +#define FEATURE_WATER_SENS 0 // 0 = deactivated, 1 = activated +#define WATER_SENS_TYPE Switch::NORMALLY_CLOSED // Switch::NORMALLY_CLOSED for sensor XKC-Y25-NPN or Switch::NORMALLY_OPEN for XKC-Y25-PNP + +#define FEATURE_PRESSURESENSOR 0 // 0 = deactivated, 1 = activated // Brew Scale #define FEATURE_SCALE 0 // 0 = deactivated, 1 = activated From b65409f44085adc651389cf307f234d3758711a9 Mon Sep 17 00:00:00 2001 From: Lorenz Uhlig <98092139+LoQue90@users.noreply.github.com> Date: Sun, 8 Sep 2024 02:18:13 +0200 Subject: [PATCH 04/23] remove Brew PID Time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit remove brew PID time (former Brew SW Time) because it isn´t used anymore after removing sw brew detection --- src/defaults.h | 84 ++++++++++++++++++++++++-------------------------- src/main.cpp | 58 ++++++++-------------------------- src/storage.h | 20 +++++------- 3 files changed, 61 insertions(+), 101 deletions(-) diff --git a/src/defaults.h b/src/defaults.h index eb8261caa..973b6da3e 100644 --- a/src/defaults.h +++ b/src/defaults.h @@ -37,7 +37,6 @@ int writeSysParamsToStorage(void); #define AGGBTN 0 // PID Tn (brew detection phase) #define AGGBTV 20 // PID Tv (brew detection phase) #define BREW_TIME 25 // brew time in seconds (only used if pump is being controlled) -#define BREW_PID_TIME 25 // keep brew PID params for this many seconds after detection #define BREW_PID_DELAY 10 // delay until enabling PID controller during brew (no heating during this time) #define PRE_INFUSION_TIME 2 // pre-infusion time in seconds #define PRE_INFUSION_PAUSE_TIME 5 // pre-infusion pause time in seconds @@ -49,51 +48,50 @@ int writeSysParamsToStorage(void); #define BACKFLUSH_FILL_TIME 5 // time in seconds the pump is running during backflush #define BACKFLUSH_FLUSH_TIME 10 // time in seconds the 3-way valve is open during backflush -#define PID_KP_START_MIN 0 -#define PID_KP_START_MAX 999 -#define PID_TN_START_MIN 0 -#define PID_TN_START_MAX 999 -#define PID_KP_REGULAR_MIN 0 -#define PID_KP_REGULAR_MAX 999 -#define PID_TN_REGULAR_MIN 0 -#define PID_TN_REGULAR_MAX 999 -#define PID_TV_REGULAR_MIN 0 -#define PID_TV_REGULAR_MAX 999 -#define PID_I_MAX_REGULAR_MIN 0 -#define PID_I_MAX_REGULAR_MAX 999 -#define PID_KP_BD_MIN 0 -#define PID_KP_BD_MAX 999 -#define PID_TN_BD_MIN 0 -#define PID_TN_BD_MAX 999 -#define PID_TV_BD_MIN 0 -#define PID_TV_BD_MAX 999 -#define BREW_SETPOINT_MIN 20 -#define BREW_SETPOINT_MAX 110 -#define STEAM_SETPOINT_MIN 100 -#define STEAM_SETPOINT_MAX 140 -#define BREW_TEMP_OFFSET_MIN 0 -#define BREW_TEMP_OFFSET_MAX 20 -#define BREW_TEMP_TIME_MIN 1 -#define BREW_TEMP_TIME_MAX 180 -#define BREW_TIME_MIN 0 -#define BREW_TIME_MAX 180 -#define BREW_PID_DELAY_MIN 0 -#define BREW_PID_DELAY_MAX 60 -#define BREW_SW_TIME_MIN 1 -#define BREW_SW_TIME_MAX 180 -#define PRE_INFUSION_TIME_MIN 0 -#define PRE_INFUSION_TIME_MAX 60 -#define PRE_INFUSION_PAUSE_MIN 0 -#define PRE_INFUSION_PAUSE_MAX 60 -#define WEIGHTSETPOINT_MIN 0 -#define WEIGHTSETPOINT_MAX 500 -#define PID_KP_STEAM_MIN 0 -#define PID_KP_STEAM_MAX 500 -#define STANDBY_MODE_TIME_MIN 30 -#define STANDBY_MODE_TIME_MAX 120 +#define PID_KP_START_MIN 0 +#define PID_KP_START_MAX 999 +#define PID_TN_START_MIN 0 +#define PID_TN_START_MAX 999 +#define PID_KP_REGULAR_MIN 0 +#define PID_KP_REGULAR_MAX 999 +#define PID_TN_REGULAR_MIN 0 +#define PID_TN_REGULAR_MAX 999 +#define PID_TV_REGULAR_MIN 0 +#define PID_TV_REGULAR_MAX 999 +#define PID_I_MAX_REGULAR_MIN 0 +#define PID_I_MAX_REGULAR_MAX 999 +#define PID_KP_BD_MIN 0 +#define PID_KP_BD_MAX 999 +#define PID_TN_BD_MIN 0 +#define PID_TN_BD_MAX 999 +#define PID_TV_BD_MIN 0 +#define PID_TV_BD_MAX 999 +#define BREW_SETPOINT_MIN 20 +#define BREW_SETPOINT_MAX 110 +#define STEAM_SETPOINT_MIN 100 +#define STEAM_SETPOINT_MAX 140 +#define BREW_TEMP_OFFSET_MIN 0 +#define BREW_TEMP_OFFSET_MAX 20 +#define BREW_TEMP_TIME_MIN 1 +#define BREW_TEMP_TIME_MAX 180 +#define BREW_TIME_MIN 0 +#define BREW_TIME_MAX 180 +#define BREW_PID_DELAY_MIN 0 +#define BREW_PID_DELAY_MAX 60 +#define PRE_INFUSION_TIME_MIN 0 +#define PRE_INFUSION_TIME_MAX 60 +#define PRE_INFUSION_PAUSE_MIN 0 +#define PRE_INFUSION_PAUSE_MAX 60 +#define WEIGHTSETPOINT_MIN 0 +#define WEIGHTSETPOINT_MAX 500 +#define PID_KP_STEAM_MIN 0 +#define PID_KP_STEAM_MAX 500 +#define STANDBY_MODE_TIME_MIN 30 +#define STANDBY_MODE_TIME_MAX 120 #define BACKFLUSH_CYCLES_MIN 2 #define BACKFLUSH_CYCLES_MAX 20 #define BACKFLUSH_FILL_TIME_MIN 5 #define BACKFLUSH_FILL_TIME_MAX 20 #define BACKFLUSH_FLUSH_TIME_MIN 5 #define BACKFLUSH_FLUSH_TIME_MAX 20 + diff --git a/src/main.cpp b/src/main.cpp index b05ef0610..1c66eba55 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -218,7 +218,6 @@ double aggbKi = aggbKp / aggbTn; #endif double aggbKd = aggbTv * aggbKp; -double brewPidTime = BREW_PID_TIME; // Time while Brew PID is running double brewPIDDelay = BREW_PID_DELAY; // Time PID will be disabled after brew started uint8_t standbyModeOn = 0; @@ -243,7 +242,6 @@ SysPara sysParaTempOffset(&brewTempOffset, BREW_TEMP_OFFSET_MIN, BREW_TE SysPara sysParaBrewPIDDelay(&brewPIDDelay, BREW_PID_DELAY_MIN, BREW_PID_DELAY_MAX, STO_ITEM_BREW_PID_DELAY); SysPara sysParaUseBDPID(&useBDPID, 0, 1, STO_ITEM_USE_BD_PID); SysPara sysParaBrewTime(&brewTime, BREW_TIME_MIN, BREW_TIME_MAX, STO_ITEM_BREW_TIME); -SysPara sysParaBrewPidTime(&brewPidTime, BREW_PID_TIME_MIN, BREW_PID_TIME_MAX, STO_ITEM_BREW_PID_TIME); SysPara sysParaWifiCredentialsSaved(&wifiCredentialsSaved, 0, 1, STO_ITEM_WIFI_CREDENTIALS_SAVED); SysPara sysParaPreInfTime(&preinfusion, PRE_INFUSION_TIME_MIN, PRE_INFUSION_TIME_MAX, STO_ITEM_PRE_INFUSION_TIME); SysPara sysParaPreInfPause(&preinfusionPause, PRE_INFUSION_PAUSE_MIN, PRE_INFUSION_PAUSE_MAX, STO_ITEM_PRE_INFUSION_PAUSE); @@ -1227,45 +1225,18 @@ void setup() { .maxValue = PID_TV_BD_MAX, .ptr = (void*)&aggbTv}; - editableVars["PID_BD_TIME"] = {.displayName = F("PID BD Time (s)"), - .hasHelpText = true, - .helpText = F("Fixed time in seconds for which the BD PID will stay " - "enabled (also after Brew switch is inactive again)."), - .type = kDouble, - .section = sBDSection, - .position = 26, - .show = [] { return true && FEATURE_BREWDETECTION == 1 && (useBDPID || BREWDETECTION_TYPE == 1); }, - .minValue = BREW_SW_TIME_MIN, - .maxValue = BREW_SW_TIME_MAX, - .ptr = (void*)&brewtimesoftware}; - - editableVars["STEAM_MODE"] = {.displayName = F("Steam Mode"), - .hasHelpText = false, - .helpText = "", - .type = kUInt8, - .section = sOtherSection, - .position = 27, .show = [] { return false; }, - .minValue = 0, - .maxValue = 1, - .ptr = (void*)&steamON}; - - editableVars["BACKFLUSH_ON"] = {.displayName = F("Backflush"), - .hasHelpText = false, - .helpText = "", - .type = kUInt8, - .section = sOtherSection, - .position = 28, - .show = [] { return false; }, - .minValue = 0, - .maxValue = 1, - .ptr = (void*)&backflushOn}; + editableVars["STEAM_MODE"] = { + .displayName = F("Steam Mode"), .hasHelpText = false, .helpText = "", .type = kUInt8, .section = sOtherSection, .position = 26, .show = [] { return false; }, .minValue = 0, .maxValue = 1, .ptr = (void*)&steamON}; + + editableVars["BACKFLUSH_ON"] = { + .displayName = F("Backflush"), .hasHelpText = false, .helpText = "", .type = kUInt8, .section = sOtherSection, .position = 27, .show = [] { return false; }, .minValue = 0, .maxValue = 1, .ptr = (void*)&backflushOn}; editableVars["STANDBY_MODE_ON"] = {.displayName = F("Enable Standby Timer"), .hasHelpText = true, .helpText = F("Turn heater off after standby time has elapsed."), .type = kUInt8, .section = sPowerSection, - .position = 29, + .position = 28, .show = [] { return true; }, .minValue = 0, .maxValue = 1, @@ -1276,7 +1247,7 @@ void setup() { .helpText = F("Time in minutes until the heater is turned off. Timer is reset by brew detection."), .type = kDouble, .section = sPowerSection, - .position = 30, + .position = 29, .show = [] { return true; }, .minValue = STANDBY_MODE_TIME_MIN, .maxValue = STANDBY_MODE_TIME_MAX, @@ -1284,14 +1255,14 @@ void setup() { #if FEATURE_SCALE == 1 editableVars["TARE_ON"] = { - .displayName = F("Tare"), .hasHelpText = false, .helpText = "", .type = kUInt8, .section = sScaleSection, .position = 31, .show = [] { return false; }, .minValue = 0, .maxValue = 1, .ptr = (void*)&scaleTareOn}; + .displayName = F("Tare"), .hasHelpText = false, .helpText = "", .type = kUInt8, .section = sScaleSection, .position = 30, .show = [] { return false; }, .minValue = 0, .maxValue = 1, .ptr = (void*)&scaleTareOn}; editableVars["CALIBRATION_ON"] = {.displayName = F("Calibration"), .hasHelpText = false, .helpText = "", .type = kUInt8, .section = sScaleSection, - .position = 32, + .position = 31, .show = [] { return false; }, .minValue = 0, .maxValue = 1, @@ -1302,7 +1273,7 @@ void setup() { .helpText = "", .type = kFloat, .section = sScaleSection, - .position = 33, + .position = 32, .show = [] { return true; }, .minValue = 0, .maxValue = 2000, @@ -1313,7 +1284,7 @@ void setup() { .helpText = "", .type = kFloat, .section = sScaleSection, - .position = 34, + .position = 33, .show = [] { return true; }, .minValue = -100000, .maxValue = 100000, @@ -1324,7 +1295,7 @@ void setup() { .helpText = "", .type = kFloat, .section = sScaleSection, - .position = 35, + .position = 34, .show = [] { return SCALE_TYPE == 0; }, .minValue = -100000, .maxValue = 100000, @@ -1332,7 +1303,7 @@ void setup() { #endif editableVars["VERSION"] = { - .displayName = F("Version"), .hasHelpText = false, .helpText = "", .type = kCString, .section = sOtherSection, .position = 36, .show = [] { return false; }, .minValue = 0, .maxValue = 1, .ptr = (void*)sysVersion}; + .displayName = F("Version"), .hasHelpText = false, .helpText = "", .type = kCString, .section = sOtherSection, .position = 35, .show = [] { return false; }, .minValue = 0, .maxValue = 1, .ptr = (void*)sysVersion}; // when adding parameters, set EDITABLE_VARS_LEN to max of .position #if (FEATURE_PRESSURESENSOR == 1) @@ -1613,7 +1584,6 @@ void looppid() { LOGF(TRACE, "Current PID Output: %f", pidOutput); LOGF(TRACE, "Current Machinestate: %s", machinestateEnumToString(machineState)); LOGF(TRACE, "timeBrewed %f", timeBrewed); - LOGF(TRACE, "Brew PID time %f", brewPidTime); LOGF(TRACE, "Brew detected %i", brewOn); } } @@ -1867,7 +1837,6 @@ int readSysParamsFromStorage(void) { if (sysParaPidTnBd.getStorage() != 0) return -1; if (sysParaPidTvBd.getStorage() != 0) return -1; if (sysParaBrewTime.getStorage() != 0) return -1; - if (sysParaBrewPidTime.getStorage() != 0) return -1; if (sysParaPreInfTime.getStorage() != 0) return -1; if (sysParaPreInfPause.getStorage() != 0) return -1; if (sysParaPidKpSteam.getStorage() != 0) return -1; @@ -1908,7 +1877,6 @@ int writeSysParamsToStorage(void) { if (sysParaPidTnBd.setStorage() != 0) return -1; if (sysParaPidTvBd.setStorage() != 0) return -1; if (sysParaBrewTime.setStorage() != 0) return -1; - if (sysParaBrewPidTime.setStorage() != 0) return -1; if (sysParaPreInfTime.setStorage() != 0) return -1; if (sysParaPreInfPause.setStorage() != 0) return -1; if (sysParaPidKpSteam.setStorage() != 0) return -1; diff --git a/src/storage.h b/src/storage.h index ca0691c20..8ea99fc69 100644 --- a/src/storage.h +++ b/src/storage.h @@ -24,7 +24,6 @@ typedef enum { STO_ITEM_BREW_TEMP_OFFSET, // brew temp offset STO_ITEM_USE_BD_PID, // use separate PID for brew detection (otherwise continue with regular PID) STO_ITEM_BREW_TIME, // brew time - STO_ITEM_BREW_PID_TIME, // brew PID time STO_ITEM_BREW_PID_DELAY, // brew PID delay STO_ITEM_WIFI_CREDENTIALS_SAVED, // flag for wifisetup STO_ITEM_PRE_INFUSION_TIME, // pre-infusion time @@ -93,18 +92,18 @@ typedef struct __attribute__((packed)) { uint8_t freeToUse8[2]; double pidTvBd; uint8_t freeToUse9[2]; - double brewPidTimeSec; + double freeToUse10; double brewPIDDelaySec; - uint8_t freeToUse10; - double freeToUse11; + uint8_t freeToUse11; + double freeToUse12; uint8_t wifiCredentialsSaved; uint8_t useStartPonM; double pidKpStart; - uint8_t freeToUse12[2]; + uint8_t freeToUse13[2]; uint8_t softApEnabledCheck; - uint8_t freeToUse13[9]; + uint8_t freeToUse14[9]; double pidTnStart; - uint8_t freeToUse14[2]; + uint8_t freeToUse15[2]; char wifiSSID[25 + 1]; char wifiPassword[25 + 1]; double weightSetpoint; @@ -144,7 +143,7 @@ static const sto_data_t itemDefaults PROGMEM = { {0xFF, 0xFF}, // free to use AGGBTV, // STO_ITEM_PID_TV_BD {0xFF, 0xFF}, // free to use - BREW_PID_TIME, // STO_ITEM_BREW_PID_TIME + 0xFF, // free to use BREW_PID_DELAY, // STO_ITEM_BREW_PID_DELAY 0xFF, // free to use 0xFF, // free to use @@ -253,11 +252,6 @@ static inline int32_t getItemAddr(sto_item_id_t itemId, uint16_t* maxItemSize = size = STRUCT_MEMBER_SIZE(sto_data_t, pidTvBd); break; - case STO_ITEM_BREW_PID_TIME: - addr = offsetof(sto_data_t, brewPidTimeSec); - size = STRUCT_MEMBER_SIZE(sto_data_t, brewPidTimeSec); - break; - case STO_ITEM_WIFI_CREDENTIALS_SAVED: addr = offsetof(sto_data_t, wifiCredentialsSaved); size = STRUCT_MEMBER_SIZE(sto_data_t, wifiCredentialsSaved); From 99bff946a9d18cb7c5dd40401d9f27ac8ec726f2 Mon Sep 17 00:00:00 2001 From: Lorenz Uhlig <98092139+LoQue90@users.noreply.github.com> Date: Sun, 8 Sep 2024 02:38:24 +0200 Subject: [PATCH 05/23] fix makros for brew() and brewTimer() --- src/main.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 1c66eba55..2bcb20b14 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -605,7 +605,7 @@ void handleMachineState() { case kBrew: if (currBrewState == kBrewIdle || currBrewState == kWaitBrewOff) { - // delay shot timer display for voltage sensor or hw brew toggle switch (brew counter) + // delay shot timer display after brewSwitch got released machineState = kShotTimerAfterBrew; lastBrewTimeMillis = millis(); // for delay } @@ -1593,12 +1593,12 @@ void looppid() { shottimerscale(); // Calculation of weight of shot while brew is running #endif -#if (FEATURE_BREWSWITCH == 1) -#if (FEATURE_BREWCONTROLL == 0) +#if (FEATURE_BREWSWITCH == 1 && FEATURE_BREWCONTROL == 0) brewTimer(); -#elif - brew(); #endif + +#if (FEATURE_BREWSWITCH == 1 && FEATURE_BREWCONTROL == 1) + brew(); #endif #if (FEATURE_PRESSURESENSOR == 1) From bdf5ba61c115ec45155dfa3e4a6749f9574d8e8b Mon Sep 17 00:00:00 2001 From: Lorenz Uhlig <98092139+LoQue90@users.noreply.github.com> Date: Tue, 10 Sep 2024 02:03:11 +0200 Subject: [PATCH 06/23] clean checkbrewswitch() --- src/brewHandler.h | 54 ++++++++++++++++++------------------- src/display/displayCommon.h | 12 ++++----- 2 files changed, 32 insertions(+), 34 deletions(-) diff --git a/src/brewHandler.h b/src/brewHandler.h index 7ce1634b9..f41f7078f 100644 --- a/src/brewHandler.h +++ b/src/brewHandler.h @@ -12,9 +12,9 @@ enum BrewSwitchState { kBrewSwitchIdle = 10, kBrewSwitchBrew = 20, - kBrewSwitchBrewAbort = 30, - kBrewSwitchFlushOff = 31, - kBrewSwitchReset = 40 + kBrewSwitchActive = 30, + kBrewSwitchFlush = 40, + kBrewSwitchWaitForRelease = 50 }; enum BrewState { @@ -97,52 +97,50 @@ void checkbrewswitch() { } break; - case kBrewSwitchBrew: - // Brew switch short pressed - start brew - if (currBrewSwitchStateMomentary == LOW) { - // Brew trigger + case kBrewSwitchBrew: // Brew switch short pressed - start brew + if (currBrewSwitchStateMomentary == LOW && currStateBrewSwitch == LOW) { currStateBrewSwitch = HIGH; brewOn = 1; - brewSwitchState = kBrewSwitchBrewAbort; + brewSwitchState = kBrewSwitchActive; LOG(DEBUG, "brewSwitchState = kBrewSwitchBrew; brew switch short pressed - start Brew"); } - - // Brew switch more than brewSwitchMomentaryLongPress pressed - start flushing - if (currBrewSwitchStateMomentary == HIGH && brewSwitch->longPressDetected() && machineState != kWaterEmpty) { - brewSwitchState = kBrewSwitchFlushOff; + 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"); } break; - case kBrewSwitchBrewAbort: - // Brew switch got short pressed while brew is running - abort brew - if ((currBrewSwitchStateMomentary == HIGH && currStateBrewSwitch == HIGH) || (machineState == kShotTimerAfterBrew) || (backflushState == kBackflushWaitBrewswitchOff)) { + case kBrewSwitchActive: + if (currBrewSwitchStateMomentary == HIGH && currStateBrewSwitch == HIGH) { // Brew switch got short pressed while brew is running - abort brew currStateBrewSwitch = LOW; - brewSwitchState = kBrewSwitchReset; brewOn = 0; - LOG(DEBUG, "brewSwitchState = kBrewSwitchBrewAbort: brew switch short pressed - stop brew"); + brewSwitchState = kBrewSwitchWaitForRelease; + LOG(DEBUG, "brewSwitchState = kBrewSwitchActive: brew switch short pressed - stop brew"); + } + else if ((machineState == kShotTimerAfterBrew) || (backflushState == kBackflushWaitBrewswitchOff)) { // Brew reached target and stopped or blackflush cycle done + currStateBrewSwitch = LOW; + brewOn = 0; + brewSwitchState = kBrewSwitchWaitForRelease; + LOG(DEBUG, "brewSwitchState = kBrewSwitchActive: brew reached target or backflush done - reset brew switch"); } break; - case kBrewSwitchFlushOff: - // Brew switch got released - stop flushing - if (currBrewSwitchStateMomentary == LOW && currStateBrewSwitch == LOW) { - brewSwitchState = kBrewSwitchReset; - brewOn = 0; - LOG(DEBUG, "brewswitchTriggerCase = kBrewSwitchFlushOff: brew switch long press released - stop flushing"); + 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"); } break; - case kBrewSwitchReset: - // Brew switch is released - go back to start and wait for next brew switch input + case kBrewSwitchWaitForRelease: // wait for brew switch got released if (currBrewSwitchStateMomentary == LOW) { brewSwitchState = kBrewSwitchIdle; - LOG(DEBUG, "brewSwitchState = kBrewSwitchReset: brew switch released - go to kBrewSwitchIdle "); + LOG(DEBUG, "brewSwitchState = kBrewSwitchWaitForRelease: brew switch released - go to kBrewSwitchIdle"); } break; } @@ -265,7 +263,7 @@ void brewTimer() { #if (FEATURE_BREWCONTROL == 1) /** - * @brief Time base brew mode + * @brief Time or weight based brew mode */ void brew() { unsigned long currentMillisTemp = millis(); @@ -277,7 +275,7 @@ void brew() { currBrewState = kWaitBrewOff; } - if (currBrewState > kBrewIdle && currBrewState < kWaitBrewOff || brewSwitchState == kBrewSwitchFlushOff) { + if (currBrewState > kBrewIdle && currBrewState < kWaitBrewOff || brewSwitchState == kBrewSwitchFlush) { timeBrewed = currentMillisTemp - startingTime; } diff --git a/src/display/displayCommon.h b/src/display/displayCommon.h index 5c28eb351..7acd901df 100644 --- a/src/display/displayCommon.h +++ b/src/display/displayCommon.h @@ -241,10 +241,10 @@ bool displayShottimer() { return false; } - if (machineState == kBrew || brewSwitchState == kBrewSwitchFlushOff) { + if (machineState == kBrew || brewSwitchState == kBrewSwitchFlush) { u8g2.clearBuffer(); - if (brewSwitchState != kBrewSwitchFlushOff) { + if (brewSwitchState != kBrewSwitchFlush) { u8g2.drawXBMP(-1, 11, Brew_Cup_Logo_width, Brew_Cup_Logo_height, Brew_Cup_Logo); } else { @@ -273,7 +273,7 @@ bool displayShottimer() { * nothing should be done, otherwise wrong time is displayed * because the switch is pressed later than totalBrewTime */ - else if (machineState == kShotTimerAfterBrew && brewSwitchState != kBrewSwitchFlushOff) { + else if (machineState == kShotTimerAfterBrew && brewSwitchState != kBrewSwitchFlush) { u8g2.clearBuffer(); u8g2.drawXBMP(-1, 11, Brew_Cup_Logo_width, Brew_Cup_Logo_height, Brew_Cup_Logo); @@ -302,7 +302,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 != kBrewSwitchFlushOff) { + if (FEATURE_HEATINGLOGO > 0 && machineState == kPidNormal && (setpoint - temperature) > 5. && brewSwitchState != kBrewSwitchFlush) { // For status info u8g2.clearBuffer(); @@ -339,7 +339,7 @@ bool displayMachineState() { return true; } // Steam - else if (machineState == kSteam && brewSwitchState != kBrewSwitchFlushOff) { + else if (machineState == kSteam && brewSwitchState != kBrewSwitchFlush) { u8g2.clearBuffer(); u8g2.drawXBMP(-1, 12, Steam_Logo_width, Steam_Logo_height, Steam_Logo); @@ -350,7 +350,7 @@ bool displayMachineState() { return true; } // Water empty - else if (machineState == kWaterEmpty && brewSwitchState != kBrewSwitchFlushOff) { + else if (machineState == kWaterEmpty && brewSwitchState != kBrewSwitchFlush) { u8g2.clearBuffer(); u8g2.drawXBMP(45, 0, Water_Empty_Logo_width, Water_Empty_Logo_height, Water_Empty_Logo); u8g2.setFont(u8g2_font_profont11_tf); From fa6d9007a8db16823455ac4e2a31811173f5c4fd Mon Sep 17 00:00:00 2001 From: Lorenz Uhlig <98092139+LoQue90@users.noreply.github.com> Date: Mon, 16 Sep 2024 11:20:55 +0200 Subject: [PATCH 07/23] move shot timer log to brewHandler --- src/brewHandler.h | 2 ++ src/main.cpp | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/brewHandler.h b/src/brewHandler.h index f41f7078f..6a02f9cd3 100644 --- a/src/brewHandler.h +++ b/src/brewHandler.h @@ -257,6 +257,7 @@ void brewTimer() { currBrewState = kBrewIdle; lastBrewTime = timeBrewed; // store brewtime to show in Shottimer after brew is finished timeBrewed = 0; + LOGF(INFO, "Shot time: %4.1f s", lastBrewTime / 1000); } } #endif @@ -383,6 +384,7 @@ void brew() { currBrewState = kBrewIdle; lastBrewTime = timeBrewed; // store brewtime to show in Shottimer after brew is finished timeBrewed = 0; + LOGF(INFO, "Shot time: %4.1f s", lastBrewTime / 1000); } break; diff --git a/src/main.cpp b/src/main.cpp index 2bcb20b14..0799ba23f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -630,7 +630,6 @@ void handleMachineState() { case kShotTimerAfterBrew: if (millis() - lastBrewTimeMillis > SHOTTIMERDISPLAYDELAY) { - LOGF(INFO, "Shot time: %4.1f s", lastBrewTime / 1000); machineState = kPidNormal; } From 7f1706afd9054ddf671e04d03b13004f5b7c4802 Mon Sep 17 00:00:00 2001 From: Lorenz Uhlig <98092139+LoQue90@users.noreply.github.com> Date: Mon, 16 Sep 2024 11:23:01 +0200 Subject: [PATCH 08/23] add brewOn to brewTimer now with brewControl 0 mashine goes to kBrew when a brew is running --- src/brewHandler.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/brewHandler.h b/src/brewHandler.h index 6a02f9cd3..dcadd7a4f 100644 --- a/src/brewHandler.h +++ b/src/brewHandler.h @@ -241,6 +241,7 @@ void brewTimer() { // Start the timer when the brew switch is turned on if (currStateBrewSwitch == HIGH && currBrewState == kBrewIdle) { + brewOn = 1; startingTime = currentMillisTemp; currBrewState = kBrewRunning; LOG(INFO, "Brew timer started"); @@ -254,6 +255,7 @@ void brewTimer() { // Stop the timer when the brew switch is turned off if (currStateBrewSwitch == LOW && currBrewState == kBrewRunning) { LOG(INFO, "Brew timer stopped"); + brewOn = 0; currBrewState = kBrewIdle; lastBrewTime = timeBrewed; // store brewtime to show in Shottimer after brew is finished timeBrewed = 0; From 6b1703bf967eed32158507df4eb2dabb0b740757 Mon Sep 17 00:00:00 2001 From: Lorenz Uhlig <98092139+LoQue90@users.noreply.github.com> Date: Mon, 16 Sep 2024 11:23:32 +0200 Subject: [PATCH 09/23] remove more optocoupler makro --- src/userConfig_sample.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/userConfig_sample.h b/src/userConfig_sample.h index 3cdd72f4e..65222effb 100644 --- a/src/userConfig_sample.h +++ b/src/userConfig_sample.h @@ -59,7 +59,6 @@ enum MACHINE { #define BREWSWITCH_MODE Switch::NORMALLY_OPEN // Switch::NORMALLY_OPEN or Switch::NORMALLY_CLOSED #define FEATURE_STEAMSWITCH 0 // 0 = deactivated, 1 = activated #define STEAMSWITCH_TYPE Switch::TOGGLE // Switch::TOGGLE or Switch::MOMENTARY (trigger) -#define OPTOCOUPLER_TYPE HIGH // BREWDETECTION 3 configuration; HIGH or LOW trigger optocoupler #define STEAMSWITCH_MODE Switch::NORMALLY_OPEN // Switch::NORMALLY_OPEN or Switch::NORMALLY_CLOSED #define HEATER_SSR_TYPE Relay::HIGH_TRIGGER // HIGH_TRIGGER = relay switches when input is HIGH, vice versa for LOW_TRIGGER #define PUMP_VALVE_SSR_TYPE Relay::HIGH_TRIGGER // HIGH_TRIGGER = relay switches when input is HIGH, vice versa for LOW_TRIGGER From c4c7329fa102f9ca1d91800f34b83bbda5dc18d8 Mon Sep 17 00:00:00 2001 From: Lorenz Uhlig <98092139+LoQue90@users.noreply.github.com> Date: Mon, 16 Sep 2024 13:18:37 +0200 Subject: [PATCH 10/23] move brewOn from brewswitch to brew() --- src/brewHandler.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/brewHandler.h b/src/brewHandler.h index dcadd7a4f..74d66727f 100644 --- a/src/brewHandler.h +++ b/src/brewHandler.h @@ -100,7 +100,6 @@ void checkbrewswitch() { case kBrewSwitchBrew: // Brew switch short pressed - start brew if (currBrewSwitchStateMomentary == LOW && currStateBrewSwitch == LOW) { currStateBrewSwitch = HIGH; - brewOn = 1; brewSwitchState = kBrewSwitchActive; LOG(DEBUG, "brewSwitchState = kBrewSwitchBrew; brew switch short pressed - start Brew"); } @@ -116,13 +115,11 @@ void checkbrewswitch() { case kBrewSwitchActive: if (currBrewSwitchStateMomentary == HIGH && currStateBrewSwitch == HIGH) { // Brew switch got short pressed while brew is running - abort brew currStateBrewSwitch = LOW; - brewOn = 0; brewSwitchState = kBrewSwitchWaitForRelease; LOG(DEBUG, "brewSwitchState = kBrewSwitchActive: brew switch short pressed - stop brew"); } else if ((machineState == kShotTimerAfterBrew) || (backflushState == kBackflushWaitBrewswitchOff)) { // Brew reached target and stopped or blackflush cycle done currStateBrewSwitch = LOW; - brewOn = 0; brewSwitchState = kBrewSwitchWaitForRelease; LOG(DEBUG, "brewSwitchState = kBrewSwitchActive: brew reached target or backflush done - reset brew switch"); } @@ -275,6 +272,7 @@ void brew() { if (currStateBrewSwitch == LOW && currBrewState > kBrewIdle) { // abort function for state machine from every state LOG(INFO, "Brew stopped manually"); + brewOn = 0; currBrewState = kWaitBrewOff; } @@ -302,9 +300,11 @@ void brew() { startingTime = millis(); if (preinfusionPause == 0 || preinfusion == 0) { + brewOn = 1; currBrewState = kBrewRunning; } else { + brewOn = 1; currBrewState = kPreinfusion; } } @@ -369,6 +369,7 @@ void brew() { break; case kBrewFinished: // brew finished + brewOn = 0; LOG(INFO, "Brew stopped"); valveRelay.off(); pumpRelay.off(); From fd91f6e60d88965efa48e705598f5b080e255740 Mon Sep 17 00:00:00 2001 From: Lorenz Uhlig <98092139+LoQue90@users.noreply.github.com> Date: Mon, 16 Sep 2024 15:02:13 +0200 Subject: [PATCH 11/23] remove mashine state kShotTimerAfterBrew SHOTTIMERDISPLAYDELAY is now broken, needs to be reworked --- src/brewHandler.h | 2 +- src/display/displayCommon.h | 2 +- src/display/displayTemplateStandard.h | 2 +- src/main.cpp | 51 ++------------------------- 4 files changed, 5 insertions(+), 52 deletions(-) diff --git a/src/brewHandler.h b/src/brewHandler.h index 74d66727f..7a0291921 100644 --- a/src/brewHandler.h +++ b/src/brewHandler.h @@ -118,7 +118,7 @@ void checkbrewswitch() { brewSwitchState = kBrewSwitchWaitForRelease; LOG(DEBUG, "brewSwitchState = kBrewSwitchActive: brew switch short pressed - stop brew"); } - else if ((machineState == kShotTimerAfterBrew) || (backflushState == kBackflushWaitBrewswitchOff)) { // Brew reached target and stopped or blackflush cycle done + 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"); diff --git a/src/display/displayCommon.h b/src/display/displayCommon.h index 7acd901df..7beb141e4 100644 --- a/src/display/displayCommon.h +++ b/src/display/displayCommon.h @@ -273,7 +273,7 @@ bool displayShottimer() { * nothing should be done, otherwise wrong time is displayed * because the switch is pressed later than totalBrewTime */ - else if (machineState == kShotTimerAfterBrew && brewSwitchState != kBrewSwitchFlush) { + else if (brewSwitchState != kBrewSwitchFlush) { //TODO: Show shottimer after brew finished fpr SHOTTIMERDISPLAYDELAY u8g2.clearBuffer(); u8g2.drawXBMP(-1, 11, Brew_Cup_Logo_width, Brew_Cup_Logo_height, Brew_Cup_Logo); diff --git a/src/display/displayTemplateStandard.h b/src/display/displayTemplateStandard.h index a408edc69..27c65f1b9 100644 --- a/src/display/displayTemplateStandard.h +++ b/src/display/displayTemplateStandard.h @@ -63,7 +63,7 @@ void printScreen() { u8g2.setCursor(35, 36); // Shot timer shown if machine is brewing and after the brew - if (machineState == kBrew || machineState == kShotTimerAfterBrew) { + if (machineState == kBrew) { u8g2.print(langstring_brew); u8g2.setCursor(84, 36); u8g2.print(timeBrewed / 1000, 0); diff --git a/src/main.cpp b/src/main.cpp index 0799ba23f..fadcce03e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -81,8 +81,6 @@ enum MachineState { kInit = 0, kPidNormal = 20, kBrew = 30, - kShotTimerAfterBrew = 31, - kBrewDetectionTrailing = 35, kSteam = 40, kBackflush = 50, kWaterEmpty = 70, @@ -604,51 +602,14 @@ void handleMachineState() { case kBrew: - if (currBrewState == kBrewIdle || currBrewState == kWaitBrewOff) { - // delay shot timer display after brewSwitch got released - machineState = kShotTimerAfterBrew; - lastBrewTimeMillis = millis(); // for delay - } - - if (steamON == 1) { - machineState = kSteam; - } - - if (emergencyStop) { - machineState = kEmergencyStop; - } - - if (pidON == 0) { - machineState = kPidDisabled; - } - - if (tempSensor->hasError()) { - machineState = kSensorError; - } - break; - - case kShotTimerAfterBrew: - - if (millis() - lastBrewTimeMillis > SHOTTIMERDISPLAYDELAY) { + if (brewOn == 0) { machineState = kPidNormal; } - if (brewOn == 1) { - machineState = kBrew; - - if (standbyModeOn) { - resetStandbyTimer(); - } - } - if (steamON == 1) { machineState = kSteam; } - if (backflushOn || backflushState > kBackflushWaitBrewswitchOn) { - machineState = kBackflush; - } - if (emergencyStop) { machineState = kEmergencyStop; } @@ -657,10 +618,6 @@ void handleMachineState() { machineState = kPidDisabled; } - if (!waterFull) { - machineState = kWaterEmpty; - } - if (tempSensor->hasError()) { machineState = kSensorError; } @@ -815,10 +772,6 @@ char const* machinestateEnumToString(MachineState machineState) { return "PID Normal"; case kBrew: return "Brew"; - case kShotTimerAfterBrew: - return "Shot Timer After Brew"; - case kBrewDetectionTrailing: - return "Brew Detection Trailing"; case kSteam: return "Steam"; case kBackflush: @@ -1667,7 +1620,7 @@ void looppid() { } // BD PID - if (machineState >= kBrew && machineState <= kBrewDetectionTrailing) { + if (machineState == kBrew) { if (brewPIDDelay > 0 && timeBrewed > 0 && timeBrewed < brewPIDDelay * 1000) { // disable PID for brewPIDDelay seconds, enable PID again with new tunings after that if (!brewPIDDisabled) { From 0cb44f1142ce4104e568805955033a6eddeaf958 Mon Sep 17 00:00:00 2001 From: Lorenz Uhlig <98092139+LoQue90@users.noreply.github.com> Date: Mon, 16 Sep 2024 19:28:01 +0200 Subject: [PATCH 12/23] rework displayed brewTime if brew is finished, by target or by hand, lastBrewTimeMillis is set from brewtimer() or brew() displayshottimer() uses lastBrewTimeMillis to show as long as SHOTTIMERDISPLAYDELAY is same is for standard, minimal template upright and rotate upright is still broken remove lastBrewTime store brew time always in timeBrewed and only reset timeBrewed on the a new brew brew time in all templates will only be shown when brew is running add timeBrewed to MQTT --- src/brewHandler.h | 26 ++-- src/display/displayCommon.h | 27 +--- src/display/displayTemplateMinimal.h | 32 ++-- src/display/displayTemplateStandard.h | 27 +++- src/display/displayTemplateUpright.h | 208 +++++++++++++------------- src/main.cpp | 4 +- 6 files changed, 162 insertions(+), 162 deletions(-) diff --git a/src/brewHandler.h b/src/brewHandler.h index 7a0291921..ec2322088 100644 --- a/src/brewHandler.h +++ b/src/brewHandler.h @@ -4,6 +4,16 @@ * @brief Handler for brewing * */ +// TODO: Clean up brew() +// move flush out of checkbrewswitch +// flush should trigger standby timer +// flush should stop standby +// move brewPIDDisabled to kBrew? +// add flush to display templates, SHOTTIMER 0 +// check all Scale stuff +// add shot time log info output +// check params website +// ... #pragma once @@ -49,8 +59,7 @@ boolean brewSwitchWasOff = false; int brewOn = 0; // flag is set if brew was detected double totalBrewTime = 0; // total brewtime set in software double timeBrewed = 0; // total brewed time -double lastBrewTimeMillis = 0; // for shottimer delay after disarmed button -double lastBrewTime = 0; +double lastBrewTimeMillis = 0; // for shottimer delay after brew is finished unsigned long startingTime = 0; // start time of brew boolean brewPIDDisabled = false; // is PID disabled for delay after brew has started? @@ -240,6 +249,7 @@ void brewTimer() { if (currStateBrewSwitch == HIGH && currBrewState == kBrewIdle) { brewOn = 1; startingTime = currentMillisTemp; + timeBrewed = 0; // reset timeBrewed, last brew is still stored currBrewState = kBrewRunning; LOG(INFO, "Brew timer started"); } @@ -253,10 +263,9 @@ void brewTimer() { if (currStateBrewSwitch == LOW && currBrewState == kBrewRunning) { LOG(INFO, "Brew timer stopped"); brewOn = 0; + lastBrewTimeMillis = millis(); // time brew finished for shottimer delay currBrewState = kBrewIdle; - lastBrewTime = timeBrewed; // store brewtime to show in Shottimer after brew is finished - timeBrewed = 0; - LOGF(INFO, "Shot time: %4.1f s", lastBrewTime / 1000); + LOGF(INFO, "Shot time: %4.1f s", timeBrewed / 1000); } } #endif @@ -298,6 +307,7 @@ void brew() { case kBrewIdle: // waiting step for brew switch turning on if (currStateBrewSwitch == HIGH && backflushState == 10 && backflushOn == 0 && brewSwitchWasOff && machineState != kWaterEmpty) { startingTime = millis(); + timeBrewed = 0; if (preinfusionPause == 0 || preinfusion == 0) { brewOn = 1; @@ -353,7 +363,6 @@ void brew() { break; case kWaitBrew: // waiting time or weight brew - lastBrewTime = timeBrewed; // stop brew if target-time is reached --> No stop if stop by time is deactivated via Parameter (0) if ((timeBrewed > totalBrewTime) && ((brewTime > 0))) { @@ -384,10 +393,9 @@ void brew() { // disarmed button currentMillisTemp = 0; + lastBrewTimeMillis = millis(); // time brew finished for shottimer delay currBrewState = kBrewIdle; - lastBrewTime = timeBrewed; // store brewtime to show in Shottimer after brew is finished - timeBrewed = 0; - LOGF(INFO, "Shot time: %4.1f s", lastBrewTime / 1000); + LOGF(INFO, "Shot time: %4.1f s", timeBrewed / 1000); } break; diff --git a/src/display/displayCommon.h b/src/display/displayCommon.h index 7beb141e4..a2529f4e1 100644 --- a/src/display/displayCommon.h +++ b/src/display/displayCommon.h @@ -241,7 +241,7 @@ bool displayShottimer() { return false; } - if (machineState == kBrew || brewSwitchState == kBrewSwitchFlush) { + if (machineState == kBrew || (millis() - lastBrewTimeMillis) < SHOTTIMERDISPLAYDELAY || brewSwitchState == kBrewSwitchFlush) { u8g2.clearBuffer(); if (brewSwitchState != kBrewSwitchFlush) { @@ -269,31 +269,6 @@ bool displayShottimer() { return true; } - /* if the totalBrewTime is reached automatically, - * nothing should be done, otherwise wrong time is displayed - * because the switch is pressed later than totalBrewTime - */ - else if (brewSwitchState != kBrewSwitchFlush) { //TODO: Show shottimer after brew finished fpr SHOTTIMERDISPLAYDELAY - u8g2.clearBuffer(); - u8g2.drawXBMP(-1, 11, Brew_Cup_Logo_width, Brew_Cup_Logo_height, Brew_Cup_Logo); - -#if (FEATURE_SCALE == 1) - u8g2.setFont(u8g2_font_profont22_tf); - u8g2.setCursor(64, 15); - u8g2.print(lastBrewTime / 1000, 1); - u8g2.print("s"); - u8g2.setCursor(64, 38); - u8g2.print(weightBrew, 1); - u8g2.print("g"); - u8g2.setFont(u8g2_font_profont11_tf); -#else - displayBrewtime(48, 25, lastBrewTime); -#endif - - displayWaterIcon(119, 1); - u8g2.sendBuffer(); - return true; - } return false; } diff --git a/src/display/displayTemplateMinimal.h b/src/display/displayTemplateMinimal.h index 7bcb235a9..78155c5c3 100644 --- a/src/display/displayTemplateMinimal.h +++ b/src/display/displayTemplateMinimal.h @@ -78,27 +78,31 @@ void printScreen() { u8g2.setFont(u8g2_font_profont11_tf); - if (isBrewDetected == 1 && currBrewState == kBrewIdle) { - u8g2.setCursor(38, 44); - u8g2.print("BD: "); - u8g2.print((millis() - timeBrewDetection) / 1000, 1); - u8g2.print("/"); - u8g2.print(brewtimesoftware, 0); - } - else { +// Brew time +#if (FEATURE_BREWSWITCH == 1 && FEATURE_BREWCONTROL == 1) + + // Shown brew time while machine is brewing and after the brewing during SHOTTIMERDISPLAYDELAY + if (machineState == kBrew || (millis() - lastBrewTimeMillis) < SHOTTIMERDISPLAYDELAY) { u8g2.setCursor(34, 44); u8g2.print(langstring_brew); u8g2.print(timeBrewed / 1000, 0); u8g2.print("/"); + u8g2.print(totalBrewTime / 1000, 0); + } - if (FEATURE_BREWCONTROL == 0) { - u8g2.print(brewtimesoftware, 0); - } - else { - u8g2.print(totalBrewTime / 1000, 0); - } +#endif + +#if (FEATURE_BREWSWITCH == 1 && FEATURE_BREWCONTROL == 0) + + // Show brew time; after brew finished show lastBrewTime during SHOTTIMERDISPLAYDELAY + if (machineState == kBrew || (millis() - lastBrewTimeMillis) < SHOTTIMERDISPLAYDELAY) { + u8g2.setCursor(34, 44); + u8g2.print(langstring_brew); + u8g2.print(timeBrewed / 1000, 0); } +#endif + // Show heater output in % displayProgressbar(pidOutput / 10, 15, 60, 100); diff --git a/src/display/displayTemplateStandard.h b/src/display/displayTemplateStandard.h index 27c65f1b9..fb54661d6 100644 --- a/src/display/displayTemplateStandard.h +++ b/src/display/displayTemplateStandard.h @@ -59,18 +59,35 @@ void printScreen() { drawTemperaturebar(8, 50, 30); } - // Brew time - u8g2.setCursor(35, 36); +// Brew time +#if (FEATURE_BREWSWITCH == 1 && FEATURE_BREWCONTROL == 1) - // Shot timer shown if machine is brewing and after the brew - if (machineState == kBrew) { + // Shown brew time while machine is brewing and after the brewing during SHOTTIMERDISPLAYDELAY + if (machineState == kBrew || (millis() - lastBrewTimeMillis) < SHOTTIMERDISPLAYDELAY) { + u8g2.setCursor(35, 36); u8g2.print(langstring_brew); u8g2.setCursor(84, 36); u8g2.print(timeBrewed / 1000, 0); u8g2.print("/"); - u8g2.print(totalBrewTime / 1000, 1); + u8g2.print(totalBrewTime / 1000, 0); + u8g2.print(" s"); } +#endif + +#if (FEATURE_BREWSWITCH == 1 && FEATURE_BREWCONTROL == 0) + + // Show brew time; after brew finished show lastBrewTime during SHOTTIMERDISPLAYDELAY + if (machineState == kBrew || (millis() - lastBrewTimeMillis) < SHOTTIMERDISPLAYDELAY) { + u8g2.setCursor(35, 36); + u8g2.print(langstring_brew); + u8g2.setCursor(84, 36); + u8g2.print(timeBrewed / 1000, 0); + u8g2.print(" s"); + } + +#endif + // PID values over heat bar u8g2.setCursor(38, 47); diff --git a/src/display/displayTemplateUpright.h b/src/display/displayTemplateUpright.h index f83eac83c..2542d380c 100644 --- a/src/display/displayTemplateUpright.h +++ b/src/display/displayTemplateUpright.h @@ -18,138 +18,132 @@ void printScreen() { } // If no specific machine state was printed, print default: - if (((machineState == kPidNormal || machineState == kBrewDetectionTrailing) || ((machineState == kBrew || machineState == kShotTimerAfterBrew) && FEATURE_SHOTTIMER == 0) || // shottimer == 0, auch Bezug anzeigen - (machineState == kPidNormal && (setpoint - temperature) > 5. && FEATURE_HEATINGLOGO == 0) || ((machineState == kPidDisabled) && FEATURE_PIDOFF_LOGO == 0)) && - (brewSwitchState != kBrewSwitchFlushOff)) { - if (!tempSensor->hasError()) { - u8g2.clearBuffer(); - u8g2.setCursor(1, 14); - u8g2.print(langstring_current_temp_rot_ur); - u8g2.print(temperature, 1); - u8g2.print(" "); - u8g2.print((char)176); - u8g2.print("C"); - u8g2.setCursor(1, 24); - u8g2.print(langstring_set_temp_rot_ur); - u8g2.print(setpoint, 1); - u8g2.print(" "); - u8g2.print((char)176); - u8g2.print("C"); - - // Draw heat bar - u8g2.drawLine(0, 124, 63, 124); - u8g2.drawLine(0, 124, 0, 127); - u8g2.drawLine(64, 124, 63, 127); - u8g2.drawLine(0, 127, 63, 127); - u8g2.drawLine(1, 125, (pidOutput / 16.13) + 1, 125); - u8g2.drawLine(1, 126, (pidOutput / 16.13) + 1, 126); - - // print heating status - u8g2.setCursor(1, 50); - u8g2.setFont(u8g2_font_profont22_tf); - - if (fabs(temperature - setpoint) < 0.3) { - if (isrCounter < 500) { - u8g2.print("OK"); - } - } - else { - u8g2.print("WAIT"); + if (!tempSensor->hasError()) { + u8g2.clearBuffer(); + u8g2.setCursor(1, 14); + u8g2.print(langstring_current_temp_rot_ur); + u8g2.print(temperature, 1); + u8g2.print(" "); + u8g2.print((char)176); + u8g2.print("C"); + u8g2.setCursor(1, 24); + u8g2.print(langstring_set_temp_rot_ur); + u8g2.print(setpoint, 1); + u8g2.print(" "); + u8g2.print((char)176); + u8g2.print("C"); + + // Draw heat bar + u8g2.drawLine(0, 124, 63, 124); + u8g2.drawLine(0, 124, 0, 127); + u8g2.drawLine(64, 124, 63, 127); + u8g2.drawLine(0, 127, 63, 127); + u8g2.drawLine(1, 125, (pidOutput / 16.13) + 1, 125); + u8g2.drawLine(1, 126, (pidOutput / 16.13) + 1, 126); + + // print heating status + u8g2.setCursor(1, 50); + u8g2.setFont(u8g2_font_profont22_tf); + + if (fabs(temperature - setpoint) < 0.3) { + if (isrCounter < 500) { + u8g2.print("OK"); } + } + else { + u8g2.print("WAIT"); + } - u8g2.setFont(u8g2_font_profont11_tf); - - if (isBrewDetected == 1) { - u8g2.setCursor(1, 75); - u8g2.print("BD "); - u8g2.print((millis() - timeBrewDetection) / 1000, 1); - u8g2.print("/"); - u8g2.print(brewtimesoftware, 0); - } + u8g2.setFont(u8g2_font_profont11_tf); - // PID values above heater output bar - u8g2.setCursor(1, 84); - u8g2.print("P: "); - u8g2.print(bPID.GetKp(), 0); + // PID values above heater output bar + u8g2.setCursor(1, 84); + u8g2.print("P: "); + u8g2.print(bPID.GetKp(), 0); - u8g2.setCursor(1, 93); - u8g2.print("I: "); + u8g2.setCursor(1, 93); + u8g2.print("I: "); - if (bPID.GetKi() != 0) { - u8g2.print(bPID.GetKp() / bPID.GetKi(), 0); - } - else { - u8g2.print("0"); - } + if (bPID.GetKi() != 0) { + u8g2.print(bPID.GetKp() / bPID.GetKi(), 0); + } + else { + u8g2.print("0"); + } - u8g2.setCursor(1, 102); - u8g2.print("D: "); - u8g2.print(bPID.GetKd() / bPID.GetKp(), 0); + u8g2.setCursor(1, 102); + u8g2.print("D: "); + u8g2.print(bPID.GetKd() / bPID.GetKp(), 0); - u8g2.setCursor(1, 111); + u8g2.setCursor(1, 111); - if (pidOutput < 99) { - u8g2.print(pidOutput / 10, 1); - } - else { - u8g2.print(pidOutput / 10, 0); - } + if (pidOutput < 99) { + u8g2.print(pidOutput / 10, 1); + } + else { + u8g2.print(pidOutput / 10, 0); + } - u8g2.print("%"); + u8g2.print("%"); - // Brew +// Brew time +#if (FEATURE_BREWSWITCH == 1 && FEATURE_BREWCONTROL == 1) + if (machineState == kBrew || (millis() - lastBrewTimeMillis) < SHOTTIMERDISPLAYDELAY) { u8g2.setCursor(1, 34); u8g2.print(langstring_brew_rot_ur); u8g2.print(timeBrewed / 1000, 0); u8g2.print("/"); - - if (FEATURE_BREWCONTROL == 0) { - u8g2.print(brewtimesoftware, 0); // deaktivieren wenn Preinfusion ( // voransetzen ) - } - else { - u8g2.print(totalBrewTime / 1000, 0); // aktivieren wenn Preinfusion - } - + u8g2.print(totalBrewTime / 1000, 0); u8g2.print(" s"); + } +#endif - // For status info - u8g2.drawFrame(0, 0, 64, 12); +#if (FEATURE_BREWSWITCH == 1 && FEATURE_BREWCONTROL == 0) + if (machineState == kBrew || (millis() - lastBrewTimeMillis) < SHOTTIMERDISPLAYDELAY) { + u8g2.setCursor(1, 34); + u8g2.print(langstring_brew_rot_ur); + u8g2.print(timeBrewed / 1000, 0); + u8g2.print(" s"); + } +#endif - if (offlineMode == 0) { - getSignalStrength(); + // For status info + u8g2.drawFrame(0, 0, 64, 12); - if (WiFi.status() == WL_CONNECTED) { - u8g2.drawXBMP(4, 2, 8, 8, Antenna_OK_Icon); + if (offlineMode == 0) { + getSignalStrength(); - for (int b = 0; b <= getSignalStrength(); b++) { - u8g2.drawVLine(13 + (b * 2), 10 - (b * 2), b * 2); - } - } - else { - u8g2.drawXBMP(4, 2, 8, 8, Antenna_NOK_Icon); - u8g2.setCursor(56, 2); - u8g2.print("RC: "); - u8g2.print(wifiReconnects); - } + if (WiFi.status() == WL_CONNECTED) { + u8g2.drawXBMP(4, 2, 8, 8, Antenna_OK_Icon); - if (FEATURE_MQTT == 1) { - if (mqtt.connected() == 1) { - u8g2.setCursor(24, 2); - u8g2.setFont(u8g2_font_profont11_tf); - u8g2.print("MQTT"); - } - else { - u8g2.setCursor(24, 2); - u8g2.print(""); - } + for (int b = 0; b <= getSignalStrength(); b++) { + u8g2.drawVLine(13 + (b * 2), 10 - (b * 2), b * 2); } } else { - u8g2.setCursor(4, 1); - u8g2.print("Offline"); + u8g2.drawXBMP(4, 2, 8, 8, Antenna_NOK_Icon); + u8g2.setCursor(56, 2); + u8g2.print("RC: "); + u8g2.print(wifiReconnects); } - u8g2.sendBuffer(); + if (FEATURE_MQTT == 1) { + if (mqtt.connected() == 1) { + u8g2.setCursor(24, 2); + u8g2.setFont(u8g2_font_profont11_tf); + u8g2.print("MQTT"); + } + else { + u8g2.setCursor(24, 2); + u8g2.print(""); + } + } } + else { + u8g2.setCursor(4, 1); + u8g2.print("Offline"); + } + + u8g2.sendBuffer(); } } diff --git a/src/main.cpp b/src/main.cpp index fadcce03e..3765f1ff5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1315,7 +1315,9 @@ void setup() { mqttSensors["currentKi"] = [] { return bPID.GetKi(); }; mqttSensors["currentKd"] = [] { return bPID.GetKd(); }; mqttSensors["machineState"] = [] { return machineState; }; - +#if FEATURE_BREWSWITCH == 1 + mqttSensors["timeBrewed"] = [] { return timeBrewed / 1000; }; +#endif #if FEATURE_PRESSURESENSOR == 1 mqttSensors["pressure"] = [] { return inputPressureFilter; }; #endif From cf326e05b3e5780c7bb43e343b5f3c6f2b1b0c77 Mon Sep 17 00:00:00 2001 From: Lorenz Uhlig <98092139+LoQue90@users.noreply.github.com> Date: Sat, 28 Sep 2024 17:02:08 +0200 Subject: [PATCH 13/23] include backflush if BREWCONTROL == 1 --- src/brewHandler.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/brewHandler.h b/src/brewHandler.h index ec2322088..beb5fc75c 100644 --- a/src/brewHandler.h +++ b/src/brewHandler.h @@ -401,4 +401,3 @@ void brew() { break; } } -#endif From 69b98de4bab14737d9d7e6d666dfed49f822ec9f 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 14/23] add manual flush as own function take manual flush out of checkbrewswitch manual flush with own mashineState kManualFlush manual flush reset standby time and ends standby remove any brew stuff out of checkbrewswitch() rename brewState and brewswitchstate add manualFlush to display templates and shottimer --- src/brewHandler.h | 281 ++++++++++++++++++-------- src/display/displayCommon.h | 12 +- src/display/displayTemplateMinimal.h | 15 +- src/display/displayTemplateStandard.h | 30 ++- src/display/displayTemplateUpright.h | 17 ++ src/languages.h | 21 +- src/main.cpp | 40 +++- 7 files changed, 305 insertions(+), 111 deletions(-) diff --git a/src/brewHandler.h b/src/brewHandler.h index beb5fc75c..e3c850b7a 100644 --- a/src/brewHandler.h +++ b/src/brewHandler.h @@ -4,16 +4,15 @@ * @brief Handler for brewing * */ -// TODO: Clean up brew() -// move flush out of checkbrewswitch -// flush should trigger standby timer -// flush should stop standby -// move brewPIDDisabled to kBrew? -// add flush to display templates, SHOTTIMER 0 +// TODO: +// clean up backflush +// Flush Timer configurable and seperated from shottimer? +// move brewPIDDisabled to kBrew? new fuction to set PID State based on mashine state switching? if kBrew -> disable PID/wait/BDPID or NORMALPID // check all Scale stuff -// add shot time log info output // check params website -// ... +// check MQTT/HASSIO for all brew stuff +// show heating logo if steam temp isn´t reached? +// how handle brew, backflush, manualflush, hotwater if mashine is in steam mode #pragma once @@ -21,9 +20,9 @@ enum BrewSwitchState { kBrewSwitchIdle = 10, - kBrewSwitchBrew = 20, - kBrewSwitchActive = 30, - kBrewSwitchFlush = 40, + kBrewSwitchPressed = 20, + kBrewSwitchShortPressed = 30, + kBrewSwitchLongPressed = 40, kBrewSwitchWaitForRelease = 50 }; @@ -36,7 +35,11 @@ enum BrewState { kBrewRunning = 40, kWaitBrew = 41, kBrewFinished = 42, - kWaitBrewOff = 43 +}; + +enum ManualFlushState { + kManualFlushIdle = 10, + kManualFlushRunning = 20, }; enum BackflushState { @@ -48,15 +51,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 +92,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; } @@ -246,31 +250,115 @@ void brewTimer() { checkbrewswitch(); // Start the timer when the brew switch is turned on - if (currStateBrewSwitch == HIGH && currBrewState == kBrewIdle) { + if (currBrewSwitchState == kBrewSwitchShortPressed && currBrewState == kBrewIdle) { brewOn = 1; startingTime = currentMillisTemp; timeBrewed = 0; // reset timeBrewed, last brew is still stored - currBrewState = kBrewRunning; LOG(INFO, "Brew timer started"); + currBrewState = kBrewRunning; } // Update the brewed time if the brew switch is still on - if (currStateBrewSwitch == HIGH && currBrewState == kBrewRunning) { + if (currBrewSwitchState == kBrewSwitchShortPressed && currBrewState == kBrewRunning) { timeBrewed = currentMillisTemp - startingTime; } // Stop the timer when the brew switch is turned off - if (currStateBrewSwitch == LOW && currBrewState == kBrewRunning) { - LOG(INFO, "Brew timer stopped"); + if (currBrewSwitchState == kBrewSwitchIdle && currBrewState == kBrewRunning) { brewOn = 0; lastBrewTimeMillis = millis(); // time brew finished for shottimer delay - currBrewState = kBrewIdle; + LOG(INFO, "Brew timer stopped"); LOGF(INFO, "Shot time: %4.1f s", timeBrewed / 1000); + currBrewState = kBrewIdle; } } #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 || backflushCycles <= 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 > (backflushFillTime * 1000)) { + startingTime = millis(); + backflushState = kBackflushFlushingStart; + } + + break; + + case kBackflushFlushingStart: + LOG(INFO, "Backflush: Flushing to drip tray..."); + valveRelay.off(); + pumpRelay.off(); + currBackflushCycles++; + backflushState = kBackflushFlushing; + + break; + + case kBackflushFlushing: + if (millis() - startingTime > (backflushFlushTime * 1000) && currBackflushCycles < backflushCycles) { + startingTime = millis(); + backflushState = kBackflushFillingStart; + } + else if (currBackflushCycles >= backflushCycles) { + backflushState = kBackflushWaitBrewswitchOff; + } + + break; + + case kBackflushWaitBrewswitchOff: + if (currBrewSwitchState == kBrewSwitchIdle) { + LOG(INFO, "Backflush: Finished!"); + valveRelay.off(); + pumpRelay.off(); + currBackflushCycles = 0; + backflushState = kBackflushWaitBrewswitchOn; + } + + break; + } +} + /** * @brief Time or weight based brew mode */ @@ -278,22 +366,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; + currBrewState = kBrewFinished; } - if (currBrewState > kBrewIdle && currBrewState < kWaitBrewOff || brewSwitchState == kBrewSwitchFlush) { - timeBrewed = currentMillisTemp - startingTime; - } - - if (currStateBrewSwitch == LOW) { + if (currBrewSwitchState == kBrewSwitchIdle) { // 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 } @@ -305,9 +392,10 @@ 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; + LOG(INFO, "Brew started"); if (preinfusionPause == 0 || preinfusion == 0) { brewOn = 1; @@ -325,9 +413,9 @@ void brew() { break; case kPreinfusion: // preinfusioon - LOG(INFO, "Preinfusion"); valveRelay.on(); pumpRelay.on(); + LOG(INFO, "Preinfusion"); currBrewState = kWaitPreinfusion; break; @@ -340,9 +428,9 @@ void brew() { break; case kPreinfusionPause: // preinfusion pause - LOG(INFO, "Preinfusion pause"); valveRelay.on(); pumpRelay.off(); + LOG(INFO, "Preinfusion pause"); currBrewState = kWaitPreinfusionPause; break; @@ -355,9 +443,9 @@ void brew() { break; case kBrewRunning: // brew running - LOG(INFO, "Brew started"); valveRelay.on(); pumpRelay.on(); + LOG(INFO, "Brew running"); currBrewState = kWaitBrew; break; @@ -366,11 +454,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 @@ -378,26 +468,53 @@ void brew() { break; case kBrewFinished: // brew finished - brewOn = 0; - LOG(INFO, "Brew stopped"); valveRelay.off(); pumpRelay.off(); - currBrewState = kWaitBrewOff; + brewOn = 0; + currentMillisTemp = 0; + lastBrewTimeMillis = millis(); // time brew finished for shottimer delay + brewSwitchWasOff = false; + LOG(INFO, "Brew finished"); + LOGF(INFO, "Shot time: %4.1f s", timeBrewed / 1000); + currBrewState = kBrewIdle; break; + } +} - case kWaitBrewOff: // waiting for brewswitch off position - if (currStateBrewSwitch == LOW) { - valveRelay.off(); - pumpRelay.off(); +/** + * @brief manual grouphead flush + */ +void manualFlush() { + unsigned long currentMillisTemp = millis(); + checkbrewswitch(); + if (currManualFlushState == kManualFlushRunning) { + timeBrewed = currentMillisTemp - startingTime; + } - // disarmed button - currentMillisTemp = 0; - lastBrewTimeMillis = millis(); // time brew finished for shottimer delay - currBrewState = kBrewIdle; - LOGF(INFO, "Shot time: %4.1f s", timeBrewed / 1000); + switch (currManualFlushState) { + case kManualFlushIdle: + if (currBrewSwitchState == kBrewSwitchLongPressed && machineState != kWaterEmpty) { + startingTime = millis(); + valveRelay.on(); + pumpRelay.on(); + manualFlushOn = 1; + LOG(INFO, "Manual flush started"); + currManualFlushState = kManualFlushRunning; } + break; + case kManualFlushRunning: + if (currBrewSwitchState != kBrewSwitchLongPressed) { + valveRelay.off(); + pumpRelay.off(); + manualFlushOn = 0; + LOG(INFO, "Manual flush stopped"); + LOGF(INFO, "Manual flush time: %4.1f s", timeBrewed / 1000); + currManualFlushState = kManualFlushIdle; + } break; } } + +#endif diff --git a/src/display/displayCommon.h b/src/display/displayCommon.h index a2529f4e1..0a3bf38c8 100644 --- a/src/display/displayCommon.h +++ b/src/display/displayCommon.h @@ -234,17 +234,17 @@ void displayLogo(String displaymessagetext, String displaymessagetext2) { } /** - * @brief display shot timer + * @brief display shot and flush timer */ bool displayShottimer() { if (FEATURE_SHOTTIMER == 0) { return false; } - if (machineState == kBrew || (millis() - lastBrewTimeMillis) < SHOTTIMERDISPLAYDELAY || brewSwitchState == kBrewSwitchFlush) { + if (machineState == kBrew || (millis() - lastBrewTimeMillis) < SHOTTIMERDISPLAYDELAY || machineState == kManualFlush) { u8g2.clearBuffer(); - if (brewSwitchState != kBrewSwitchFlush) { + if (machineState != kManualFlush) { 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.) { // For status info u8g2.clearBuffer(); @@ -314,7 +314,7 @@ bool displayMachineState() { return true; } // Steam - else if (machineState == kSteam && brewSwitchState != kBrewSwitchFlush) { + else if (machineState == kSteam) { 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) { 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/display/displayTemplateMinimal.h b/src/display/displayTemplateMinimal.h index 78155c5c3..297b0f1ed 100644 --- a/src/display/displayTemplateMinimal.h +++ b/src/display/displayTemplateMinimal.h @@ -90,11 +90,24 @@ void printScreen() { u8g2.print(totalBrewTime / 1000, 0); } + // Flush time + + // Shown flush time while machine is flushing + if (machineState == kManualFlush) { + u8g2.setDrawColor(0); + u8g2.drawBox(34, 44, 100, 15); + u8g2.setDrawColor(1); + u8g2.setCursor(34, 44); + u8g2.print(langstring_manual_flush); + u8g2.print(timeBrewed / 1000, 0); + } + #endif +// Brew Timer with optocoupler #if (FEATURE_BREWSWITCH == 1 && FEATURE_BREWCONTROL == 0) - // Show brew time; after brew finished show lastBrewTime during SHOTTIMERDISPLAYDELAY + // Shown brew time while machine is brewing and after the brewing during SHOTTIMERDISPLAYDELAY if (machineState == kBrew || (millis() - lastBrewTimeMillis) < SHOTTIMERDISPLAYDELAY) { u8g2.setCursor(34, 44); u8g2.print(langstring_brew); diff --git a/src/display/displayTemplateStandard.h b/src/display/displayTemplateStandard.h index fb54661d6..aea5e6845 100644 --- a/src/display/displayTemplateStandard.h +++ b/src/display/displayTemplateStandard.h @@ -32,18 +32,18 @@ void printScreen() { displayStatusbar(); - u8g2.setCursor(35, 16); + u8g2.setCursor(34, 16); u8g2.print(langstring_current_temp); u8g2.setCursor(84, 16); u8g2.print(temperature, 1); - u8g2.setCursor(114, 16); + u8g2.setCursor(115, 16); u8g2.print((char)176); u8g2.print("C"); - u8g2.setCursor(35, 26); + u8g2.setCursor(34, 26); u8g2.print(langstring_set_temp); u8g2.setCursor(84, 26); u8g2.print(setpoint, 1); - u8g2.setCursor(114, 26); + u8g2.setCursor(115, 26); u8g2.print((char)176); u8g2.print("C"); @@ -64,7 +64,8 @@ void printScreen() { // Shown brew time while machine is brewing and after the brewing during SHOTTIMERDISPLAYDELAY if (machineState == kBrew || (millis() - lastBrewTimeMillis) < SHOTTIMERDISPLAYDELAY) { - u8g2.setCursor(35, 36); + u8g2.setFontMode(1); + u8g2.setCursor(34, 36); u8g2.print(langstring_brew); u8g2.setCursor(84, 36); u8g2.print(timeBrewed / 1000, 0); @@ -73,13 +74,28 @@ void printScreen() { u8g2.print(" s"); } + // Flush time + + // Shown flush time while machine is flushing + if (machineState == kManualFlush) { + u8g2.setDrawColor(0); + u8g2.drawBox(34, 36, 100, 10); + u8g2.setDrawColor(1); + u8g2.setCursor(34, 36); + u8g2.print(langstring_manual_flush); + u8g2.setCursor(84, 36); + u8g2.print(timeBrewed / 1000, 0); + u8g2.print(" s"); + } + #endif +// Brew Timer with optocoupler #if (FEATURE_BREWSWITCH == 1 && FEATURE_BREWCONTROL == 0) - // Show brew time; after brew finished show lastBrewTime during SHOTTIMERDISPLAYDELAY + // Shown brew time while machine is brewing and after the brewing during SHOTTIMERDISPLAYDELAY if (machineState == kBrew || (millis() - lastBrewTimeMillis) < SHOTTIMERDISPLAYDELAY) { - u8g2.setCursor(35, 36); + u8g2.setCursor(34, 36); u8g2.print(langstring_brew); u8g2.setCursor(84, 36); u8g2.print(timeBrewed / 1000, 0); diff --git a/src/display/displayTemplateUpright.h b/src/display/displayTemplateUpright.h index 2542d380c..303ebcda7 100644 --- a/src/display/displayTemplateUpright.h +++ b/src/display/displayTemplateUpright.h @@ -88,6 +88,7 @@ void printScreen() { // Brew time #if (FEATURE_BREWSWITCH == 1 && FEATURE_BREWCONTROL == 1) + // Show brew time; after brew finished show lastBrewTime during SHOTTIMERDISPLAYDELAY if (machineState == kBrew || (millis() - lastBrewTimeMillis) < SHOTTIMERDISPLAYDELAY) { u8g2.setCursor(1, 34); u8g2.print(langstring_brew_rot_ur); @@ -96,9 +97,25 @@ void printScreen() { u8g2.print(totalBrewTime / 1000, 0); u8g2.print(" s"); } + + // Flush time + + // Shown flush time while machine is flushing + if (machineState == kManualFlush) { + u8g2.setDrawColor(0); + u8g2.drawBox(1, 34, 100, 15); + u8g2.setDrawColor(1); + u8g2.setCursor(1, 34); + u8g2.print(langstring_manual_flush_rot_ur); + u8g2.print(timeBrewed / 1000, 0); + u8g2.print(" s"); + } + #endif +// Brew Timer with optocoupler #if (FEATURE_BREWSWITCH == 1 && FEATURE_BREWCONTROL == 0) + // Shown brew time while machine is brewing and after the brewing during SHOTTIMERDISPLAYDELAY if (machineState == kBrew || (millis() - lastBrewTimeMillis) < SHOTTIMERDISPLAYDELAY) { u8g2.setCursor(1, 34); u8g2.print(langstring_brew_rot_ur); diff --git a/src/languages.h b/src/languages.h index 439c3cdf7..9bde884b6 100644 --- a/src/languages.h +++ b/src/languages.h @@ -12,24 +12,21 @@ #if (DISPLAYTEMPLATE <= 4) static const char* langstring_set_temp = "Soll: "; static const char* langstring_current_temp = "Ist: "; -static const char* langstring_brew = "Brew: "; +static const char* langstring_brew = "Bezug: "; +static const char* langstring_manual_flush = "Spuelen: "; static const char* langstring_uptime = "Uptime: "; #endif #if (DISPLAYTEMPLATE >= 20) // vertical templates static const char* langstring_set_temp_rot_ur = "S: "; static const char* langstring_current_temp_rot_ur = "I: "; static const char* langstring_brew_rot_ur = "B: "; +static const char* langstring_manual_flush_rot_ur = "S: "; #endif static const char* langstring_offlinemode = "Offline"; -#if TOF == 1 -static const char* langstring_waterempty = "Wasser leer"; -#endif - static const char* langstring_wifirecon = "Wifi reconnect:"; static const char* langstring_connectwifi1 = "1: Verbinde WLAN:"; static const char* langstring_nowifi[] = {"Kein ", "WLAN"}; - static const char* langstring_error_tsensor[] = {"Fehler, Temp: ", "Temp.-Sensor ueberpruefen!"}; // static const char *langstring_emergencyStop[] = {"HEATING", "STOPPED"}; @@ -42,19 +39,17 @@ static const char* langstring_backflush_finish = "um zu beenden..."; static const char* langstring_set_temp = "Set: "; static const char* langstring_current_temp = "Temp: "; static const char* langstring_brew = "Brew: "; +static const char* langstring_manual_flush = "Flush: "; static const char* langstring_uptime = "Uptime: "; #endif #if (DISPLAYTEMPLATE >= 20) // vertical templates static const char* langstring_set_temp_rot_ur = "S: "; static const char* langstring_current_temp_rot_ur = "T: "; static const char* langstring_brew_rot_ur = "B: "; +static const char* langstring_manual_flush_rot_ur = "F: "; #endif static const char* langstring_offlinemode = "Offline"; -#if TOF == 1 -static const char* langstring_waterempty = "Empty water"; -#endif - static const char* langstring_wifirecon = "Wifi reconnect:"; static const char* langstring_connectwifi1 = "1: Connecting Wifi:"; static const char* langstring_nowifi[] = {"No ", "WIFI"}; @@ -71,19 +66,17 @@ static const char* langstring_backflush_finish = "to finish..."; static const char* langstring_set_temp = "Obj: "; static const char* langstring_current_temp = "T: "; static const char* langstring_brew = "Brew: "; +static const char* langstring_manual_flush = "Fregar: "; static const char* langstring_uptime = "Uptime: "; #endif #if (DISPLAYTEMPLATE >= 20) // vertical templates static const char* langstring_set_temp_rot_ur = "O: "; static const char* langstring_current_temp_rot_ur = "T: "; static const char* langstring_brew_rot_ur = "B: "; +static const char* langstring_manual_flush_rot_ur = "F: "; #endif static const char* langstring_offlinemode = "Offline"; -#if TOF == 1 -static const char* langstring_waterempty = "Agua vacía"; -#endif - static const char* langstring_wifirecon = "Reconecta wifi:"; static const char* langstring_connectwifi1 = "1: Wifi conectado :"; static const char* langstring_nowifi[] = {"No ", "WIFI"}; diff --git a/src/main.cpp b/src/main.cpp index 3765f1ff5..1a8cd4803 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -81,6 +81,7 @@ enum MachineState { kInit = 0, kPidNormal = 20, kBrew = 30, + kManualFlush = 35, kSteam = 40, kBackflush = 50, kWaterEmpty = 70, @@ -561,6 +562,14 @@ void handleMachineState() { } } + if (manualFlushOn == 1) { + machineState = kManualFlush; + + if (standbyModeOn) { + resetStandbyTimer(); + } + } + if (steamON == 1) { machineState = kSteam; @@ -623,6 +632,29 @@ void handleMachineState() { } break; + case kManualFlush: + + if (manualFlushOn == 0) { + machineState = kPidNormal; + } + + if (steamON == 1) { + machineState = kSteam; + } + + if (emergencyStop) { + machineState = kEmergencyStop; + } + + if (pidON == 0) { + machineState = kPidDisabled; + } + + if (tempSensor->hasError()) { + machineState = kSensorError; + } + break; + case kSteam: if (steamON == 0) { machineState = kPidNormal; @@ -722,7 +754,7 @@ void handleMachineState() { #endif } - if (pidON || steamON || brewOn) { + if (pidON || steamON || brewOn || manualFlushOn) { pidON = 1; resetStandbyTimer(); #if OLED_DISPLAY != 0 @@ -735,6 +767,9 @@ void handleMachineState() { else if (brewOn) { machineState = kBrew; } + else if (manualFlushOn) { + machineState = kManualFlush; + } else { machineState = kPidNormal; } @@ -772,6 +807,8 @@ char const* machinestateEnumToString(MachineState machineState) { return "PID Normal"; case kBrew: return "Brew"; + case kManualFlush: + return "Manual Flush"; case kSteam: return "Steam"; case kBackflush: @@ -1553,6 +1590,7 @@ void looppid() { #if (FEATURE_BREWSWITCH == 1 && FEATURE_BREWCONTROL == 1) brew(); + manualFlush(); #endif #if (FEATURE_PRESSURESENSOR == 1) From 0e7bb9868cce8df79e5242dd0856be1f6c0f4e14 Mon Sep 17 00:00:00 2001 From: Lorenz Uhlig <98092139+LoQue90@users.noreply.github.com> Date: Fri, 11 Oct 2024 13:41:02 +0200 Subject: [PATCH 15/23] fixes after rebase --- src/brewHandler.h | 84 ----------------------------------------------- src/defaults.h | 79 +++++++++++++++++++++----------------------- src/main.cpp | 8 ++--- 3 files changed, 42 insertions(+), 129 deletions(-) diff --git a/src/brewHandler.h b/src/brewHandler.h index e3c850b7a..675f2ec76 100644 --- a/src/brewHandler.h +++ b/src/brewHandler.h @@ -157,90 +157,6 @@ void checkbrewswitch() { } } -/** - * @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 || backflushCycles <= 0 || backflushOn == 0) { - return; - } - - if (bPID.GetMode() == 1) { // Deactivate PID - bPID.SetMode(0); - pidOutput = 0; - } - - heaterRelay.off(); // Stop heating - - checkbrewswitch(); - - if (currStateBrewSwitch == LOW && backflushState != kBackflushWaitBrewswitchOn) { // Abort function for state machine from every state - backflushState = kBackflushWaitBrewswitchOff; - } - - // 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 > (backflushFillTime * 1000)) { - startingTime = millis(); - backflushState = kBackflushFlushingStart; - } - - break; - - case kBackflushFlushingStart: - LOG(INFO, "Backflush: Flushing to drip tray..."); - valveRelay.off(); - pumpRelay.off(); - currBackflushCycles++; - backflushState = kBackflushFlushing; - - break; - - case kBackflushFlushing: - if (millis() - startingTime > (backflushFlushTime * 1000) && currBackflushCycles < backflushCycles) { - startingTime = millis(); - backflushState = kBackflushFillingStart; - } - else if (currBackflushCycles >= backflushCycles) { - backflushState = kBackflushWaitBrewswitchOff; - } - - break; - - case kBackflushWaitBrewswitchOff: - if (currStateBrewSwitch == LOW) { - LOG(INFO, "Backflush: Finished!"); - valveRelay.off(); - pumpRelay.off(); - currBackflushCycles = 0; - backflushState = kBackflushWaitBrewswitchOn; - } - - break; - } -} - #if (FEATURE_BREWCONTROL == 0) /** * @brief Brew timer diff --git a/src/defaults.h b/src/defaults.h index 973b6da3e..8e1a4e3a3 100644 --- a/src/defaults.h +++ b/src/defaults.h @@ -48,50 +48,47 @@ int writeSysParamsToStorage(void); #define BACKFLUSH_FILL_TIME 5 // time in seconds the pump is running during backflush #define BACKFLUSH_FLUSH_TIME 10 // time in seconds the 3-way valve is open during backflush -#define PID_KP_START_MIN 0 -#define PID_KP_START_MAX 999 -#define PID_TN_START_MIN 0 -#define PID_TN_START_MAX 999 -#define PID_KP_REGULAR_MIN 0 -#define PID_KP_REGULAR_MAX 999 -#define PID_TN_REGULAR_MIN 0 -#define PID_TN_REGULAR_MAX 999 -#define PID_TV_REGULAR_MIN 0 -#define PID_TV_REGULAR_MAX 999 -#define PID_I_MAX_REGULAR_MIN 0 -#define PID_I_MAX_REGULAR_MAX 999 -#define PID_KP_BD_MIN 0 -#define PID_KP_BD_MAX 999 -#define PID_TN_BD_MIN 0 -#define PID_TN_BD_MAX 999 -#define PID_TV_BD_MIN 0 -#define PID_TV_BD_MAX 999 -#define BREW_SETPOINT_MIN 20 -#define BREW_SETPOINT_MAX 110 -#define STEAM_SETPOINT_MIN 100 -#define STEAM_SETPOINT_MAX 140 -#define BREW_TEMP_OFFSET_MIN 0 -#define BREW_TEMP_OFFSET_MAX 20 -#define BREW_TEMP_TIME_MIN 1 -#define BREW_TEMP_TIME_MAX 180 -#define BREW_TIME_MIN 0 -#define BREW_TIME_MAX 180 -#define BREW_PID_DELAY_MIN 0 -#define BREW_PID_DELAY_MAX 60 -#define PRE_INFUSION_TIME_MIN 0 -#define PRE_INFUSION_TIME_MAX 60 -#define PRE_INFUSION_PAUSE_MIN 0 -#define PRE_INFUSION_PAUSE_MAX 60 -#define WEIGHTSETPOINT_MIN 0 -#define WEIGHTSETPOINT_MAX 500 -#define PID_KP_STEAM_MIN 0 -#define PID_KP_STEAM_MAX 500 -#define STANDBY_MODE_TIME_MIN 30 -#define STANDBY_MODE_TIME_MAX 120 +#define PID_KP_START_MIN 0 +#define PID_KP_START_MAX 999 +#define PID_TN_START_MIN 0 +#define PID_TN_START_MAX 999 +#define PID_KP_REGULAR_MIN 0 +#define PID_KP_REGULAR_MAX 999 +#define PID_TN_REGULAR_MIN 0 +#define PID_TN_REGULAR_MAX 999 +#define PID_TV_REGULAR_MIN 0 +#define PID_TV_REGULAR_MAX 999 +#define PID_I_MAX_REGULAR_MIN 0 +#define PID_I_MAX_REGULAR_MAX 999 +#define PID_KP_BD_MIN 0 +#define PID_KP_BD_MAX 999 +#define PID_TN_BD_MIN 0 +#define PID_TN_BD_MAX 999 +#define PID_TV_BD_MIN 0 +#define PID_TV_BD_MAX 999 +#define BREW_SETPOINT_MIN 20 +#define BREW_SETPOINT_MAX 110 +#define STEAM_SETPOINT_MIN 100 +#define STEAM_SETPOINT_MAX 140 +#define BREW_TEMP_OFFSET_MIN 0 +#define BREW_TEMP_OFFSET_MAX 20 +#define BREW_TIME_MIN 0 +#define BREW_TIME_MAX 180 +#define BREW_PID_DELAY_MIN 0 +#define BREW_PID_DELAY_MAX 60 +#define PRE_INFUSION_TIME_MIN 0 +#define PRE_INFUSION_TIME_MAX 60 +#define PRE_INFUSION_PAUSE_MIN 0 +#define PRE_INFUSION_PAUSE_MAX 60 +#define WEIGHTSETPOINT_MIN 0 +#define WEIGHTSETPOINT_MAX 500 +#define PID_KP_STEAM_MIN 0 +#define PID_KP_STEAM_MAX 500 +#define STANDBY_MODE_TIME_MIN 30 +#define STANDBY_MODE_TIME_MAX 120 #define BACKFLUSH_CYCLES_MIN 2 #define BACKFLUSH_CYCLES_MAX 20 #define BACKFLUSH_FILL_TIME_MIN 5 #define BACKFLUSH_FILL_TIME_MAX 20 #define BACKFLUSH_FLUSH_TIME_MIN 5 #define BACKFLUSH_FLUSH_TIME_MAX 20 - diff --git a/src/main.cpp b/src/main.cpp index 1a8cd4803..c8cfaa672 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1167,7 +1167,7 @@ void setup() { .type = kUInt8, .section = sBDSection, .position = 22, - .show = [] { return true && FEATURE_BREWDETECTION == 1; }, + .show = [] { return true && FEATURE_BREWSWITCH == 1; }, .minValue = 0, .maxValue = 1, .ptr = (void*)&useBDPID}; @@ -1185,7 +1185,7 @@ void setup() { .type = kDouble, .section = sBDSection, .position = 23, - .show = [] { return true && FEATURE_BREWDETECTION == 1 && useBDPID; }, + .show = [] { return true && FEATURE_BREWSWITCH == 1 && useBDPID; }, .minValue = PID_KP_BD_MIN, .maxValue = PID_KP_BD_MAX, .ptr = (void*)&aggbKp}; @@ -1197,7 +1197,7 @@ void setup() { .type = kDouble, .section = sBDSection, .position = 24, - .show = [] { return true && FEATURE_BREWDETECTION == 1 && useBDPID; }, + .show = [] { return true && FEATURE_BREWSWITCH == 1 && useBDPID; }, .minValue = PID_TN_BD_MIN, .maxValue = PID_TN_BD_MAX, .ptr = (void*)&aggbTn}; @@ -1209,7 +1209,7 @@ void setup() { .type = kDouble, .section = sBDSection, .position = 25, - .show = [] { return true && FEATURE_BREWDETECTION == 1 && useBDPID; }, + .show = [] { return true && FEATURE_BREWSWITCH == 1 && useBDPID; }, .minValue = PID_TV_BD_MIN, .maxValue = PID_TV_BD_MAX, .ptr = (void*)&aggbTv}; From 4687343960a605925bb67e77736d893b98142fcf Mon Sep 17 00:00:00 2001 From: Lorenz Uhlig <98092139+LoQue90@users.noreply.github.com> Date: Fri, 11 Oct 2024 17:59:07 +0200 Subject: [PATCH 16/23] rework brew() and backflush() clean up and less states for brew() and backflush() removed brewOn and used bool brew() removed manualFlushOn and used bool manualFlush() move all backflush related stuff into brewHandler fix includes for brewHandler.h backflush() is now only called if mashineState is kBackflush if mashine is in kBackflush brewswitch controls backflush and it is not possible to start a brew removed boolean, use bool moved PID and Heater disable into mashine state kBachflush --- src/brewHandler.h | 352 +++++++++++++++++------------------- src/display/displayCommon.h | 8 +- src/main.cpp | 174 +++++++++--------- 3 files changed, 267 insertions(+), 267 deletions(-) diff --git a/src/brewHandler.h b/src/brewHandler.h index 675f2ec76..3b1109c66 100644 --- a/src/brewHandler.h +++ b/src/brewHandler.h @@ -5,7 +5,7 @@ * */ // TODO: -// clean up backflush +// FEATURE_BREWCONTROL has to be removed from userconfig, setup on website // Flush Timer configurable and seperated from shottimer? // move brewPIDDisabled to kBrew? new fuction to set PID State based on mashine state switching? if kBrew -> disable PID/wait/BDPID or NORMALPID // check all Scale stuff @@ -29,12 +29,9 @@ enum BrewSwitchState { enum BrewState { kBrewIdle = 10, kPreinfusion = 20, - kWaitPreinfusion = 21, kPreinfusionPause = 30, - kWaitPreinfusionPause = 31, kBrewRunning = 40, - kWaitBrew = 41, - kBrewFinished = 42, + kBrewFinished = 50, }; enum ManualFlushState { @@ -43,30 +40,38 @@ enum ManualFlushState { }; enum BackflushState { - kBackflushWaitBrewswitchOn = 10, - kBackflushFillingStart = 20, - kBackflushFilling = 21, - kBackflushFlushingStart = 30, - kBackflushFlushing = 31, - kBackflushWaitBrewswitchOff = 43 + kBackflushIdle = 10, + kBackflushFilling = 20, + kBackflushFlushing = 30, + kBackflushFinished = 40 }; // Brew control states BrewSwitchState currBrewSwitchState = kBrewSwitchIdle; BrewState currBrewState = kBrewIdle; ManualFlushState currManualFlushState = kManualFlushIdle; +BackflushState currBackflushState = kBackflushIdle; 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 -unsigned long startingTime = 0; // start time of brew -boolean brewPIDDisabled = false; // is PID disabled for delay after brew has started? +bool brewSwitchWasOff = false; + +// Brew values +double brewTime = BREW_TIME; // brewtime in s +double preinfusion = PRE_INFUSION_TIME; // preinfusion time in s +double preinfusionPause = PRE_INFUSION_PAUSE_TIME; // preinfusion pause time in s +double totalBrewTime = 0; // total brewtime including preinfusion and preinfusion pause +double timeBrewed = 0; // total brewed time +double lastBrewTimeMillis = 0; // for shottimer delay after brew is finished +unsigned long startingTime = 0; // start time of brew +bool brewPIDDisabled = false; // is PID disabled for delay after brew has started? + +// Backflush values +int backflushCycles = BACKFLUSH_CYCLES; +double backflushFillTime = BACKFLUSH_FILL_TIME; +double backflushFlushTime = BACKFLUSH_FLUSH_TIME; +int backflushOn = 0; +int currBackflushCycles = 1; // Shot timer with or without scale #if FEATURE_SCALE == 1 @@ -132,9 +137,9 @@ void checkbrewswitch() { 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"); + LOG(DEBUG, "Brew switch short press detected -> got to currBrewSwitchState = kBrewSwitchWaitForRelease; brew or backflush stopped manually"); } - else if ((currBrewState == kBrewFinished) || (backflushState == kBackflushWaitBrewswitchOff)) { // Brew reached target and stopped or blackflush cycle done + else if ((currBrewState == kBrewFinished) || (currBackflushState == kBackflushFinished)) { // Brew reached target and stopped or blackflush cycle done currBrewSwitchState = kBrewSwitchWaitForRelease; LOG(DEBUG, "Brew reached target or backflush done -> got to currBrewSwitchState = kBrewSwitchWaitForRelease"); } @@ -157,148 +162,36 @@ void checkbrewswitch() { } } -#if (FEATURE_BREWCONTROL == 0) /** - * @brief Brew timer + * @brief Brew process handeling including timer and state machine for brew-by-time and brew-by-weight + * @return true if brew is running, false otherwise */ -void brewTimer() { +bool brew() { unsigned long currentMillisTemp = millis(); checkbrewswitch(); - // Start the timer when the brew switch is turned on - if (currBrewSwitchState == kBrewSwitchShortPressed && currBrewState == kBrewIdle) { - brewOn = 1; - startingTime = currentMillisTemp; - timeBrewed = 0; // reset timeBrewed, last brew is still stored - LOG(INFO, "Brew timer started"); - currBrewState = kBrewRunning; + // abort function for state machine from every state + if (currBrewSwitchState == kBrewSwitchIdle && currBrewState > kBrewIdle && currBrewState < kBrewFinished) { + if (currBrewState != kBrewFinished) { + LOG(INFO, "Brew stopped manually"); + } + currBrewState = kBrewFinished; } - - // Update the brewed time if the brew switch is still on - if (currBrewSwitchState == kBrewSwitchShortPressed && currBrewState == kBrewRunning) { + // calculated brew time while brew is running + if (currBrewState > kBrewIdle && currBrewState < kBrewFinished) { timeBrewed = currentMillisTemp - startingTime; } - // Stop the timer when the brew switch is turned off - if (currBrewSwitchState == kBrewSwitchIdle && currBrewState == kBrewRunning) { - brewOn = 0; - lastBrewTimeMillis = millis(); // time brew finished for shottimer delay - LOG(INFO, "Brew timer stopped"); - LOGF(INFO, "Shot time: %4.1f s", timeBrewed / 1000); - currBrewState = kBrewIdle; - } -} -#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 || backflushCycles <= 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 > (backflushFillTime * 1000)) { - startingTime = millis(); - backflushState = kBackflushFlushingStart; - } - - break; - - case kBackflushFlushingStart: - LOG(INFO, "Backflush: Flushing to drip tray..."); - valveRelay.off(); - pumpRelay.off(); - currBackflushCycles++; - backflushState = kBackflushFlushing; - - break; - - case kBackflushFlushing: - if (millis() - startingTime > (backflushFlushTime * 1000) && currBackflushCycles < backflushCycles) { - startingTime = millis(); - backflushState = kBackflushFillingStart; - } - else if (currBackflushCycles >= backflushCycles) { - backflushState = kBackflushWaitBrewswitchOff; - } - - break; - - case kBackflushWaitBrewswitchOff: - if (currBrewSwitchState == kBrewSwitchIdle) { - LOG(INFO, "Backflush: Finished!"); - valveRelay.off(); - pumpRelay.off(); - currBackflushCycles = 0; - backflushState = kBackflushWaitBrewswitchOn; - } - - break; - } -} - -/** - * @brief Time or weight based brew mode - */ -void brew() { - unsigned long currentMillisTemp = millis(); - checkbrewswitch(); - - if (currBrewSwitchState == kBrewSwitchIdle && currBrewState > kBrewIdle && currBrewState < kBrewFinished) { - // abort function for state machine from every state - LOG(INFO, "Brew stopped manually"); - currBrewState = kBrewFinished; - } +#if (FEATURE_BREWCONTROL == 1) // brew-by-time and brew-by-weight + // check if brewswitch was turned off after a brew; Brew only runs once even brewswitch is still pressed if (currBrewSwitchState == kBrewSwitchIdle) { - // check if brewswitch was turned off at least once, last time, brewSwitchWasOff = true; } - if (currBrewState > kBrewIdle && currBrewState < kBrewFinished) { - timeBrewed = currentMillisTemp - startingTime; - } - + // set brew time every cycle, in case changes are done during brew if (brewTime > 0) { - totalBrewTime = (preinfusion * 1000) + (preinfusionPause * 1000) + (brewTime * 1000); // running every cycle, in case changes are done during brew + totalBrewTime = (preinfusion * 1000) + (preinfusionPause * 1000) + (brewTime * 1000); } else { // Stop by time deactivated --> brewTime = 0 @@ -307,66 +200,49 @@ void brew() { // state machine for brew switch (currBrewState) { - case kBrewIdle: // waiting step for brew switch turning on - if (currBrewSwitchState == kBrewSwitchShortPressed && backflushState == 10 && backflushOn == 0 && brewSwitchWasOff && machineState != kWaterEmpty) { + case kBrewIdle: // waiting step for brew switch turning on + if (currBrewSwitchState == kBrewSwitchShortPressed && brewSwitchWasOff && backflushOn == 0 && machineState != kWaterEmpty && machineState != kBackflush) { startingTime = millis(); - timeBrewed = 0; + timeBrewed = 0; // reset timeBrewed, last brew is still stored LOG(INFO, "Brew started"); if (preinfusionPause == 0 || preinfusion == 0) { - brewOn = 1; + LOG(INFO, "Brew running"); currBrewState = kBrewRunning; } else { - brewOn = 1; + LOG(INFO, "Preinfusion running"); currBrewState = kPreinfusion; } } - else { - backflush(); - } break; - case kPreinfusion: // preinfusioon + case kPreinfusion: valveRelay.on(); pumpRelay.on(); - LOG(INFO, "Preinfusion"); - currBrewState = kWaitPreinfusion; - break; - - case kWaitPreinfusion: // waiting time preinfusion if (timeBrewed > (preinfusion * 1000)) { + LOG(INFO, "Preinfusion pause running"); currBrewState = kPreinfusionPause; } break; - case kPreinfusionPause: // preinfusion pause + case kPreinfusionPause: valveRelay.on(); pumpRelay.off(); - LOG(INFO, "Preinfusion pause"); - currBrewState = kWaitPreinfusionPause; - break; - - case kWaitPreinfusionPause: // waiting time preinfusion pause - if (timeBrewed > ((preinfusion * 1000) + (preinfusionPause * 1000))) { + if (timeBrewed > ((preinfusion + preinfusionPause) * 1000)) { + LOG(INFO, "Brew running"); currBrewState = kBrewRunning; } break; - case kBrewRunning: // brew running + case kBrewRunning: valveRelay.on(); pumpRelay.on(); - LOG(INFO, "Brew running"); - currBrewState = kWaitBrew; - - break; - - case kWaitBrew: // waiting time or weight brew // stop brew if target-time is reached --> No stop if stop by time is deactivated via Parameter (0) if ((timeBrewed > totalBrewTime) && ((brewTime > 0))) { @@ -383,25 +259,60 @@ void brew() { break; - case kBrewFinished: // brew finished + case kBrewFinished: valveRelay.off(); pumpRelay.off(); - brewOn = 0; currentMillisTemp = 0; lastBrewTimeMillis = millis(); // time brew finished for shottimer delay brewSwitchWasOff = false; LOG(INFO, "Brew finished"); LOGF(INFO, "Shot time: %4.1f s", timeBrewed / 1000); + LOG(INFO, "Brew idle"); currBrewState = kBrewIdle; break; } +#else // FEATURE_BREWCONTROL == 0, only brew time + + switch (currBrewState) { + case kBrewIdle: // waiting step for brew switch turning on + if (currBrewSwitchState == kBrewSwitchShortPressed && machineState != kWaterEmpty) { + startingTime = millis(); + timeBrewed = 0; // reset timeBrewed, last brew is still stored + LOG(INFO, "Brew timer started"); + currBrewState = kBrewRunning; + } + + break; + + case kBrewRunning: + if (currBrewSwitchState == kBrewSwitchIdle && currBrewState == kBrewRunning) { + currBrewState = kBrewFinished; + } + + break; + + case kBrewFinished: + currentMillisTemp = 0; + lastBrewTimeMillis = millis(); // time brew finished for shottimer delay + LOG(INFO, "Brew finished"); + LOGF(INFO, "Shot time: %4.1f s", timeBrewed / 1000); + LOG(INFO, "Brew idle"); + currBrewState = kBrewIdle; + + break; + } +#endif + + return (currBrewState != kBrewIdle && currBrewState != kBrewFinished); } +#if (FEATURE_BREWCONTROL == 1) /** * @brief manual grouphead flush + * @return true if manual flush is running, false otherwise */ -void manualFlush() { +bool manualFlush() { unsigned long currentMillisTemp = millis(); checkbrewswitch(); if (currManualFlushState == kManualFlushRunning) { @@ -414,7 +325,6 @@ void manualFlush() { startingTime = millis(); valveRelay.on(); pumpRelay.on(); - manualFlushOn = 1; LOG(INFO, "Manual flush started"); currManualFlushState = kManualFlushRunning; } @@ -424,13 +334,91 @@ void manualFlush() { if (currBrewSwitchState != kBrewSwitchLongPressed) { valveRelay.off(); pumpRelay.off(); - manualFlushOn = 0; LOG(INFO, "Manual flush stopped"); LOGF(INFO, "Manual flush time: %4.1f s", timeBrewed / 1000); currManualFlushState = kManualFlushIdle; } break; } + return (currManualFlushState == kManualFlushRunning); } +/** + * @brief Backflush + */ +void backflush() { + checkbrewswitch(); + if (currBackflushState != kBackflushIdle && backflushOn == 0) { + currBackflushState = kBackflushFinished; // Force reset in case backflushOn is reset during backflush! + LOG(INFO, "Backflush: Disabled via webinterface"); + } + else if (offlineMode == 1 || currBrewState > kBrewIdle || backflushCycles <= 0 || backflushOn == 0) { + return; + } + + // abort function for state machine from every state + if (currBrewSwitchState == kBrewSwitchIdle && currBackflushState > kBackflushIdle && currBackflushState < kBackflushFinished) { + currBackflushState = kBackflushFinished; + if (currBackflushState != kBackflushFinished) { + LOG(INFO, "Backflush stopped manually"); + } + } + + // check if brewswitch was turned off after a backflush; Backflush only runs once even brewswitch is still pressed + if (currBrewSwitchState == kBrewSwitchIdle) { + brewSwitchWasOff = true; + } + + // State machine for backflush + switch (currBackflushState) { + case kBackflushIdle: + if (currBrewSwitchState == kBrewSwitchShortPressed && backflushOn && brewSwitchWasOff && machineState != kWaterEmpty) { + startingTime = millis(); + valveRelay.on(); + pumpRelay.on(); + LOGF(INFO, "Start backflush cycle %d", currBackflushCycles); + LOG(INFO, "Backflush: filling portafilter"); + currBackflushState = kBackflushFilling; + } + + break; + + case kBackflushFilling: + if (millis() - startingTime > (backflushFillTime * 1000)) { + startingTime = millis(); + valveRelay.off(); + pumpRelay.off(); + LOG(INFO, "Backflush: flushing into drip tray"); + currBackflushState = kBackflushFlushing; + } + break; + + case kBackflushFlushing: + if (millis() - startingTime > (backflushFlushTime * 1000)) { + if (currBackflushCycles < backflushCycles) { + startingTime = millis(); + valveRelay.on(); + pumpRelay.on(); + currBackflushCycles++; + LOGF(INFO, "Backflush: next backflush cycle %d", currBackflushCycles); + LOG(INFO, "Backflush: filling portafilter"); + currBackflushState = kBackflushFilling; + } + else { + currBackflushState = kBackflushFinished; + } + } + break; + + case kBackflushFinished: + valveRelay.off(); + pumpRelay.off(); + LOGF(INFO, "Backflush finished after %d cycles", currBackflushCycles); + currBackflushCycles = 1; + brewSwitchWasOff = false; + currBackflushState = kBackflushIdle; + + break; + } +} #endif diff --git a/src/display/displayCommon.h b/src/display/displayCommon.h index 0a3bf38c8..fe1f0c8aa 100644 --- a/src/display/displayCommon.h +++ b/src/display/displayCommon.h @@ -339,8 +339,8 @@ bool displayMachineState() { u8g2.setCursor(2, 10); u8g2.print("Backflush"); - switch (backflushState) { - case kBackflushWaitBrewswitchOn: + switch (currBackflushState) { + case kBackflushIdle: u8g2.setFont(u8g2_font_profont12_tf); u8g2.setCursor(4, 37); u8g2.print(langstring_backflush_press); @@ -348,7 +348,7 @@ bool displayMachineState() { u8g2.print(langstring_backflush_start); break; - case kBackflushWaitBrewswitchOff: + case kBackflushFinished: u8g2.setFont(u8g2_font_profont12_tf); u8g2.setCursor(4, 37); u8g2.print(langstring_backflush_press); @@ -359,7 +359,7 @@ bool displayMachineState() { default: u8g2.setFont(u8g2_font_fub17_tf); u8g2.setCursor(42, 42); - u8g2.print(currBackflushCycles + 1, 0); + u8g2.print(currBackflushCycles, 0); u8g2.print("/"); u8g2.print(backflushCycles, 0); break; diff --git a/src/main.cpp b/src/main.cpp index c8cfaa672..79cb3b9c7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -118,14 +118,6 @@ unsigned int wifiReconnects = 0; // actual number of reconnects // OTA const char* OTApass = OTAPASS; -// Backflush values -int backflushCycles = BACKFLUSH_CYCLES; -double backflushFillTime = BACKFLUSH_FILL_TIME; -double backflushFlushTime = BACKFLUSH_FLUSH_TIME; -int backflushOn = 0; -int backflushState = 10; -int currBackflushCycles = 0; // number of active flush cycles - // Pressure sensor #if (FEATURE_PRESSURESENSOR == 1) float inputPressure = 0; @@ -199,9 +191,7 @@ double aggKp = AGGKP; double aggTn = AGGTN; double aggTv = AGGTV; double aggIMax = AGGIMAX; -double brewTime = BREW_TIME; // brewtime in s -double preinfusion = PRE_INFUSION_TIME; // preinfusion time in s -double preinfusionPause = PRE_INFUSION_PAUSE_TIME; // preinfusion pause time in s + double weightSetpoint = SCALE_WEIGHTSETPOINT; // PID - values for offline brew detection @@ -224,6 +214,29 @@ double standbyModeTime = STANDBY_MODE_TIME; #include "standby.h" +// Variables to hold PID values (Temp input, Heater output) +double temperature, pidOutput; +int steamON = 0; +int steamFirstON = 0; + +#if startTn == 0 +double startKi = 0; +#else +double startKi = startKp / startTn; +#endif + +#if aggTn == 0 +double aggKi = 0; +#else +double aggKi = aggKp / aggTn; +#endif + +double aggKd = aggTv * aggKp; + +PID bPID(&temperature, &pidOutput, &setpoint, aggKp, aggKi, aggKd, 1, DIRECT); + +#include "brewHandler.h" + // system parameter EEPROM storage wrappers (current value as pointer to variable, minimum, maximum, optional storage ID) SysPara sysParaPidOn(&pidON, 0, 1, STO_ITEM_PID_ON); SysPara sysParaUsePonM(&usePonM, 0, 1, STO_ITEM_PID_START_PONM); @@ -274,29 +287,6 @@ unsigned long previousMillistemp; // initialisation at the end of init() double setpointTemp; double previousInput = 0; -// Variables to hold PID values (Temp input, Heater output) -double temperature, pidOutput; -int steamON = 0; -int steamFirstON = 0; - -#if startTn == 0 -double startKi = 0; -#else -double startKi = startKp / startTn; -#endif - -#if aggTn == 0 -double aggKi = 0; -#else -double aggKi = aggKp / aggTn; -#endif - -double aggKd = aggTv * aggKp; - -PID bPID(&temperature, &pidOutput, &setpoint, aggKp, aggKi, aggKd, 1, DIRECT); - -#include "brewHandler.h" - // Embedded HTTP Server #include "embeddedWebserver.h" @@ -553,16 +543,17 @@ void handleMachineState() { break; case kPidNormal: - - if (brewOn == 1) { +#if (FEATURE_BREWSWITCH == 1) + if (brew()) { machineState = kBrew; if (standbyModeOn) { resetStandbyTimer(); } } - - if (manualFlushOn == 1) { +#endif +#if (FEATURE_BREWCONTROL == 1) + if (manualFlush()) { machineState = kManualFlush; if (standbyModeOn) { @@ -570,16 +561,16 @@ void handleMachineState() { } } - if (steamON == 1) { - machineState = kSteam; + if (backflushOn || currBackflushState > kBackflushIdle) { + machineState = kBackflush; if (standbyModeOn) { resetStandbyTimer(); } } - - if (backflushOn || backflushState > kBackflushWaitBrewswitchOn) { - machineState = kBackflush; +#endif + if (steamON == 1) { + machineState = kSteam; if (standbyModeOn) { resetStandbyTimer(); @@ -608,10 +599,10 @@ void handleMachineState() { } break; - +#if (FEATURE_BREWSWITCH == 1) case kBrew: - if (brewOn == 0) { + if (!brew()) { machineState = kPidNormal; } @@ -631,10 +622,11 @@ void handleMachineState() { machineState = kSensorError; } break; - +#endif +#if (FEATURE_BREWCONTROL == 1) case kManualFlush: - if (manualFlushOn == 0) { + if (!manualFlush()) { machineState = kPidNormal; } @@ -654,7 +646,7 @@ void handleMachineState() { machineState = kSensorError; } break; - +#endif case kSteam: if (steamON == 0) { machineState = kPidNormal; @@ -664,7 +656,7 @@ void handleMachineState() { machineState = kEmergencyStop; } - if (backflushOn || backflushState > kBackflushWaitBrewswitchOn) { + if (backflushOn || currBackflushState > kBackflushIdle) { // if this is possible, any other state change (brew, flush.etc should be possible) machineState = kBackflush; } @@ -680,8 +672,18 @@ void handleMachineState() { machineState = kSensorError; } break; - +#if (FEATURE_BREWCONTROL == 1) case kBackflush: + // turn off PID and Heater during backflush; flushing will cause the PID to swing + if (bPID.GetMode() == 1) { // Deactivate PID + bPID.SetMode(0); + pidOutput = 0; + } + + heaterRelay.off(); // Stop heating + + backflush(); + if (backflushOn == 0) { machineState = kPidNormal; } @@ -694,7 +696,7 @@ void handleMachineState() { machineState = kPidDisabled; } - if (!waterFull && (backflushState == kBackflushWaitBrewswitchOn || backflushState == kBackflushWaitBrewswitchOff)) { + if (!waterFull && (currBackflushState == kBackflushIdle || currBackflushState == kBackflushFinished)) { machineState = kWaterEmpty; } @@ -702,7 +704,7 @@ void handleMachineState() { machineState = kSensorError; } break; - +#endif case kEmergencyStop: if (!emergencyStop) { machineState = kPidNormal; @@ -754,41 +756,55 @@ void handleMachineState() { #endif } - if (pidON || steamON || brewOn || manualFlushOn) { + if (pidON) { pidON = 1; resetStandbyTimer(); #if OLED_DISPLAY != 0 u8g2.setPowerSave(0); #endif + machineState = kPidNormal; + } + if (steamON) { + pidON = 1; + resetStandbyTimer(); +#if OLED_DISPLAY != 0 + u8g2.setPowerSave(0); +#endif + machineState = kSteam; + } - if (steamON) { - machineState = kSteam; - } - else if (brewOn) { - machineState = kBrew; - } - else if (manualFlushOn) { - machineState = kManualFlush; - } - else { - machineState = kPidNormal; +#if (FEATURE_BREWSWITCH == 1) + if (brew()) { + pidON = 1; + resetStandbyTimer(); +#if OLED_DISPLAY != 0 + u8g2.setPowerSave(0); +#endif +#endif +#if (FEATURE_BREWCONTROL == 1) + if (manualFlush()) { + pidON = 1; + resetStandbyTimer(); +#if OLED_DISPLAY != 0 + u8g2.setPowerSave(0); +#endif } - } +#endif - if (tempSensor->hasError()) { - machineState = kSensorError; - } - break; + if (tempSensor->hasError()) { + machineState = kSensorError; + } + break; - case kSensorError: - machineState = kSensorError; - break; + case kSensorError: + machineState = kSensorError; + break; - case kEepromError: - machineState = kEepromError; - break; + case kEepromError: + machineState = kEepromError; + break; + } } - if (machineState != lastmachinestate) { printMachineState(); lastmachinestate = machineState; @@ -1575,7 +1591,7 @@ void looppid() { LOGF(TRACE, "Current PID Output: %f", pidOutput); LOGF(TRACE, "Current Machinestate: %s", machinestateEnumToString(machineState)); LOGF(TRACE, "timeBrewed %f", timeBrewed); - LOGF(TRACE, "Brew detected %i", brewOn); + LOGF(TRACE, "Brew detected %i", brew()); } } @@ -1584,10 +1600,6 @@ void looppid() { shottimerscale(); // Calculation of weight of shot while brew is running #endif -#if (FEATURE_BREWSWITCH == 1 && FEATURE_BREWCONTROL == 0) - brewTimer(); -#endif - #if (FEATURE_BREWSWITCH == 1 && FEATURE_BREWCONTROL == 1) brew(); manualFlush(); From 22561c9cb1c6c28d6cc34081684324b3577fce87 Mon Sep 17 00:00:00 2001 From: Lorenz Uhlig <98092139+LoQue90@users.noreply.github.com> Date: Sun, 13 Oct 2024 19:11:30 +0200 Subject: [PATCH 17/23] bring brewcontrol setting onto website disable PID for backflush with global PID ON/OFF --- data/js/app.js | 10 +- src/brewHandler.h | 208 +++++++++++++------------- src/defaults.h | 1 + src/display/displayRotateUpright.h | 2 +- src/display/displayTemplateMinimal.h | 58 ++++--- src/display/displayTemplateStandard.h | 77 +++++----- src/display/displayTemplateUpright.h | 62 ++++---- src/embeddedWebserver.h | 2 +- src/main.cpp | 120 ++++++++------- src/storage.h | 10 +- src/userConfig_sample.h | 1 - 11 files changed, 285 insertions(+), 266 deletions(-) diff --git a/data/js/app.js b/data/js/app.js index 11cc61aad..623c6aa43 100644 --- a/data/js/app.js +++ b/data/js/app.js @@ -24,7 +24,7 @@ const vueApp = Vue.createApp({ // post parameter array the same as if it was posted from a form (the values are already updated // from the v-model bindings) var formBody = []; - + this.parameters.forEach(param => { var encodedKey = encodeURIComponent(param.name); var encodedValue = encodeURIComponent(param.value); @@ -41,7 +41,7 @@ const vueApp = Vue.createApp({ cache: 'no-cache', body: formBody }; - + this.isPostingForm = true fetch("/parameters", requestOptions) @@ -74,13 +74,13 @@ const vueApp = Vue.createApp({ sectionName(sectionId) { const sectionNames = { 0: 'PID Parameters', - 1: 'Temperature and Preinfusion', - 2: 'Brew Detection and Brew PID Parameters', + 1: 'Temperature', + 2: 'Brew PID Parameters', 3: 'Brew Control', 4: 'Scale Parameters', 5: 'Power Settings' } - + return sectionNames[sectionId] }, diff --git a/src/brewHandler.h b/src/brewHandler.h index 3b1109c66..97d8851bd 100644 --- a/src/brewHandler.h +++ b/src/brewHandler.h @@ -7,12 +7,11 @@ // TODO: // FEATURE_BREWCONTROL has to be removed from userconfig, setup on website // Flush Timer configurable and seperated from shottimer? -// move brewPIDDisabled to kBrew? new fuction to set PID State based on mashine state switching? if kBrew -> disable PID/wait/BDPID or NORMALPID // check all Scale stuff -// check params website // check MQTT/HASSIO for all brew stuff // show heating logo if steam temp isn´t reached? // how handle brew, backflush, manualflush, hotwater if mashine is in steam mode +// show sections on website only if needed #pragma once @@ -57,14 +56,15 @@ uint8_t currReadingBrewSwitch = LOW; bool brewSwitchWasOff = false; // Brew values +uint8_t featureBrewControl = FEATURE_BREW_CONTROL; // enables control of pumpe and valve double brewTime = BREW_TIME; // brewtime in s double preinfusion = PRE_INFUSION_TIME; // preinfusion time in s double preinfusionPause = PRE_INFUSION_PAUSE_TIME; // preinfusion pause time in s -double totalBrewTime = 0; // total brewtime including preinfusion and preinfusion pause -double timeBrewed = 0; // total brewed time -double lastBrewTimeMillis = 0; // for shottimer delay after brew is finished -unsigned long startingTime = 0; // start time of brew -bool brewPIDDisabled = false; // is PID disabled for delay after brew has started? +double totalBrewTime = 0; // total brewtime including preinfusion and preinfusion pause +double timeBrewed = 0; // total brewed time +double lastBrewTimeMillis = 0; // for shottimer delay after brew is finished +unsigned long startingTime = 0; // start time of brew +bool brewPIDDisabled = false; // is PID disabled for delay after brew has started? // Backflush values int backflushCycles = BACKFLUSH_CYCLES; @@ -182,132 +182,131 @@ bool brew() { timeBrewed = currentMillisTemp - startingTime; } -#if (FEATURE_BREWCONTROL == 1) // brew-by-time and brew-by-weight + if (featureBrewControl) { // brew-by-time and brew-by-weight - // check if brewswitch was turned off after a brew; Brew only runs once even brewswitch is still pressed - if (currBrewSwitchState == kBrewSwitchIdle) { - brewSwitchWasOff = true; - } - - // set brew time every cycle, in case changes are done during brew - if (brewTime > 0) { - totalBrewTime = (preinfusion * 1000) + (preinfusionPause * 1000) + (brewTime * 1000); - } - else { - // Stop by time deactivated --> brewTime = 0 - totalBrewTime = 0; - } + // check if brewswitch was turned off after a brew; Brew only runs once even brewswitch is still pressed + if (currBrewSwitchState == kBrewSwitchIdle) { + brewSwitchWasOff = true; + } - // state machine for brew - switch (currBrewState) { - case kBrewIdle: // waiting step for brew switch turning on - if (currBrewSwitchState == kBrewSwitchShortPressed && brewSwitchWasOff && backflushOn == 0 && machineState != kWaterEmpty && machineState != kBackflush) { - startingTime = millis(); - timeBrewed = 0; // reset timeBrewed, last brew is still stored - LOG(INFO, "Brew started"); + // set brew time every cycle, in case changes are done during brew + if (brewTime > 0) { + totalBrewTime = (preinfusion * 1000) + (preinfusionPause * 1000) + (brewTime * 1000); + } + else { + // Stop by time deactivated --> brewTime = 0 + totalBrewTime = 0; + } - if (preinfusionPause == 0 || preinfusion == 0) { - LOG(INFO, "Brew running"); - currBrewState = kBrewRunning; - } - else { - LOG(INFO, "Preinfusion running"); - currBrewState = kPreinfusion; + // state machine for brew + switch (currBrewState) { + case kBrewIdle: // waiting step for brew switch turning on + if (currBrewSwitchState == kBrewSwitchShortPressed && brewSwitchWasOff && backflushOn == 0 && machineState != kWaterEmpty && machineState != kBackflush) { + startingTime = millis(); + timeBrewed = 0; // reset timeBrewed, last brew is still stored + LOG(INFO, "Brew started"); + + if (preinfusionPause == 0 || preinfusion == 0) { + LOG(INFO, "Brew running"); + currBrewState = kBrewRunning; + } + else { + LOG(INFO, "Preinfusion running"); + currBrewState = kPreinfusion; + } } - } - break; + break; - case kPreinfusion: - valveRelay.on(); - pumpRelay.on(); + case kPreinfusion: + valveRelay.on(); + pumpRelay.on(); - if (timeBrewed > (preinfusion * 1000)) { - LOG(INFO, "Preinfusion pause running"); - currBrewState = kPreinfusionPause; - } + if (timeBrewed > (preinfusion * 1000)) { + LOG(INFO, "Preinfusion pause running"); + currBrewState = kPreinfusionPause; + } - break; + break; - case kPreinfusionPause: - valveRelay.on(); - pumpRelay.off(); + case kPreinfusionPause: + valveRelay.on(); + pumpRelay.off(); - if (timeBrewed > ((preinfusion + preinfusionPause) * 1000)) { - LOG(INFO, "Brew running"); - currBrewState = kBrewRunning; - } + if (timeBrewed > ((preinfusion + preinfusionPause) * 1000)) { + LOG(INFO, "Brew running"); + currBrewState = kBrewRunning; + } - break; + break; - case kBrewRunning: - valveRelay.on(); - pumpRelay.on(); + case kBrewRunning: + valveRelay.on(); + pumpRelay.on(); - // 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; - } + // 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; - } + // 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 - break; + break; - case kBrewFinished: - valveRelay.off(); - pumpRelay.off(); - currentMillisTemp = 0; - lastBrewTimeMillis = millis(); // time brew finished for shottimer delay - brewSwitchWasOff = false; - LOG(INFO, "Brew finished"); - LOGF(INFO, "Shot time: %4.1f s", timeBrewed / 1000); - LOG(INFO, "Brew idle"); - currBrewState = kBrewIdle; + case kBrewFinished: + valveRelay.off(); + pumpRelay.off(); + currentMillisTemp = 0; + lastBrewTimeMillis = millis(); // time brew finished for shottimer delay + brewSwitchWasOff = false; + LOG(INFO, "Brew finished"); + LOGF(INFO, "Shot time: %4.1f s", timeBrewed / 1000); + LOG(INFO, "Brew idle"); + currBrewState = kBrewIdle; - break; + break; + } } -#else // FEATURE_BREWCONTROL == 0, only brew time + else { // brewControlOn == 0, only brew time - switch (currBrewState) { - case kBrewIdle: // waiting step for brew switch turning on - if (currBrewSwitchState == kBrewSwitchShortPressed && machineState != kWaterEmpty) { - startingTime = millis(); - timeBrewed = 0; // reset timeBrewed, last brew is still stored - LOG(INFO, "Brew timer started"); - currBrewState = kBrewRunning; - } + switch (currBrewState) { + case kBrewIdle: // waiting step for brew switch turning on + if (currBrewSwitchState == kBrewSwitchShortPressed && machineState != kWaterEmpty) { + startingTime = millis(); + timeBrewed = 0; // reset timeBrewed, last brew is still stored + LOG(INFO, "Brew timer started"); + currBrewState = kBrewRunning; + } - break; + break; - case kBrewRunning: - if (currBrewSwitchState == kBrewSwitchIdle && currBrewState == kBrewRunning) { - currBrewState = kBrewFinished; - } + case kBrewRunning: + if (currBrewSwitchState == kBrewSwitchIdle && currBrewState == kBrewRunning) { + currBrewState = kBrewFinished; + } - break; + break; - case kBrewFinished: - currentMillisTemp = 0; - lastBrewTimeMillis = millis(); // time brew finished for shottimer delay - LOG(INFO, "Brew finished"); - LOGF(INFO, "Shot time: %4.1f s", timeBrewed / 1000); - LOG(INFO, "Brew idle"); - currBrewState = kBrewIdle; + case kBrewFinished: + currentMillisTemp = 0; + lastBrewTimeMillis = millis(); // time brew finished for shottimer delay + LOG(INFO, "Brew finished"); + LOGF(INFO, "Shot time: %4.1f s", timeBrewed / 1000); + LOG(INFO, "Brew idle"); + currBrewState = kBrewIdle; - break; + break; + } } -#endif - return (currBrewState != kBrewIdle && currBrewState != kBrewFinished); } -#if (FEATURE_BREWCONTROL == 1) /** * @brief manual grouphead flush * @return true if manual flush is running, false otherwise @@ -421,4 +420,3 @@ void backflush() { break; } } -#endif diff --git a/src/defaults.h b/src/defaults.h index 8e1a4e3a3..7de3ef828 100644 --- a/src/defaults.h +++ b/src/defaults.h @@ -47,6 +47,7 @@ int writeSysParamsToStorage(void); #define BACKFLUSH_CYCLES 5 // number of cycles the backflush should run #define BACKFLUSH_FILL_TIME 5 // time in seconds the pump is running during backflush #define BACKFLUSH_FLUSH_TIME 10 // time in seconds the 3-way valve is open during backflush +#define FEATURE_BREW_CONTROL 0 // enables function to control pump and solenoid valve #define PID_KP_START_MIN 0 #define PID_KP_START_MAX 999 diff --git a/src/display/displayRotateUpright.h b/src/display/displayRotateUpright.h index 391bf6181..7caa85c75 100644 --- a/src/display/displayRotateUpright.h +++ b/src/display/displayRotateUpright.h @@ -88,7 +88,7 @@ void displayEmergencyStop(void) { * @brief display shot timer */ bool displayShottimer() { - if (((timeBrewed > 0 && FEATURE_BREWCONTROL == 0) || (FEATURE_BREWCONTROL > 0 && currBrewState > kBrewIdle && currBrewState <= kBrewFinished)) && FEATURE_SHOTTIMER == 1) { + if (((timeBrewed > 0 && featureBrewControl == 0) || (featureBrewControl > 0 && currBrewState > kBrewIdle && currBrewState <= kBrewFinished)) && FEATURE_SHOTTIMER == 1) { u8g2.clearBuffer(); // draw temp icon diff --git a/src/display/displayTemplateMinimal.h b/src/display/displayTemplateMinimal.h index 297b0f1ed..de8063b0c 100644 --- a/src/display/displayTemplateMinimal.h +++ b/src/display/displayTemplateMinimal.h @@ -79,41 +79,39 @@ void printScreen() { u8g2.setFont(u8g2_font_profont11_tf); // Brew time -#if (FEATURE_BREWSWITCH == 1 && FEATURE_BREWCONTROL == 1) - - // Shown brew time while machine is brewing and after the brewing during SHOTTIMERDISPLAYDELAY - if (machineState == kBrew || (millis() - lastBrewTimeMillis) < SHOTTIMERDISPLAYDELAY) { - u8g2.setCursor(34, 44); - u8g2.print(langstring_brew); - u8g2.print(timeBrewed / 1000, 0); - u8g2.print("/"); - u8g2.print(totalBrewTime / 1000, 0); - } +#if (FEATURE_BREWSWITCH == 1) + if (featureBrewControl) { + // Shown brew time while machine is brewing and after the brewing during SHOTTIMERDISPLAYDELAY + if (machineState == kBrew || (millis() - lastBrewTimeMillis) < SHOTTIMERDISPLAYDELAY) { + u8g2.setCursor(34, 44); + u8g2.print(langstring_brew); + u8g2.print(timeBrewed / 1000, 0); + u8g2.print("/"); + u8g2.print(totalBrewTime / 1000, 0); + } - // Flush time + // Flush time - // Shown flush time while machine is flushing - if (machineState == kManualFlush) { - u8g2.setDrawColor(0); - u8g2.drawBox(34, 44, 100, 15); - u8g2.setDrawColor(1); - u8g2.setCursor(34, 44); - u8g2.print(langstring_manual_flush); - u8g2.print(timeBrewed / 1000, 0); + // Shown flush time while machine is flushing + if (machineState == kManualFlush) { + u8g2.setDrawColor(0); + u8g2.drawBox(34, 44, 100, 15); + u8g2.setDrawColor(1); + u8g2.setCursor(34, 44); + u8g2.print(langstring_manual_flush); + u8g2.print(timeBrewed / 1000, 0); + } } -#endif - -// Brew Timer with optocoupler -#if (FEATURE_BREWSWITCH == 1 && FEATURE_BREWCONTROL == 0) - - // Shown brew time while machine is brewing and after the brewing during SHOTTIMERDISPLAYDELAY - if (machineState == kBrew || (millis() - lastBrewTimeMillis) < SHOTTIMERDISPLAYDELAY) { - u8g2.setCursor(34, 44); - u8g2.print(langstring_brew); - u8g2.print(timeBrewed / 1000, 0); + // Brew Timer with optocoupler + else { + // Shown brew time while machine is brewing and after the brewing during SHOTTIMERDISPLAYDELAY + if (machineState == kBrew || (millis() - lastBrewTimeMillis) < SHOTTIMERDISPLAYDELAY) { + u8g2.setCursor(34, 44); + u8g2.print(langstring_brew); + u8g2.print(timeBrewed / 1000, 0); + } } - #endif // Show heater output in % diff --git a/src/display/displayTemplateStandard.h b/src/display/displayTemplateStandard.h index aea5e6845..bf837555e 100644 --- a/src/display/displayTemplateStandard.h +++ b/src/display/displayTemplateStandard.h @@ -60,48 +60,47 @@ void printScreen() { } // Brew time -#if (FEATURE_BREWSWITCH == 1 && FEATURE_BREWCONTROL == 1) - - // Shown brew time while machine is brewing and after the brewing during SHOTTIMERDISPLAYDELAY - if (machineState == kBrew || (millis() - lastBrewTimeMillis) < SHOTTIMERDISPLAYDELAY) { - u8g2.setFontMode(1); - u8g2.setCursor(34, 36); - u8g2.print(langstring_brew); - u8g2.setCursor(84, 36); - u8g2.print(timeBrewed / 1000, 0); - u8g2.print("/"); - u8g2.print(totalBrewTime / 1000, 0); - u8g2.print(" s"); - } +#if (FEATURE_BREWSWITCH == 1) + + if (featureBrewControl) { + // Shown brew time while machine is brewing and after the brewing during SHOTTIMERDISPLAYDELAY + if (machineState == kBrew || (millis() - lastBrewTimeMillis) < SHOTTIMERDISPLAYDELAY) { + u8g2.setFontMode(1); + u8g2.setCursor(34, 36); + u8g2.print(langstring_brew); + u8g2.setCursor(84, 36); + u8g2.print(timeBrewed / 1000, 0); + u8g2.print("/"); + u8g2.print(totalBrewTime / 1000, 0); + u8g2.print(" s"); + } - // Flush time - - // Shown flush time while machine is flushing - if (machineState == kManualFlush) { - u8g2.setDrawColor(0); - u8g2.drawBox(34, 36, 100, 10); - u8g2.setDrawColor(1); - u8g2.setCursor(34, 36); - u8g2.print(langstring_manual_flush); - u8g2.setCursor(84, 36); - u8g2.print(timeBrewed / 1000, 0); - u8g2.print(" s"); + // Flush time + + // Shown flush time while machine is flushing + if (machineState == kManualFlush) { + u8g2.setDrawColor(0); + u8g2.drawBox(34, 36, 100, 10); + u8g2.setDrawColor(1); + u8g2.setCursor(34, 36); + u8g2.print(langstring_manual_flush); + u8g2.setCursor(84, 36); + u8g2.print(timeBrewed / 1000, 0); + u8g2.print(" s"); + } } - -#endif - -// Brew Timer with optocoupler -#if (FEATURE_BREWSWITCH == 1 && FEATURE_BREWCONTROL == 0) - - // Shown brew time while machine is brewing and after the brewing during SHOTTIMERDISPLAYDELAY - if (machineState == kBrew || (millis() - lastBrewTimeMillis) < SHOTTIMERDISPLAYDELAY) { - u8g2.setCursor(34, 36); - u8g2.print(langstring_brew); - u8g2.setCursor(84, 36); - u8g2.print(timeBrewed / 1000, 0); - u8g2.print(" s"); + else { + // Brew Timer with optocoupler + + // Shown brew time while machine is brewing and after the brewing during SHOTTIMERDISPLAYDELAY + if (machineState == kBrew || (millis() - lastBrewTimeMillis) < SHOTTIMERDISPLAYDELAY) { + u8g2.setCursor(34, 36); + u8g2.print(langstring_brew); + u8g2.setCursor(84, 36); + u8g2.print(timeBrewed / 1000, 0); + u8g2.print(" s"); + } } - #endif // PID values over heat bar diff --git a/src/display/displayTemplateUpright.h b/src/display/displayTemplateUpright.h index 303ebcda7..ffc27bc51 100644 --- a/src/display/displayTemplateUpright.h +++ b/src/display/displayTemplateUpright.h @@ -87,40 +87,42 @@ void printScreen() { u8g2.print("%"); // Brew time -#if (FEATURE_BREWSWITCH == 1 && FEATURE_BREWCONTROL == 1) - // Show brew time; after brew finished show lastBrewTime during SHOTTIMERDISPLAYDELAY - if (machineState == kBrew || (millis() - lastBrewTimeMillis) < SHOTTIMERDISPLAYDELAY) { - u8g2.setCursor(1, 34); - u8g2.print(langstring_brew_rot_ur); - u8g2.print(timeBrewed / 1000, 0); - u8g2.print("/"); - u8g2.print(totalBrewTime / 1000, 0); - u8g2.print(" s"); - } +#if (FEATURE_BREWSWITCH == 1) + if (featureBrewControl) { + // Show brew time; after brew finished show lastBrewTime during SHOTTIMERDISPLAYDELAY + if (machineState == kBrew || (millis() - lastBrewTimeMillis) < SHOTTIMERDISPLAYDELAY) { + u8g2.setCursor(1, 34); + u8g2.print(langstring_brew_rot_ur); + u8g2.print(timeBrewed / 1000, 0); + u8g2.print("/"); + u8g2.print(totalBrewTime / 1000, 0); + u8g2.print(" s"); + } - // Flush time - - // Shown flush time while machine is flushing - if (machineState == kManualFlush) { - u8g2.setDrawColor(0); - u8g2.drawBox(1, 34, 100, 15); - u8g2.setDrawColor(1); - u8g2.setCursor(1, 34); - u8g2.print(langstring_manual_flush_rot_ur); - u8g2.print(timeBrewed / 1000, 0); - u8g2.print(" s"); + // Flush time + + // Shown flush time while machine is flushing + if (machineState == kManualFlush) { + u8g2.setDrawColor(0); + u8g2.drawBox(1, 34, 100, 15); + u8g2.setDrawColor(1); + u8g2.setCursor(1, 34); + u8g2.print(langstring_manual_flush_rot_ur); + u8g2.print(timeBrewed / 1000, 0); + u8g2.print(" s"); + } } + else { -#endif + // Brew Timer with optocoupler -// Brew Timer with optocoupler -#if (FEATURE_BREWSWITCH == 1 && FEATURE_BREWCONTROL == 0) - // Shown brew time while machine is brewing and after the brewing during SHOTTIMERDISPLAYDELAY - if (machineState == kBrew || (millis() - lastBrewTimeMillis) < SHOTTIMERDISPLAYDELAY) { - u8g2.setCursor(1, 34); - u8g2.print(langstring_brew_rot_ur); - u8g2.print(timeBrewed / 1000, 0); - u8g2.print(" s"); + // Shown brew time while machine is brewing and after the brewing during SHOTTIMERDISPLAYDELAY + if (machineState == kBrew || (millis() - lastBrewTimeMillis) < SHOTTIMERDISPLAYDELAY) { + u8g2.setCursor(1, 34); + u8g2.print(langstring_brew_rot_ur); + u8g2.print(timeBrewed / 1000, 0); + u8g2.print(" s"); + } } #endif diff --git a/src/embeddedWebserver.h b/src/embeddedWebserver.h index 5c312cf10..3690977bf 100644 --- a/src/embeddedWebserver.h +++ b/src/embeddedWebserver.h @@ -58,7 +58,7 @@ void serverSetup(); void setEepromWriteFcn(int (*fcnPtr)(void)); // editable vars are specified in main.cpp -#define EDITABLE_VARS_LEN 35 +#define EDITABLE_VARS_LEN 37 extern std::map editableVars; // EEPROM diff --git a/src/main.cpp b/src/main.cpp index 79cb3b9c7..569887cdb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -268,6 +268,7 @@ SysPara sysParaScaleKnownWeight(&scaleKnownWeight, 0, 2000, STO_ITEM_SCAL SysPara sysParaBackflushCycles(&backflushCycles, BACKFLUSH_CYCLES_MIN, BACKFLUSH_CYCLES_MAX, STO_ITEM_BACKFLUSH_CYCLES); SysPara sysParaBackflushFillTime(&backflushFillTime, BACKFLUSH_FILL_TIME_MIN, BACKFLUSH_FILL_TIME_MAX, STO_ITEM_BACKFLUSH_FILL_TIME); SysPara sysParaBackflushFlushTime(&backflushFlushTime, BACKFLUSH_FLUSH_TIME_MIN, BACKFLUSH_FLUSH_TIME_MAX, STO_ITEM_BACKFLUSH_FLUSH_TIME); +SysPara sysParaFeatureBrewControl(&featureBrewControl, 0, 1, STO_ITEM_FEATURE_BREW_CONTROL); // Other variables boolean emergencyStop = false; // Emergency stop if temperature is too high @@ -543,7 +544,7 @@ void handleMachineState() { break; case kPidNormal: -#if (FEATURE_BREWSWITCH == 1) + if (brew()) { machineState = kBrew; @@ -551,8 +552,7 @@ void handleMachineState() { resetStandbyTimer(); } } -#endif -#if (FEATURE_BREWCONTROL == 1) + if (manualFlush()) { machineState = kManualFlush; @@ -561,14 +561,14 @@ void handleMachineState() { } } - if (backflushOn || currBackflushState > kBackflushIdle) { + if (backflushOn) { machineState = kBackflush; if (standbyModeOn) { resetStandbyTimer(); } } -#endif + if (steamON == 1) { machineState = kSteam; @@ -599,7 +599,7 @@ void handleMachineState() { } break; -#if (FEATURE_BREWSWITCH == 1) + case kBrew: if (!brew()) { @@ -622,8 +622,7 @@ void handleMachineState() { machineState = kSensorError; } break; -#endif -#if (FEATURE_BREWCONTROL == 1) + case kManualFlush: if (!manualFlush()) { @@ -646,7 +645,7 @@ void handleMachineState() { machineState = kSensorError; } break; -#endif + case kSteam: if (steamON == 0) { machineState = kPidNormal; @@ -672,15 +671,8 @@ void handleMachineState() { machineState = kSensorError; } break; -#if (FEATURE_BREWCONTROL == 1) - case kBackflush: - // turn off PID and Heater during backflush; flushing will cause the PID to swing - if (bPID.GetMode() == 1) { // Deactivate PID - bPID.SetMode(0); - pidOutput = 0; - } - heaterRelay.off(); // Stop heating + case kBackflush: backflush(); @@ -704,7 +696,7 @@ void handleMachineState() { machineState = kSensorError; } break; -#endif + case kEmergencyStop: if (!emergencyStop) { machineState = kPidNormal; @@ -773,15 +765,13 @@ void handleMachineState() { machineState = kSteam; } -#if (FEATURE_BREWSWITCH == 1) if (brew()) { pidON = 1; resetStandbyTimer(); #if OLED_DISPLAY != 0 u8g2.setPowerSave(0); #endif -#endif -#if (FEATURE_BREWCONTROL == 1) + if (manualFlush()) { pidON = 1; resetStandbyTimer(); @@ -789,7 +779,6 @@ void handleMachineState() { u8g2.setPowerSave(0); #endif } -#endif if (tempSensor->hasError()) { machineState = kSensorError; @@ -1086,13 +1075,24 @@ void setup() { .maxValue = STEAM_SETPOINT_MAX, .ptr = (void*)&steamSetpoint}; + editableVars["BREWCONTROL"] = {.displayName = F("Brew Control"), + .hasHelpText = true, + .helpText = F("Enables brew-by-time or brew-by-weight"), + .type = kUInt8, + .section = sBrewSection, + .position = 14, + .show = [] { return true && FEATURE_BREWSWITCH == 1; }, + .minValue = false, + .maxValue = true, + .ptr = (void*)&featureBrewControl}; + editableVars["BREW_TIME"] = {.displayName = F("Brew Time (s)"), .hasHelpText = true, .helpText = F("Stop brew after this time. Set to 0 to deactivate brew-by-time-feature."), .type = kDouble, .section = sBrewSection, - .position = 14, - .show = [] { return true && FEATURE_BREWCONTROL == 1; }, + .position = 15, + .show = [] { return true && featureBrewControl == 1; }, .minValue = BREW_TIME_MIN, .maxValue = BREW_TIME_MAX, .ptr = (void*)&brewTime}; @@ -1102,8 +1102,8 @@ void setup() { .helpText = "", .type = kDouble, .section = sBrewSection, - .position = 15, - .show = [] { return true && FEATURE_BREWCONTROL == 1; }, + .position = 16, + .show = [] { return true && featureBrewControl == 1; }, .minValue = PRE_INFUSION_PAUSE_MIN, .maxValue = PRE_INFUSION_PAUSE_MAX, .ptr = (void*)&preinfusionPause}; @@ -1113,8 +1113,8 @@ void setup() { .helpText = "", .type = kDouble, .section = sBrewSection, - .position = 16, - .show = [] { return true && FEATURE_BREWCONTROL == 1; }, + .position = 17, + .show = [] { return true && featureBrewControl == 1; }, .minValue = PRE_INFUSION_TIME_MIN, .maxValue = PRE_INFUSION_TIME_MAX, .ptr = (void*)&preinfusion}; @@ -1124,8 +1124,8 @@ void setup() { .helpText = "Number of cycles of filling and flushing during a backflush", .type = kInteger, .section = sBrewSection, - .position = 17, - .show = [] { return true && FEATURE_BREWCONTROL == 1; }, + .position = 18, + .show = [] { return true && featureBrewControl == 1; }, .minValue = BACKFLUSH_CYCLES_MIN, .maxValue = BACKFLUSH_CYCLES_MAX, .ptr = (void*)&backflushCycles}; @@ -1135,8 +1135,8 @@ void setup() { .helpText = "Time in seconds the pump is running during one backflush cycle", .type = kDouble, .section = sBrewSection, - .position = 18, - .show = [] { return true && FEATURE_BREWCONTROL == 1; }, + .position = 19, + .show = [] { return true && featureBrewControl == 1; }, .minValue = BACKFLUSH_FILL_TIME_MIN, .maxValue = BACKFLUSH_FILL_TIME_MAX, .ptr = (void*)&backflushFillTime}; @@ -1146,8 +1146,8 @@ void setup() { .helpText = "Time in seconds the selenoid valve stays open during one backflush cycle", .type = kDouble, .section = sBrewSection, - .position = 19, - .show = [] { return true && FEATURE_BREWCONTROL == 1; }, + .position = 20, + .show = [] { return true && featureBrewControl == 1; }, .minValue = BACKFLUSH_FLUSH_TIME_MIN, .maxValue = BACKFLUSH_FLUSH_TIME_MAX, .ptr = (void*)&backflushFlushTime}; @@ -1157,7 +1157,7 @@ void setup() { .helpText = F("Brew is running until this weight has been measured. Set to 0 to deactivate brew-by-weight-feature."), .type = kDouble, .section = sBrewSection, - .position = 20, + .position = 21, .show = [] { return true && FEATURE_SCALE == 1; }, .minValue = WEIGHTSETPOINT_MIN, .maxValue = WEIGHTSETPOINT_MAX, @@ -1171,7 +1171,7 @@ void setup() { "Silvia. Set to 0 for thermoblock machines."), .type = kDouble, .section = sBDSection, - .position = 21, + .position = 22, .show = [] { return true; }, .minValue = BREW_PID_DELAY_MIN, .maxValue = BREW_PID_DELAY_MAX, @@ -1182,7 +1182,7 @@ void setup() { .helpText = F("Use separate PID parameters while brew is running"), .type = kUInt8, .section = sBDSection, - .position = 22, + .position = 23, .show = [] { return true && FEATURE_BREWSWITCH == 1; }, .minValue = 0, .maxValue = 1, @@ -1200,7 +1200,7 @@ void setup() { "#post-1453641' target='_blank'>Details)"), .type = kDouble, .section = sBDSection, - .position = 23, + .position = 24, .show = [] { return true && FEATURE_BREWSWITCH == 1 && useBDPID; }, .minValue = PID_KP_BD_MIN, .maxValue = PID_KP_BD_MAX, @@ -1212,7 +1212,7 @@ void setup() { "brewing has been detected."), .type = kDouble, .section = sBDSection, - .position = 24, + .position = 25, .show = [] { return true && FEATURE_BREWSWITCH == 1 && useBDPID; }, .minValue = PID_TN_BD_MIN, .maxValue = PID_TN_BD_MAX, @@ -1224,24 +1224,24 @@ void setup() { "when brewing has been detected."), .type = kDouble, .section = sBDSection, - .position = 25, + .position = 26, .show = [] { return true && FEATURE_BREWSWITCH == 1 && useBDPID; }, .minValue = PID_TV_BD_MIN, .maxValue = PID_TV_BD_MAX, .ptr = (void*)&aggbTv}; editableVars["STEAM_MODE"] = { - .displayName = F("Steam Mode"), .hasHelpText = false, .helpText = "", .type = kUInt8, .section = sOtherSection, .position = 26, .show = [] { return false; }, .minValue = 0, .maxValue = 1, .ptr = (void*)&steamON}; + .displayName = F("Steam Mode"), .hasHelpText = false, .helpText = "", .type = kUInt8, .section = sOtherSection, .position = 27, .show = [] { return false; }, .minValue = 0, .maxValue = 1, .ptr = (void*)&steamON}; editableVars["BACKFLUSH_ON"] = { - .displayName = F("Backflush"), .hasHelpText = false, .helpText = "", .type = kUInt8, .section = sOtherSection, .position = 27, .show = [] { return false; }, .minValue = 0, .maxValue = 1, .ptr = (void*)&backflushOn}; + .displayName = F("Backflush"), .hasHelpText = false, .helpText = "", .type = kUInt8, .section = sOtherSection, .position = 28, .show = [] { return false; }, .minValue = 0, .maxValue = 1, .ptr = (void*)&backflushOn}; editableVars["STANDBY_MODE_ON"] = {.displayName = F("Enable Standby Timer"), .hasHelpText = true, .helpText = F("Turn heater off after standby time has elapsed."), .type = kUInt8, .section = sPowerSection, - .position = 28, + .position = 29, .show = [] { return true; }, .minValue = 0, .maxValue = 1, @@ -1252,22 +1252,33 @@ void setup() { .helpText = F("Time in minutes until the heater is turned off. Timer is reset by brew detection."), .type = kDouble, .section = sPowerSection, - .position = 29, + .position = 30, .show = [] { return true; }, .minValue = STANDBY_MODE_TIME_MIN, .maxValue = STANDBY_MODE_TIME_MAX, .ptr = (void*)&standbyModeTime}; + editableVars["BREWCONTROL"] = {.displayName = F("Brew Control"), + .hasHelpText = true, + .helpText = F("Enables brew-by-time or brew-by-weight"), + .type = kUInt8, + .section = sBrewSection, + .position = 31, + .show = [] { return true && FEATURE_BREWSWITCH == 1; }, + .minValue = false, + .maxValue = true, + .ptr = (void*)&featureBrewControl}; + #if FEATURE_SCALE == 1 editableVars["TARE_ON"] = { - .displayName = F("Tare"), .hasHelpText = false, .helpText = "", .type = kUInt8, .section = sScaleSection, .position = 30, .show = [] { return false; }, .minValue = 0, .maxValue = 1, .ptr = (void*)&scaleTareOn}; + .displayName = F("Tare"), .hasHelpText = false, .helpText = "", .type = kUInt8, .section = sScaleSection, .position = 32, .show = [] { return false; }, .minValue = 0, .maxValue = 1, .ptr = (void*)&scaleTareOn}; editableVars["CALIBRATION_ON"] = {.displayName = F("Calibration"), .hasHelpText = false, .helpText = "", .type = kUInt8, .section = sScaleSection, - .position = 31, + .position = 33, .show = [] { return false; }, .minValue = 0, .maxValue = 1, @@ -1278,7 +1289,7 @@ void setup() { .helpText = "", .type = kFloat, .section = sScaleSection, - .position = 32, + .position = 34, .show = [] { return true; }, .minValue = 0, .maxValue = 2000, @@ -1289,7 +1300,7 @@ void setup() { .helpText = "", .type = kFloat, .section = sScaleSection, - .position = 33, + .position = 35, .show = [] { return true; }, .minValue = -100000, .maxValue = 100000, @@ -1300,7 +1311,7 @@ void setup() { .helpText = "", .type = kFloat, .section = sScaleSection, - .position = 34, + .position = 36, .show = [] { return SCALE_TYPE == 0; }, .minValue = -100000, .maxValue = 100000, @@ -1308,7 +1319,7 @@ void setup() { #endif editableVars["VERSION"] = { - .displayName = F("Version"), .hasHelpText = false, .helpText = "", .type = kCString, .section = sOtherSection, .position = 35, .show = [] { return false; }, .minValue = 0, .maxValue = 1, .ptr = (void*)sysVersion}; + .displayName = F("Version"), .hasHelpText = false, .helpText = "", .type = kCString, .section = sOtherSection, .position = 37, .show = [] { return false; }, .minValue = 0, .maxValue = 1, .ptr = (void*)sysVersion}; // when adding parameters, set EDITABLE_VARS_LEN to max of .position #if (FEATURE_PRESSURESENSOR == 1) @@ -1333,7 +1344,7 @@ void setup() { mqttVars["steamKp"] = [] { return &editableVars.at("STEAM_KP"); }; mqttVars["standbyModeOn"] = [] { return &editableVars.at("STANDBY_MODE_ON"); }; - if (FEATURE_BREWCONTROL == 1) { + if (featureBrewControl == 1) { mqttVars["brewtime"] = [] { return &editableVars.at("BREW_TIME"); }; mqttVars["preinfusion"] = [] { return &editableVars.at("BREW_PREINFUSION"); }; mqttVars["preinfusionPause"] = [] { return &editableVars.at("BREW_PREINFUSIONPAUSE"); }; @@ -1600,7 +1611,7 @@ void looppid() { shottimerscale(); // Calculation of weight of shot while brew is running #endif -#if (FEATURE_BREWSWITCH == 1 && FEATURE_BREWCONTROL == 1) +#if (FEATURE_BREWSWITCH == 1) brew(); manualFlush(); #endif @@ -1635,7 +1646,8 @@ void looppid() { printDisplayTimer(); #endif - if (machineState == kPidDisabled || machineState == kWaterEmpty || machineState == kSensorError || machineState == kEmergencyStop || machineState == kEepromError || machineState == kStandby || brewPIDDisabled) { + if (machineState == kPidDisabled || machineState == kWaterEmpty || machineState == kSensorError || machineState == kEmergencyStop || machineState == kEepromError || machineState == kStandby || + machineState == kBackflush || brewPIDDisabled) { if (bPID.GetMode() == 1) { // Force PID shutdown bPID.SetMode(0); @@ -1855,6 +1867,7 @@ int readSysParamsFromStorage(void) { if (sysParaBackflushCycles.getStorage() != 0) return -1; if (sysParaBackflushFillTime.getStorage() != 0) return -1; if (sysParaBackflushFlushTime.getStorage() != 0) return -1; + if (sysParaFeatureBrewControl.getStorage() != 0) return -1; return 0; } @@ -1895,6 +1908,7 @@ int writeSysParamsToStorage(void) { if (sysParaBackflushCycles.setStorage() != 0) return -1; if (sysParaBackflushFillTime.setStorage() != 0) return -1; if (sysParaBackflushFlushTime.setStorage() != 0) return -1; + if (sysParaFeatureBrewControl.setStorage() != 0) return -1; return storageCommit(); } diff --git a/src/storage.h b/src/storage.h index 8ea99fc69..c642b3f0c 100644 --- a/src/storage.h +++ b/src/storage.h @@ -44,6 +44,7 @@ typedef enum { STO_ITEM_BACKFLUSH_CYCLES, // number of cycles the backflush should run STO_ITEM_BACKFLUSH_FILL_TIME, // time in ms the pump is running during backflush STO_ITEM_BACKFLUSH_FLUSH_TIME, // time in ms the 3-way valve is open during backflush + STO_ITEM_FEATURE_BREW_CONTROL, // enables function to control pump and solenoid valve /* WHEN ADDING NEW ITEMS, THE FOLLOWING HAS TO BE UPDATED: * - storage structure: sto_data_t @@ -114,6 +115,7 @@ typedef struct __attribute__((packed)) { int backflushCycles; double backflushFillTimeMs; double backflushFlushTimeMs; + bool featureBrewControl; } sto_data_t; @@ -165,6 +167,7 @@ static const sto_data_t itemDefaults PROGMEM = { BACKFLUSH_CYCLES, // STO_ITEM_BACKFLUSH_CYCLES BACKFLUSH_FILL_TIME, // STO_ITEM_BACKFLUSH_FILLTIME BACKFLUSH_FLUSH_TIME, // STO_ITEM_BACKFLUSH_FLUSHTIME + FEATURE_BREW_CONTROL, // STO_ITEM_FEATURE_BREW_CONTROL }; /** @@ -347,6 +350,11 @@ static inline int32_t getItemAddr(sto_item_id_t itemId, uint16_t* maxItemSize = size = STRUCT_MEMBER_SIZE(sto_data_t, backflushFlushTimeMs); break; + case STO_ITEM_FEATURE_BREW_CONTROL: + addr = offsetof(sto_data_t, featureBrewControl); + size = STRUCT_MEMBER_SIZE(sto_data_t, featureBrewControl); + break; + default: LOGF(ERROR, "invalid item ID %i!", itemId); addr = -1; @@ -670,7 +678,7 @@ int storageGet(sto_item_id_t itemId, String& itemValue) { * The value is set in the RAM only! Use 'commit=true' or call * storageCommit() to write the RAM content to the non-volatile memory! * - * @param itemId - storage item ID + * @param itemId - storage item ID * @param itemValue - item value to set * @param commit - true=write current RAM content to NV memory (optional, default=false) * diff --git a/src/userConfig_sample.h b/src/userConfig_sample.h index 65222effb..657e7c8e3 100644 --- a/src/userConfig_sample.h +++ b/src/userConfig_sample.h @@ -50,7 +50,6 @@ enum MACHINE { #define WIFICONNECTIONDELAY 10000 // delay between reconnects in ms // PID & Hardware -#define FEATURE_BREWCONTROL 0 // 0 = deactivated, 1 = activated #define FEATURE_POWERSWITCH 0 // 0 = deactivated, 1 = activated #define POWERSWITCH_TYPE Switch::TOGGLE // Switch::TOGGLE or Switch::MOMENTARY (trigger) #define POWERSWITCH_MODE Switch::NORMALLY_OPEN // Switch::NORMALLY_OPEN or Switch::NORMALLY_CLOSED From 3516b53d20c94ec42ec1347760dd49d35bca61af Mon Sep 17 00:00:00 2001 From: Lorenz Uhlig <98092139+LoQue90@users.noreply.github.com> Date: Mon, 14 Oct 2024 17:40:48 +0200 Subject: [PATCH 18/23] clean up MQTT Brew stuff adding case kInteger to assignMQTTParam() so backflushCycles could be changed thru MQTT --- src/brewHandler.h | 2 - src/main.cpp | 57 +++++++++++------------- src/mqtt.h | 109 ++++++++++++++++++++-------------------------- src/storage.h | 2 +- 4 files changed, 74 insertions(+), 96 deletions(-) diff --git a/src/brewHandler.h b/src/brewHandler.h index 97d8851bd..39f4b3567 100644 --- a/src/brewHandler.h +++ b/src/brewHandler.h @@ -5,10 +5,8 @@ * */ // TODO: -// FEATURE_BREWCONTROL has to be removed from userconfig, setup on website // Flush Timer configurable and seperated from shottimer? // check all Scale stuff -// check MQTT/HASSIO for all brew stuff // show heating logo if steam temp isn´t reached? // how handle brew, backflush, manualflush, hotwater if mashine is in steam mode // show sections on website only if needed diff --git a/src/main.cpp b/src/main.cpp index 569887cdb..4d1d7a543 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1332,8 +1332,6 @@ void setup() { mqttVars["brewTempOffset"] = [] { return &editableVars.at("BREW_TEMP_OFFSET"); }; mqttVars["steamON"] = [] { return &editableVars.at("STEAM_MODE"); }; mqttVars["steamSetpoint"] = [] { return &editableVars.at("STEAM_SETPOINT"); }; - mqttVars["brewPidDelay"] = [] { return &editableVars.at("PID_BD_DELAY"); }; - mqttVars["backflushOn"] = [] { return &editableVars.at("BACKFLUSH_ON"); }; mqttVars["startUsePonM"] = [] { return &editableVars.at("START_USE_PONM"); }; mqttVars["startKp"] = [] { return &editableVars.at("START_KP"); }; mqttVars["startTn"] = [] { return &editableVars.at("START_TN"); }; @@ -1343,33 +1341,18 @@ void setup() { mqttVars["aggIMax"] = [] { return &editableVars.at("PID_I_MAX"); }; mqttVars["steamKp"] = [] { return &editableVars.at("STEAM_KP"); }; mqttVars["standbyModeOn"] = [] { return &editableVars.at("STANDBY_MODE_ON"); }; - - if (featureBrewControl == 1) { - mqttVars["brewtime"] = [] { return &editableVars.at("BREW_TIME"); }; - mqttVars["preinfusion"] = [] { return &editableVars.at("BREW_PREINFUSION"); }; - mqttVars["preinfusionPause"] = [] { return &editableVars.at("BREW_PREINFUSIONPAUSE"); }; - mqttVars["backflushCycles"] = [] { return &editableVars.at("BACKFLUSH_CYCLES"); }; - mqttVars["backflushFillTime"] = [] { return &editableVars.at("BACKFLUSH_FILL_TIME"); }; - mqttVars["backflushFlushTime"] = [] { return &editableVars.at("BACKFLUSH_FLUSH_TIME"); }; - } - - if (FEATURE_SCALE == 1) { - mqttVars["weightSetpoint"] = [] { return &editableVars.at("SCALE_WEIGHTSETPOINT"); }; - mqttVars["scaleCalibration"] = [] { return &editableVars.at("SCALE_CALIBRATION"); }; -#if SCALE_TYPE == 0 - mqttVars["scale2Calibration"] = [] { return &editableVars.at("SCALE2_CALIBRATION"); }; -#endif - mqttVars["scaleKnownWeight"] = [] { return &editableVars.at("SCALE_KNOWN_WEIGHT"); }; - mqttVars["scaleTareOn"] = [] { return &editableVars.at("TARE_ON"); }; - mqttVars["scaleCalibrationOn"] = [] { return &editableVars.at("CALIBRATION_ON"); }; - } - - if (FEATURE_BREWSWITCH == 1) { - mqttVars["pidUseBD"] = [] { return &editableVars.at("PID_BD_ON"); }; - mqttVars["aggbKp"] = [] { return &editableVars.at("PID_BD_KP"); }; - mqttVars["aggbTn"] = [] { return &editableVars.at("PID_BD_TN"); }; - mqttVars["aggbTv"] = [] { return &editableVars.at("PID_BD_TV"); }; - } + mqttVars["brewTime"] = [] { return &editableVars.at("BREW_TIME"); }; + mqttVars["preinfusion"] = [] { return &editableVars.at("BREW_PREINFUSION"); }; + mqttVars["preinfusionPause"] = [] { return &editableVars.at("BREW_PREINFUSIONPAUSE"); }; + mqttVars["backflushOn"] = [] { return &editableVars.at("BACKFLUSH_ON"); }; + mqttVars["backflushCycles"] = [] { return &editableVars.at("BACKFLUSH_CYCLES"); }; + mqttVars["backflushFillTime"] = [] { return &editableVars.at("BACKFLUSH_FILL_TIME"); }; + mqttVars["backflushFlushTime"] = [] { return &editableVars.at("BACKFLUSH_FLUSH_TIME"); }; + mqttVars["brewPidDelay"] = [] { return &editableVars.at("PID_BD_DELAY"); }; + mqttVars["pidUseBD"] = [] { return &editableVars.at("PID_BD_ON"); }; + mqttVars["aggbKp"] = [] { return &editableVars.at("PID_BD_KP"); }; + mqttVars["aggbTn"] = [] { return &editableVars.at("PID_BD_TN"); }; + mqttVars["aggbTv"] = [] { return &editableVars.at("PID_BD_TV"); }; // Values reported to MQTT mqttSensors["temperature"] = [] { return temperature; }; @@ -1379,17 +1362,27 @@ void setup() { mqttSensors["currentKi"] = [] { return bPID.GetKi(); }; mqttSensors["currentKd"] = [] { return bPID.GetKd(); }; mqttSensors["machineState"] = [] { return machineState; }; + #if FEATURE_BREWSWITCH == 1 mqttSensors["timeBrewed"] = [] { return timeBrewed / 1000; }; #endif -#if FEATURE_PRESSURESENSOR == 1 - mqttSensors["pressure"] = [] { return inputPressureFilter; }; -#endif #if FEATURE_SCALE == 1 + mqttVars["weightSetpoint"] = [] { return &editableVars.at("SCALE_WEIGHTSETPOINT"); }; + mqttVars["scaleCalibration"] = [] { return &editableVars.at("SCALE_CALIBRATION"); }; +#if SCALE_TYPE == 0 + mqttVars["scale2Calibration"] = [] { return &editableVars.at("SCALE2_CALIBRATION"); }; +#endif + mqttVars["scaleKnownWeight"] = [] { return &editableVars.at("SCALE_KNOWN_WEIGHT"); }; + mqttVars["scaleTareOn"] = [] { return &editableVars.at("TARE_ON"); }; + mqttVars["scaleCalibrationOn"] = [] { return &editableVars.at("CALIBRATION_ON"); }; + mqttSensors["currentWeight"] = [] { return weight; }; #endif +#if FEATURE_PRESSURESENSOR == 1 + mqttSensors["pressure"] = [] { return inputPressureFilter; }; +#endif initTimer1(); storageSetup(); diff --git a/src/mqtt.h b/src/mqtt.h index 0b6ac311c..83192c247 100644 --- a/src/mqtt.h +++ b/src/mqtt.h @@ -155,31 +155,36 @@ void assignMQTTParam(char* param, double value) { break; case kFloat: - *(float*)var->ptr = value; - mqtt_publish(param, number2string(value), true); + *(float*)var->ptr = static_cast(value); + mqtt_publish(param, number2string(static_cast(value)), true); break; case kUInt8: - *(uint8_t*)var->ptr = value; + *(uint8_t*)var->ptr = static_cast(value); if (strcasecmp(param, "steamON") == 0) { steamFirstON = value; } - mqtt_publish(param, number2string(value), true); + mqtt_publish(param, number2string(static_cast(value)), true); writeSysParamsToStorage(); break; + case kInteger: + *(int*)var->ptr = static_cast(value); + mqtt_publish(param, number2string(static_cast(value)), true); + break; + default: LOGF(WARNING, "%s is not a recognized type for this MQTT parameter.", var->type); break; } } else { - LOGF(WARNING, "Value out of range for MQTT parameter %s", param); + LOGF(WARNING, "%s is not a valid MQTT parameter.", param); } } catch (const std::out_of_range& e) { - LOGF(WARNING, "%s is not a valid MQTT parameter.", param); + LOGF(WARNING, "Value out of range for MQTT parameter %s", param); } } @@ -504,11 +509,15 @@ DiscoveryObject GenerateNumberDevice(String name, String displayName, int min_va * @return 0 if successful, MQTT connection error code if failed to send messages */ int sendHASSIODiscoveryMsg() { - // Number Devices + // Sensor, number and switch objects which will always be published + + DiscoveryObject machineStateDevice = GenerateSensorDevice("machineState", "Machine State", "", "enum"); + DiscoveryObject actual_temperature = GenerateSensorDevice("temperature", "Boiler Temperature", "°C", "temperature"); + DiscoveryObject heaterPower = GenerateSensorDevice("heaterPower", "Heater Power", "%", "power_factor"); + DiscoveryObject brewSetpoint = GenerateNumberDevice("brewSetpoint", "Brew setpoint", BREW_SETPOINT_MIN, BREW_SETPOINT_MAX, 0.1, "°C"); - DiscoveryObject steamSetPoint = GenerateNumberDevice("steamSetpoint", "Steam setpoint", STEAM_SETPOINT_MIN, STEAM_SETPOINT_MAX, 0.1, "°C"); + DiscoveryObject steamSetpoint = GenerateNumberDevice("steamSetpoint", "Steam setpoint", STEAM_SETPOINT_MIN, STEAM_SETPOINT_MAX, 0.1, "°C"); DiscoveryObject brewTempOffset = GenerateNumberDevice("brewTempOffset", "Brew Temp. Offset", BREW_TEMP_OFFSET_MIN, BREW_TEMP_OFFSET_MAX, 0.1, "°C"); - DiscoveryObject brewPidDelay = GenerateNumberDevice("brewPidDelay", "Brew Pid Delay", BREW_PID_DELAY_MIN, BREW_PID_DELAY_MAX, 0.1, ""); DiscoveryObject startKp = GenerateNumberDevice("startKp", "Start kP", PID_KP_START_MIN, PID_KP_START_MAX, 0.1, ""); DiscoveryObject startTn = GenerateNumberDevice("startTn", "Start Tn", PID_TN_START_MIN, PID_TN_START_MAX, 0.1, ""); DiscoveryObject steamKp = GenerateNumberDevice("steamKp", "Start Kp", PID_KP_STEAM_MIN, PID_KP_STEAM_MAX, 0.1, ""); @@ -516,76 +525,54 @@ int sendHASSIODiscoveryMsg() { DiscoveryObject aggTn = GenerateNumberDevice("aggTn", "aggTn", PID_TN_REGULAR_MIN, PID_TN_REGULAR_MAX, 0.1, ""); DiscoveryObject aggTv = GenerateNumberDevice("aggTv", "aggTv", PID_TV_REGULAR_MIN, PID_TV_REGULAR_MAX, 0.1, ""); DiscoveryObject aggIMax = GenerateNumberDevice("aggIMax", "aggIMax", PID_I_MAX_REGULAR_MIN, PID_I_MAX_REGULAR_MAX, 0.1, ""); - -#if FEATURE_BREWCONTROL == 1 - DiscoveryObject brewtime = GenerateNumberDevice("brewtime", "Brew time", BREW_TIME_MIN, BREW_TIME_MAX, 0.1, "s"); + DiscoveryObject brewTime = GenerateNumberDevice("brewTime", "Brew time", BREW_TIME_MIN, BREW_TIME_MAX, 0.1, "s"); DiscoveryObject preinfusion = GenerateNumberDevice("preinfusion", "Preinfusion filling time", PRE_INFUSION_TIME_MIN, PRE_INFUSION_TIME_MAX, 0.1, "s"); DiscoveryObject preinfusionPause = GenerateNumberDevice("preinfusionPause", "Preinfusion pause time", PRE_INFUSION_PAUSE_MIN, PRE_INFUSION_PAUSE_MAX, 0.1, "s"); DiscoveryObject backflushCycles = GenerateNumberDevice("backflushCycles", "Backflush Cycles", BACKFLUSH_CYCLES_MIN, BACKFLUSH_CYCLES_MAX, 1, ""); DiscoveryObject backflushFillTime = GenerateNumberDevice("backflushFillTime", "Backflush filling time", BACKFLUSH_FILL_TIME_MIN, BACKFLUSH_FILL_TIME_MAX, 0.1, "s"); DiscoveryObject backflushFlushTime = GenerateNumberDevice("backflushFlushTime", "Backflush flushing time", BACKFLUSH_FLUSH_TIME_MIN, BACKFLUSH_FLUSH_TIME_MAX, 0.1, "s"); -#endif - - // Sensor Devices - DiscoveryObject actual_temperature = GenerateSensorDevice("temperature", "Boiler Temperature", "°C", "temperature"); - DiscoveryObject heaterPower = GenerateSensorDevice("heaterPower", "Heater Power", "%", "power_factor"); - DiscoveryObject machineStateDevice = GenerateSensorDevice("machineState", "Machine State", "", "enum"); - DiscoveryObject currentWeight = GenerateSensorDevice("currentWeight", "Weight", "g", "weight"); - -#if FEATURE_PRESSURESENSOR == 1 - DiscoveryObject pressure = GenerateSensorDevice("pressure", "Pressure", "bar", "pressure"); -#endif - - // Switch Devices DiscoveryObject pidOn = GenerateSwitchDevice("pidON", "Use PID"); DiscoveryObject steamON = GenerateSwitchDevice("steamON", "Steam"); -#if FEATURE_BREWCONTROL == 1 - DiscoveryObject backflushOn = GenerateSwitchDevice("backflushOn", "Backflush"); -#endif DiscoveryObject startUsePonM = GenerateSwitchDevice("startUsePonM", "Use PonM"); + DiscoveryObject backflushOn = GenerateSwitchDevice("backflushOn", "Backflush"); - // Button Devices - DiscoveryObject scaleCalibrateButton = GenerateButtonDevice("scaleCalibrationOn", "Calibrate Scale"); - DiscoveryObject scaleTareButton = GenerateButtonDevice("scaleTareOn", "Tare Scale"); + // List of all DiscoveryObjects, will be always published + std::vector discoveryObjects = { + machineStateDevice, actual_temperature, heaterPower, brewSetpoint, steamSetpoint, brewTempOffset, startKp, startTn, steamKp, aggKp, aggTn, aggTv, aggIMax, + brewTime, preinfusion, preinfusionPause, backflushCycles, backflushFillTime, backflushFlushTime, pidOn, steamON, startUsePonM, backflushOn}; - std::vector discoveryObjects = {brewSetpoint, - steamSetPoint, - brewTempOffset, - brewPidDelay, - startKp, - startTn, - steamKp, - aggKp, - aggTn, - aggTv, - aggIMax, - actual_temperature, - heaterPower, - machineStateDevice, -#if FEATURE_BREWCONTROL == 1 - brewtime, - preinfusion, - preinfusionPause, - backflushOn, - backflushCycles, - backflushFillTime, - backflushFlushTime, -#endif - pidOn, - steamON, - startUsePonM + // Sensor, number and switch object which will be published based on feature set +#if FEATURE_BREWSWITCH == 1 -#if FEATURE_PRESSURESENSOR == 1 - , - pressure + DiscoveryObject timeBrewed = GenerateSensorDevice("timeBrewed", "Time brewed", "s", "duration"); + + DiscoveryObject brewPidDelay = GenerateNumberDevice("brewPidDelay", "Brew Pid Delay", BREW_PID_DELAY_MIN, BREW_PID_DELAY_MAX, 0.1, "s"); + + discoveryObjects.push_back(timeBrewed); + discoveryObjects.push_back(brewPidDelay); #endif - }; #if FEATURE_SCALE == 1 + + DiscoveryObject currentWeight = GenerateSensorDevice("currentWeight", "Weight", "g", "weight"); + + DiscoveryObject scaleCalibrateButton = GenerateButtonDevice("scaleCalibrationOn", "Calibrate Scale"); + DiscoveryObject scaleTareButton = GenerateButtonDevice("scaleTareOn", "Tare Scale"); + + DiscoveryObject weightSetpoint = GenerateNumberDevice("weightSetpoint", "Weight setpoint", WEIGHTSETPOINT_MIN, WEIGHTSETPOINT_MAX, 0.1, "g"); + discoveryObjects.push_back(currentWeight); discoveryObjects.push_back(scaleCalibrateButton); discoveryObjects.push_back(scaleTareButton); + discoveryObjects.push_back(weightSetpoint); +#endif + +#if FEATURE_PRESSURESENSOR == 1 + + DiscoveryObject pressure = GenerateSensorDevice("pressure", "Pressure", "bar", "pressure"); + + discoveryObjects.push_back(pressure); #endif // Send the Objects to Hassio diff --git a/src/storage.h b/src/storage.h index c642b3f0c..0f613deb9 100644 --- a/src/storage.h +++ b/src/storage.h @@ -115,7 +115,7 @@ typedef struct __attribute__((packed)) { int backflushCycles; double backflushFillTimeMs; double backflushFlushTimeMs; - bool featureBrewControl; + uint8_t featureBrewControl; } sto_data_t; From 05a813250ea9ccf09101e47e5e277a29f6c15e8f Mon Sep 17 00:00:00 2001 From: Lorenz Uhlig <98092139+LoQue90@users.noreply.github.com> Date: Thu, 17 Oct 2024 01:00:45 +0200 Subject: [PATCH 19/23] =?UTF-8?q?don=C2=B4t=20start=20backflush=20from=20k?= =?UTF-8?q?Steam?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit if mashine is in any other state then kPidNormal, it should not be possible to switch to states like kBrew, kManualFlush, kBackflush, etc. --- src/brewHandler.h | 1 - src/main.cpp | 4 ---- 2 files changed, 5 deletions(-) diff --git a/src/brewHandler.h b/src/brewHandler.h index 39f4b3567..f32edf7c9 100644 --- a/src/brewHandler.h +++ b/src/brewHandler.h @@ -8,7 +8,6 @@ // Flush Timer configurable and seperated from shottimer? // check all Scale stuff // show heating logo if steam temp isn´t reached? -// how handle brew, backflush, manualflush, hotwater if mashine is in steam mode // show sections on website only if needed #pragma once diff --git a/src/main.cpp b/src/main.cpp index 4d1d7a543..c8df9cd62 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -655,10 +655,6 @@ void handleMachineState() { machineState = kEmergencyStop; } - if (backflushOn || currBackflushState > kBackflushIdle) { // if this is possible, any other state change (brew, flush.etc should be possible) - machineState = kBackflush; - } - if (pidON == 0) { machineState = kPidDisabled; } From f3d1c1ffb3a5c99f145a4625baf8186916dfb699 Mon Sep 17 00:00:00 2001 From: Lorenz Uhlig <98092139+LoQue90@users.noreply.github.com> Date: Thu, 17 Oct 2024 02:28:53 +0200 Subject: [PATCH 20/23] bring display settings onto the website FEATURE_SHOT_TIMER SHOT_TIMER_DISPLAY_DELAY FEATURE_HEATING_LOGO FEATURE_PID_OFF_LOGO bump ESPAsyncWebServer: another change in release structure -> new version -> broke build check --- data/js/app.js | 3 +- src/defaults.h | 94 ++++++++++++++------------- src/display/displayCommon.h | 10 +-- src/display/displayRotateUpright.h | 6 +- src/display/displayTemplateMinimal.h | 8 +-- src/display/displayTemplateStandard.h | 8 +-- src/embeddedWebserver.h | 2 +- src/main.cpp | 66 ++++++++++++++++++- src/storage.h | 32 +++++++++ src/userConfig_sample.h | 20 +++--- 10 files changed, 172 insertions(+), 77 deletions(-) diff --git a/data/js/app.js b/data/js/app.js index 623c6aa43..6fc7e456f 100644 --- a/data/js/app.js +++ b/data/js/app.js @@ -78,7 +78,8 @@ const vueApp = Vue.createApp({ 2: 'Brew PID Parameters', 3: 'Brew Control', 4: 'Scale Parameters', - 5: 'Power Settings' + 5: 'Display Settings', + 6: 'Power Settings' } return sectionNames[sectionId] diff --git a/src/defaults.h b/src/defaults.h index 7de3ef828..a097a10cf 100644 --- a/src/defaults.h +++ b/src/defaults.h @@ -48,48 +48,54 @@ int writeSysParamsToStorage(void); #define BACKFLUSH_FILL_TIME 5 // time in seconds the pump is running during backflush #define BACKFLUSH_FLUSH_TIME 10 // time in seconds the 3-way valve is open during backflush #define FEATURE_BREW_CONTROL 0 // enables function to control pump and solenoid valve +#define FEATURE_SHOT_TIMER 0 // enables full screen shot timer +#define SHOT_TIMER_DISPLAY_DELAY 3 // time in seconds that shot timer will be shown after brew finished +#define FEATURE_HEATING_LOGO 1 // enables full screen logo if mashine is heating +#define FEATURE_PID_OFF_LOGO 1 // enables full screen logo if pid is switched off -#define PID_KP_START_MIN 0 -#define PID_KP_START_MAX 999 -#define PID_TN_START_MIN 0 -#define PID_TN_START_MAX 999 -#define PID_KP_REGULAR_MIN 0 -#define PID_KP_REGULAR_MAX 999 -#define PID_TN_REGULAR_MIN 0 -#define PID_TN_REGULAR_MAX 999 -#define PID_TV_REGULAR_MIN 0 -#define PID_TV_REGULAR_MAX 999 -#define PID_I_MAX_REGULAR_MIN 0 -#define PID_I_MAX_REGULAR_MAX 999 -#define PID_KP_BD_MIN 0 -#define PID_KP_BD_MAX 999 -#define PID_TN_BD_MIN 0 -#define PID_TN_BD_MAX 999 -#define PID_TV_BD_MIN 0 -#define PID_TV_BD_MAX 999 -#define BREW_SETPOINT_MIN 20 -#define BREW_SETPOINT_MAX 110 -#define STEAM_SETPOINT_MIN 100 -#define STEAM_SETPOINT_MAX 140 -#define BREW_TEMP_OFFSET_MIN 0 -#define BREW_TEMP_OFFSET_MAX 20 -#define BREW_TIME_MIN 0 -#define BREW_TIME_MAX 180 -#define BREW_PID_DELAY_MIN 0 -#define BREW_PID_DELAY_MAX 60 -#define PRE_INFUSION_TIME_MIN 0 -#define PRE_INFUSION_TIME_MAX 60 -#define PRE_INFUSION_PAUSE_MIN 0 -#define PRE_INFUSION_PAUSE_MAX 60 -#define WEIGHTSETPOINT_MIN 0 -#define WEIGHTSETPOINT_MAX 500 -#define PID_KP_STEAM_MIN 0 -#define PID_KP_STEAM_MAX 500 -#define STANDBY_MODE_TIME_MIN 30 -#define STANDBY_MODE_TIME_MAX 120 -#define BACKFLUSH_CYCLES_MIN 2 -#define BACKFLUSH_CYCLES_MAX 20 -#define BACKFLUSH_FILL_TIME_MIN 5 -#define BACKFLUSH_FILL_TIME_MAX 20 -#define BACKFLUSH_FLUSH_TIME_MIN 5 -#define BACKFLUSH_FLUSH_TIME_MAX 20 +#define PID_KP_START_MIN 0 +#define PID_KP_START_MAX 999 +#define PID_TN_START_MIN 0 +#define PID_TN_START_MAX 999 +#define PID_KP_REGULAR_MIN 0 +#define PID_KP_REGULAR_MAX 999 +#define PID_TN_REGULAR_MIN 0 +#define PID_TN_REGULAR_MAX 999 +#define PID_TV_REGULAR_MIN 0 +#define PID_TV_REGULAR_MAX 999 +#define PID_I_MAX_REGULAR_MIN 0 +#define PID_I_MAX_REGULAR_MAX 999 +#define PID_KP_BD_MIN 0 +#define PID_KP_BD_MAX 999 +#define PID_TN_BD_MIN 0 +#define PID_TN_BD_MAX 999 +#define PID_TV_BD_MIN 0 +#define PID_TV_BD_MAX 999 +#define BREW_SETPOINT_MIN 20 +#define BREW_SETPOINT_MAX 110 +#define STEAM_SETPOINT_MIN 100 +#define STEAM_SETPOINT_MAX 140 +#define BREW_TEMP_OFFSET_MIN 0 +#define BREW_TEMP_OFFSET_MAX 20 +#define BREW_TIME_MIN 0 +#define BREW_TIME_MAX 180 +#define BREW_PID_DELAY_MIN 0 +#define BREW_PID_DELAY_MAX 60 +#define PRE_INFUSION_TIME_MIN 0 +#define PRE_INFUSION_TIME_MAX 60 +#define PRE_INFUSION_PAUSE_MIN 0 +#define PRE_INFUSION_PAUSE_MAX 60 +#define WEIGHTSETPOINT_MIN 0 +#define WEIGHTSETPOINT_MAX 500 +#define PID_KP_STEAM_MIN 0 +#define PID_KP_STEAM_MAX 500 +#define STANDBY_MODE_TIME_MIN 30 +#define STANDBY_MODE_TIME_MAX 120 +#define BACKFLUSH_CYCLES_MIN 2 +#define BACKFLUSH_CYCLES_MAX 20 +#define BACKFLUSH_FILL_TIME_MIN 5 +#define BACKFLUSH_FILL_TIME_MAX 20 +#define BACKFLUSH_FLUSH_TIME_MIN 5 +#define BACKFLUSH_FLUSH_TIME_MAX 20 +#define SHOT_TIMER_DISPLAY_DELAY_MIN 0 +#define SHOT_TIMER_DISPLAY_DELAY_MAX 60 diff --git a/src/display/displayCommon.h b/src/display/displayCommon.h index fe1f0c8aa..464111c7d 100644 --- a/src/display/displayCommon.h +++ b/src/display/displayCommon.h @@ -237,11 +237,11 @@ void displayLogo(String displaymessagetext, String displaymessagetext2) { * @brief display shot and flush timer */ bool displayShottimer() { - if (FEATURE_SHOTTIMER == 0) { + if (featureShotTimer == 0) { return false; } - if (machineState == kBrew || (millis() - lastBrewTimeMillis) < SHOTTIMERDISPLAYDELAY || machineState == kManualFlush) { + if (machineState == kBrew || (millis() - lastBrewTimeMillis) < (shotTimerDisplayDelay * 1000) || machineState == kManualFlush) { u8g2.clearBuffer(); if (machineState != kManualFlush) { @@ -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.) { + if (featureHeatingLogo > 0 && machineState == kPidNormal && (setpoint - temperature) > 5.) { // For status info u8g2.clearBuffer(); @@ -293,7 +293,7 @@ bool displayMachineState() { return true; } // Offline logo - else if (FEATURE_PIDOFF_LOGO == 1 && machineState == kPidDisabled) { + else if (featurePidOffLogo == 1 && machineState == kPidDisabled) { u8g2.clearBuffer(); u8g2.drawXBMP(38, 0, Off_Logo_width, Off_Logo_height, Off_Logo); u8g2.setCursor(0, 55); @@ -303,7 +303,7 @@ bool displayMachineState() { u8g2.sendBuffer(); return true; } - else if (FEATURE_PIDOFF_LOGO == 1 && machineState == kStandby) { + else if (featurePidOffLogo == 1 && machineState == kStandby) { u8g2.clearBuffer(); u8g2.drawXBMP(38, 0, Off_Logo_width, Off_Logo_height, Off_Logo); u8g2.setCursor(36, 55); diff --git a/src/display/displayRotateUpright.h b/src/display/displayRotateUpright.h index 7caa85c75..1f2e6e2f2 100644 --- a/src/display/displayRotateUpright.h +++ b/src/display/displayRotateUpright.h @@ -88,7 +88,7 @@ void displayEmergencyStop(void) { * @brief display shot timer */ bool displayShottimer() { - if (((timeBrewed > 0 && featureBrewControl == 0) || (featureBrewControl > 0 && currBrewState > kBrewIdle && currBrewState <= kBrewFinished)) && FEATURE_SHOTTIMER == 1) { + if (((timeBrewed > 0 && featureBrewControl == 0) || (featureBrewControl > 0 && currBrewState > kBrewIdle && currBrewState <= kBrewFinished)) && featureShotTimer == 1) { u8g2.clearBuffer(); // draw temp icon @@ -100,8 +100,8 @@ bool displayShottimer() { u8g2.sendBuffer(); return true; } - else if (FEATURE_SHOTTIMER == 1 && millis() >= lastBrewTimeMillis && // directly after creating lastbrewTimeMillis (happens when turning off the brew switch, case 43 in the code) should be started - lastBrewTimeMillis + SHOTTIMERDISPLAYDELAY >= millis() && // should run until millis() has caught up with SHOTTIMERDISPLAYDELAY, this can be used to control the display duration + else if (featureShotTimer == 1 && millis() >= lastBrewTimeMillis && // directly after creating lastbrewTimeMillis (happens when turning off the brew switch, case 43 in the code) should be started + lastBrewTimeMillis + (shotTimerDisplayDelay * 1000) >= millis() && // should run until millis() has caught up with shotTimerDisplayDelay, this can be used to control the display duration lastBrewTimeMillis < totalBrewTime) // if the totalBrewTime is reached automatically, nothing should be done, otherwise wrong time will be displayed because switch is pressed later than totalBrewTime { u8g2.clearBuffer(); diff --git a/src/display/displayTemplateMinimal.h b/src/display/displayTemplateMinimal.h index de8063b0c..3deb69de5 100644 --- a/src/display/displayTemplateMinimal.h +++ b/src/display/displayTemplateMinimal.h @@ -81,8 +81,8 @@ void printScreen() { // Brew time #if (FEATURE_BREWSWITCH == 1) if (featureBrewControl) { - // Shown brew time while machine is brewing and after the brewing during SHOTTIMERDISPLAYDELAY - if (machineState == kBrew || (millis() - lastBrewTimeMillis) < SHOTTIMERDISPLAYDELAY) { + // Shown brew time while machine is brewing and after the brewing during shotTimerDisplayDelay + if (machineState == kBrew || (millis() - lastBrewTimeMillis) < (shotTimerDisplayDelay * 1000)) { u8g2.setCursor(34, 44); u8g2.print(langstring_brew); u8g2.print(timeBrewed / 1000, 0); @@ -105,8 +105,8 @@ void printScreen() { // Brew Timer with optocoupler else { - // Shown brew time while machine is brewing and after the brewing during SHOTTIMERDISPLAYDELAY - if (machineState == kBrew || (millis() - lastBrewTimeMillis) < SHOTTIMERDISPLAYDELAY) { + // Shown brew time while machine is brewing and after the brewing during shotTimerDisplayDelay + if (machineState == kBrew || (millis() - lastBrewTimeMillis) < (shotTimerDisplayDelay * 1000)) { u8g2.setCursor(34, 44); u8g2.print(langstring_brew); u8g2.print(timeBrewed / 1000, 0); diff --git a/src/display/displayTemplateStandard.h b/src/display/displayTemplateStandard.h index bf837555e..1de766224 100644 --- a/src/display/displayTemplateStandard.h +++ b/src/display/displayTemplateStandard.h @@ -63,8 +63,8 @@ void printScreen() { #if (FEATURE_BREWSWITCH == 1) if (featureBrewControl) { - // Shown brew time while machine is brewing and after the brewing during SHOTTIMERDISPLAYDELAY - if (machineState == kBrew || (millis() - lastBrewTimeMillis) < SHOTTIMERDISPLAYDELAY) { + // Shown brew time while machine is brewing and after the brewing during shotTimerDisplayDelay + if (machineState == kBrew || (millis() - lastBrewTimeMillis) < (shotTimerDisplayDelay * 1000)) { u8g2.setFontMode(1); u8g2.setCursor(34, 36); u8g2.print(langstring_brew); @@ -92,8 +92,8 @@ void printScreen() { else { // Brew Timer with optocoupler - // Shown brew time while machine is brewing and after the brewing during SHOTTIMERDISPLAYDELAY - if (machineState == kBrew || (millis() - lastBrewTimeMillis) < SHOTTIMERDISPLAYDELAY) { + // Shown brew time while machine is brewing and after the brewing during shotTimerDisplayDelay + if (machineState == kBrew || (millis() - lastBrewTimeMillis) < (shotTimerDisplayDelay * 1000)) { u8g2.setCursor(34, 36); u8g2.print(langstring_brew); u8g2.setCursor(84, 36); diff --git a/src/embeddedWebserver.h b/src/embeddedWebserver.h index 3690977bf..e9f87ff0f 100644 --- a/src/embeddedWebserver.h +++ b/src/embeddedWebserver.h @@ -58,7 +58,7 @@ void serverSetup(); void setEepromWriteFcn(int (*fcnPtr)(void)); // editable vars are specified in main.cpp -#define EDITABLE_VARS_LEN 37 +#define EDITABLE_VARS_LEN 41 extern std::map editableVars; // EEPROM diff --git a/src/main.cpp b/src/main.cpp index c8df9cd62..d06d0d688 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -104,6 +104,10 @@ const boolean ota = OTA; // Display uint8_t oled_i2c = OLED_I2C; +uint8_t featureShotTimer = FEATURE_SHOT_TIMER; +double shotTimerDisplayDelay = SHOT_TIMER_DISPLAY_DELAY; +uint8_t featureHeatingLogo = FEATURE_HEATING_LOGO; +uint8_t featurePidOffLogo = FEATURE_PID_OFF_LOGO; // WiFi uint8_t wifiCredentialsSaved = 0; @@ -269,6 +273,10 @@ SysPara sysParaBackflushCycles(&backflushCycles, BACKFLUSH_CYCLES_MIN, BACK SysPara sysParaBackflushFillTime(&backflushFillTime, BACKFLUSH_FILL_TIME_MIN, BACKFLUSH_FILL_TIME_MAX, STO_ITEM_BACKFLUSH_FILL_TIME); SysPara sysParaBackflushFlushTime(&backflushFlushTime, BACKFLUSH_FLUSH_TIME_MIN, BACKFLUSH_FLUSH_TIME_MAX, STO_ITEM_BACKFLUSH_FLUSH_TIME); SysPara sysParaFeatureBrewControl(&featureBrewControl, 0, 1, STO_ITEM_FEATURE_BREW_CONTROL); +SysPara sysParaFeatureShotTimer(&featureShotTimer, 0, 1, STO_ITEM_FEATURE_SHOT_TIMER); +SysPara sysParaShotTimerDisplayDelay(&shotTimerDisplayDelay, SHOT_TIMER_DISPLAY_DELAY_MIN, SHOT_TIMER_DISPLAY_DELAY_MAX, STO_ITEM_SHOT_TIMER_DISPLAY_DELAY); +SysPara sysParaFeatureHeatingLogo(&featureHeatingLogo, 0, 1, STO_ITEM_FEATURE_HEATING_LOGO); +SysPara sysParaFeaturePidOffLogo(&featurePidOffLogo, 0, 1, STO_ITEM_FEATURE_PID_OFF_LOGO); // Other variables boolean emergencyStop = false; // Emergency stop if temperature is too high @@ -297,6 +305,7 @@ enum SectionNames { sBDSection, sBrewSection, sScaleSection, + sDisplaySection, sPowerSection, sOtherSection }; @@ -1245,7 +1254,7 @@ void setup() { editableVars["STANDBY_MODE_TIMER"] = {.displayName = F("Standby Time"), .hasHelpText = true, - .helpText = F("Time in minutes until the heater is turned off. Timer is reset by brew detection."), + .helpText = F("Time in minutes until the heater is turned off. Timer is reset by brew, manual flush, backflush and steam."), .type = kDouble, .section = sPowerSection, .position = 30, @@ -1254,7 +1263,7 @@ void setup() { .maxValue = STANDBY_MODE_TIME_MAX, .ptr = (void*)&standbyModeTime}; - editableVars["BREWCONTROL"] = {.displayName = F("Brew Control"), + editableVars["BREWCONTROL"] = {.displayName = F("Enable Brew Control"), .hasHelpText = true, .helpText = F("Enables brew-by-time or brew-by-weight"), .type = kUInt8, @@ -1314,8 +1323,51 @@ void setup() { .ptr = (void*)&scale2Calibration}; #endif + editableVars["SHOT_TIMER"] = {.displayName = F("Enable Shot Timer"), + .hasHelpText = true, + .helpText = "Enables a full screen shot and flush timer", + .type = kUInt8, + .section = sDisplaySection, + .position = 37, + .show = [] { return true; }, + .minValue = 0, + .maxValue = 1, + .ptr = (void*)&featureShotTimer}; + + editableVars["SHOT_TIMER_DISPLAY_DELAY"] = {.displayName = F("Shot Timer Display Delay (s)"), + .hasHelpText = true, + .helpText = "time in ms that shot timer will be shown after brew finished", + .type = kDouble, + .section = sDisplaySection, + .position = 38, + .show = [] { return true; }, + .minValue = SHOT_TIMER_DISPLAY_DELAY_MIN, + .maxValue = SHOT_TIMER_DISPLAY_DELAY_MAX, + .ptr = (void*)&shotTimerDisplayDelay}; + + editableVars["HEATING_LOGO"] = {.displayName = F("Enable Heating Logo"), + .hasHelpText = true, + .helpText = "full screen logo will be shown if temperature is 5°C below setpoint", + .type = kUInt8, + .section = sDisplaySection, + .position = 39, + .show = [] { return true; }, + .minValue = 0, + .maxValue = 1, + .ptr = (void*)&featureHeatingLogo}; + + editableVars["PID_OFF_LOGO"] = {.displayName = F("Enable ´PID Disabled´ Logo"), + .hasHelpText = true, + .helpText = "full screen logo will be shown if pid is disabled", + .type = kUInt8, + .section = sDisplaySection, + .position = 40, + .show = [] { return true; }, + .minValue = 0, + .maxValue = 1, + .ptr = (void*)&featurePidOffLogo}; editableVars["VERSION"] = { - .displayName = F("Version"), .hasHelpText = false, .helpText = "", .type = kCString, .section = sOtherSection, .position = 37, .show = [] { return false; }, .minValue = 0, .maxValue = 1, .ptr = (void*)sysVersion}; + .displayName = F("Version"), .hasHelpText = false, .helpText = "", .type = kCString, .section = sOtherSection, .position = 41, .show = [] { return false; }, .minValue = 0, .maxValue = 1, .ptr = (void*)sysVersion}; // when adding parameters, set EDITABLE_VARS_LEN to max of .position #if (FEATURE_PRESSURESENSOR == 1) @@ -1857,6 +1909,10 @@ int readSysParamsFromStorage(void) { if (sysParaBackflushFillTime.getStorage() != 0) return -1; if (sysParaBackflushFlushTime.getStorage() != 0) return -1; if (sysParaFeatureBrewControl.getStorage() != 0) return -1; + if (sysParaFeatureShotTimer.getStorage() != 0) return -1; + if (sysParaShotTimerDisplayDelay.getStorage() != 0) return -1; + if (sysParaFeatureHeatingLogo.getStorage() != 0) return -1; + if (sysParaFeaturePidOffLogo.getStorage() != 0) return -1; return 0; } @@ -1898,6 +1954,10 @@ int writeSysParamsToStorage(void) { if (sysParaBackflushFillTime.setStorage() != 0) return -1; if (sysParaBackflushFlushTime.setStorage() != 0) return -1; if (sysParaFeatureBrewControl.setStorage() != 0) return -1; + if (sysParaFeatureShotTimer.setStorage() != 0) return -1; + if (sysParaShotTimerDisplayDelay.setStorage() != 0) return -1; + if (sysParaFeatureHeatingLogo.setStorage() != 0) return -1; + if (sysParaFeaturePidOffLogo.setStorage() != 0) return -1; return storageCommit(); } diff --git a/src/storage.h b/src/storage.h index 0f613deb9..9bf4688e2 100644 --- a/src/storage.h +++ b/src/storage.h @@ -45,6 +45,10 @@ typedef enum { STO_ITEM_BACKFLUSH_FILL_TIME, // time in ms the pump is running during backflush STO_ITEM_BACKFLUSH_FLUSH_TIME, // time in ms the 3-way valve is open during backflush STO_ITEM_FEATURE_BREW_CONTROL, // enables function to control pump and solenoid valve + STO_ITEM_FEATURE_SHOT_TIMER, // enables full screen shot timer + STO_ITEM_SHOT_TIMER_DISPLAY_DELAY, // time in ms that shot timer will be shown after brew finished + STO_ITEM_FEATURE_HEATING_LOGO, // enables full screen logo if mashine is heating + STO_ITEM_FEATURE_PID_OFF_LOGO, // enables full screen logo if pid is switched off /* WHEN ADDING NEW ITEMS, THE FOLLOWING HAS TO BE UPDATED: * - storage structure: sto_data_t @@ -116,6 +120,10 @@ typedef struct __attribute__((packed)) { double backflushFillTimeMs; double backflushFlushTimeMs; uint8_t featureBrewControl; + uint8_t featureShotTimer; + double shotTimerDisplayDelay; + uint8_t featureHeatingLogo; + uint8_t featurePidOffLogo; } sto_data_t; @@ -168,6 +176,10 @@ static const sto_data_t itemDefaults PROGMEM = { BACKFLUSH_FILL_TIME, // STO_ITEM_BACKFLUSH_FILLTIME BACKFLUSH_FLUSH_TIME, // STO_ITEM_BACKFLUSH_FLUSHTIME FEATURE_BREW_CONTROL, // STO_ITEM_FEATURE_BREW_CONTROL + FEATURE_SHOT_TIMER, // STO_ITEM_FEATURE_SHOT_TIMER + SHOT_TIMER_DISPLAY_DELAY, // STO_ITEM_SHOT_TIMER_DISPLAY_DELAY + FEATURE_HEATING_LOGO, // STO_ITEM_FEATURE_HEATING_LOGO + FEATURE_PID_OFF_LOGO, // STO_ITEM_FEATURE_PID_OFF_LOGO }; /** @@ -355,6 +367,26 @@ static inline int32_t getItemAddr(sto_item_id_t itemId, uint16_t* maxItemSize = size = STRUCT_MEMBER_SIZE(sto_data_t, featureBrewControl); break; + case STO_ITEM_FEATURE_SHOT_TIMER: + addr = offsetof(sto_data_t, featureShotTimer); + size = STRUCT_MEMBER_SIZE(sto_data_t, featureShotTimer); + break; + + case STO_ITEM_SHOT_TIMER_DISPLAY_DELAY: + addr = offsetof(sto_data_t, shotTimerDisplayDelay); + size = STRUCT_MEMBER_SIZE(sto_data_t, shotTimerDisplayDelay); + break; + + case STO_ITEM_FEATURE_HEATING_LOGO: + addr = offsetof(sto_data_t, featureHeatingLogo); + size = STRUCT_MEMBER_SIZE(sto_data_t, featureHeatingLogo); + break; + + case STO_ITEM_FEATURE_PID_OFF_LOGO: + addr = offsetof(sto_data_t, featurePidOffLogo); + size = STRUCT_MEMBER_SIZE(sto_data_t, featurePidOffLogo); + break; + default: LOGF(ERROR, "invalid item ID %i!", itemId); addr = -1; diff --git a/src/userConfig_sample.h b/src/userConfig_sample.h index 657e7c8e3..07b800a9c 100644 --- a/src/userConfig_sample.h +++ b/src/userConfig_sample.h @@ -29,18 +29,14 @@ enum MACHINE { #define MACHINEID RancilioSilvia // Machine type (see enum MACHINE) // Display -#define OLED_DISPLAY 2 // 0 = deactivated, 1 = SH1106 (e.g. 1.3 "128x64), 2 = SSD1306 (e.g. 0.96" 128x64), 3 = SH1106_126x64_SPI -#define OLED_I2C 0x3C // I2C address for OLED, 0x3C by default -#define DISPLAYTEMPLATE 3 // 1 = Standard display template, 2 = Minimal template, 3 = only temperature, 4 = scale template, 20 = vertical display (see git Handbook for further information) -#define DISPLAYROTATE U8G2_R0 // rotate display clockwise: U8G2_R0 = no rotation; U8G2_R1 = 90°; U8G2_R2 = 180°; U8G2_R3 = 270° -#define SCREEN_WIDTH 128 // OLED display width, in pixels -#define SCREEN_HEIGHT 64 // OLED display height, in pixels -#define FEATURE_SHOTTIMER 1 // 0 = deactivated, 1 = activated (with weight if FEATURE_SCALE activated) -#define FEATURE_HEATINGLOGO 1 // 0 = deactivated, 1 = activated -#define FEATURE_PIDOFF_LOGO 1 // 0 = deactivated, 1 = activated -#define SHOTTIMERDISPLAYDELAY 3000 // time in ms that shot timer will be shown after brew finished - -#define LANGUAGE 0 // LANGUAGE = 0 (DE), LANGUAGE = 1 (EN), LANGUAGE = 2 (ES) +#define OLED_DISPLAY 2 // 0 = deactivated, 1 = SH1106 (e.g. 1.3 "128x64), 2 = SSD1306 (e.g. 0.96" 128x64), 3 = SH1106_126x64_SPI +#define OLED_I2C 0x3C // I2C address for OLED, 0x3C by default +#define DISPLAYTEMPLATE 3 // 1 = Standard display template, 2 = Minimal template, 3 = only temperature, 4 = scale template, 20 = vertical display (see git Handbook for further information) +#define DISPLAYROTATE U8G2_R0 // rotate display clockwise: U8G2_R0 = no rotation; U8G2_R1 = 90°; U8G2_R2 = 180°; U8G2_R3 = 270° +#define SCREEN_WIDTH 128 // OLED display width, in pixels +#define SCREEN_HEIGHT 64 // OLED display height, in pixels + +#define LANGUAGE 0 // LANGUAGE = 0 (DE), LANGUAGE = 1 (EN), LANGUAGE = 2 (ES) // Connectivity #define CONNECTMODE 1 // 0 = offline 1 = WIFI-MODE From f39a2c907142a504fd54ab58a942a03398197524 Mon Sep 17 00:00:00 2001 From: Lorenz Uhlig <98092139+LoQue90@users.noreply.github.com> Date: Fri, 18 Oct 2024 01:17:23 +0200 Subject: [PATCH 21/23] rework scale shottimer cleanup in main.cpp adding translations rename some scale vars to be more precice do not show weight in full screen shot timer during manual flush add weightBrewed to MQTT sensors and HA auto discovery --- src/brewHandler.h | 10 +-- src/display/displayCommon.h | 26 +++--- src/display/displayTemplateScale.h | 104 ++++++++++++++++-------- src/display/displayTemplateStandard.h | 112 +++++++++++++------------- src/languages.h | 6 ++ src/main.cpp | 26 +++--- src/mqtt.h | 6 +- src/scaleHandler.h | 12 +-- 8 files changed, 173 insertions(+), 129 deletions(-) diff --git a/src/brewHandler.h b/src/brewHandler.h index f32edf7c9..403550376 100644 --- a/src/brewHandler.h +++ b/src/brewHandler.h @@ -6,9 +6,9 @@ */ // TODO: // Flush Timer configurable and seperated from shottimer? -// check all Scale stuff // show heating logo if steam temp isn´t reached? // show sections on website only if needed +// add pressure to shot timer? #pragma once @@ -76,9 +76,9 @@ boolean scaleCalibrationOn = 0; boolean scaleTareOn = 0; int shottimerCounter = 10; float calibrationValue = SCALE_CALIBRATION_FACTOR; // use calibration example to get value -float weight = 0; // value from HX711 -float weightPreBrew = 0; // value of scale before wrew started -float weightBrew = 0; // weight value of brew +float currWeight = 0; // value from HX711 +float weightPreBrew = 0; // value of scale before brew started +float weightBrewed = 0; // weight value of brew float scaleDelayValue = 2.5; // value in gramm that takes still flows onto the scale after brew is stopped bool scaleFailure = false; const unsigned long intervalWeight = 200; // weight scale @@ -248,7 +248,7 @@ bool brew() { } #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)) { + else if (((FEATURE_SCALE == 1) && (weightBrewed > weightSetpoint)) && (weightSetpoint > 0)) { LOG(INFO, "Brew reached weight target"); currBrewState = kBrewFinished; } diff --git a/src/display/displayCommon.h b/src/display/displayCommon.h index 464111c7d..af1f3644e 100644 --- a/src/display/displayCommon.h +++ b/src/display/displayCommon.h @@ -246,24 +246,24 @@ bool displayShottimer() { if (machineState != kManualFlush) { u8g2.drawXBMP(-1, 11, Brew_Cup_Logo_width, Brew_Cup_Logo_height, Brew_Cup_Logo); +#if (FEATURE_SCALE == 1) + u8g2.setFont(u8g2_font_profont22_tf); + u8g2.setCursor(64, 15); + u8g2.print(timeBrewed / 1000, 1); + u8g2.print("s"); + u8g2.setCursor(64, 38); + u8g2.print(weightBrewed, 1); + u8g2.print("g"); + u8g2.setFont(u8g2_font_profont11_tf); +#else + displayBrewtime(48, 25, timeBrewed); +#endif } else { u8g2.drawXBMP(0, 12, Manual_Flush_Logo_width, Manual_Flush_Logo_height, Manual_Flush_Logo); + displayBrewtime(48, 25, timeBrewed); } -#if (FEATURE_SCALE == 1) - u8g2.setFont(u8g2_font_profont22_tf); - u8g2.setCursor(64, 15); - u8g2.print(timeBrewed / 1000, 1); - u8g2.print("s"); - u8g2.setCursor(64, 38); - u8g2.print(weightBrew, 1); - u8g2.print("g"); - u8g2.setFont(u8g2_font_profont11_tf); -#else - displayBrewtime(48, 25, timeBrewed); -#endif - displayWaterIcon(119, 1); u8g2.sendBuffer(); return true; diff --git a/src/display/displayTemplateScale.h b/src/display/displayTemplateScale.h index 5120dd2bc..e27646eb6 100644 --- a/src/display/displayTemplateScale.h +++ b/src/display/displayTemplateScale.h @@ -51,53 +51,91 @@ void printScreen() { u8g2.print("/"); u8g2.print(setpoint, 1); + /** + * @brief Shot timer for scale + * + * If scale has an error show fault on the display otherwise show current reading of the scale + * if brew is running show current brew time and current brew weight + * if brewControl is enabled and time or weight target is set show targets + * if brewControl is enabled show flush time during manualFlush + * if FEATURE_PRESSURESENSOR is enabled show current pressure during brew + * if brew is finished show brew values for shotTimerDisplayDelay + */ + + // Show current weight if scale has no error u8g2.setCursor(32, 26); - u8g2.print("W: "); - + u8g2.print(langstring_weight); + u8g2.setCursor(82, 26); if (scaleFailure) { u8g2.print("fault"); } else { - if (machineState == kBrew) { - u8g2.print(weightBrew, 0); - } - else { - u8g2.print(weight, 0); - } - - if (weightSetpoint > 0) { - u8g2.print("/"); - u8g2.print(weightSetpoint, 0); - } - - u8g2.print(" ("); - u8g2.print(weightBrew, 1); - u8g2.print(")"); + u8g2.print(currWeight, 0); + u8g2.print(" g"); } - // Brew - u8g2.setCursor(32, 36); - u8g2.print("t: "); - u8g2.print(timeBrewed / 1000, 0); - - if (FEATURE_BREWCONTROL == 0) { - u8g2.print("/"); - u8g2.print(brewtimesoftware, 0); + if (featureBrewControl) { + // Shown brew time and weight while machine is brewing and after the brewing during shotTimerDisplayDelay + if (machineState == kBrew || (millis() - lastBrewTimeMillis) < (shotTimerDisplayDelay * 1000)) { + + // weight + u8g2.setCursor(32, 26); + u8g2.print(langstring_weight); + u8g2.setCursor(82, 26); + u8g2.print(weightBrewed, 0); + + if (weightSetpoint > 0) { + u8g2.print("/"); + u8g2.print(weightSetpoint, 0); + u8g2.print(" g"); + } + // time + u8g2.setCursor(32, 36); + u8g2.print(langstring_brew); + u8g2.setCursor(82, 36); + u8g2.print(timeBrewed / 1000, 0); + + if (brewTime > 0) { + u8g2.print("/"); + u8g2.print(totalBrewTime / 1000, 0); + u8g2.print(" s"); + } + } + // Shown flush time while machine is flushing + if (machineState == kManualFlush) { + u8g2.setDrawColor(0); + u8g2.drawBox(32, 26, 100, 40); + u8g2.setDrawColor(1); + u8g2.setCursor(32, 26); + u8g2.print(langstring_manual_flush); + u8g2.setCursor(82, 26); + u8g2.print(timeBrewed / 1000, 0); + u8g2.print(" s"); + } } else { - if (brewTime > 0) { - u8g2.print("/"); - u8g2.print(totalBrewTime / 1000, 0); + // Brew Timer with optocoupler + + // Shown brew time and weight while machine is brewing and after the brewing during shotTimerDisplayDelay + if (machineState == kBrew || (millis() - lastBrewTimeMillis) < (shotTimerDisplayDelay * 1000)) { + // weight + u8g2.setCursor(32, 26); + u8g2.print(langstring_weight); + u8g2.setCursor(82, 26); + u8g2.print(weightBrewed, 0); + u8g2.print(" g"); + // time + u8g2.setCursor(32, 36); + u8g2.print(langstring_brew); + u8g2.setCursor(82, 36); + u8g2.print(timeBrewed / 1000, 0); + u8g2.print(" s"); } - - u8g2.print(" ("); - u8g2.print(lastBrewTime / 1000, 1); - u8g2.print(")"); } #if (FEATURE_PRESSURESENSOR == 1) u8g2.setCursor(32, 46); - u8g2.print("P: "); + u8g2.print(langstring_pressure); u8g2.print(inputPressure, 1); #endif diff --git a/src/display/displayTemplateStandard.h b/src/display/displayTemplateStandard.h index 1de766224..c26b4ded0 100644 --- a/src/display/displayTemplateStandard.h +++ b/src/display/displayTemplateStandard.h @@ -59,78 +59,74 @@ void printScreen() { drawTemperaturebar(8, 50, 30); } -// Brew time +// Brew and flush time #if (FEATURE_BREWSWITCH == 1) if (featureBrewControl) { // Shown brew time while machine is brewing and after the brewing during shotTimerDisplayDelay - if (machineState == kBrew || (millis() - lastBrewTimeMillis) < (shotTimerDisplayDelay * 1000)) { - u8g2.setFontMode(1); - u8g2.setCursor(34, 36); - u8g2.print(langstring_brew); - u8g2.setCursor(84, 36); - u8g2.print(timeBrewed / 1000, 0); - u8g2.print("/"); - u8g2.print(totalBrewTime / 1000, 0); - u8g2.print(" s"); - } - - // Flush time - - // Shown flush time while machine is flushing - if (machineState == kManualFlush) { - u8g2.setDrawColor(0); - u8g2.drawBox(34, 36, 100, 10); - u8g2.setDrawColor(1); - u8g2.setCursor(34, 36); - u8g2.print(langstring_manual_flush); - u8g2.setCursor(84, 36); - u8g2.print(timeBrewed / 1000, 0); - u8g2.print(" s"); - } + u8g2.setCursor(34, 36); + u8g2.print(langstring_brew); + u8g2.setCursor(84, 36); + u8g2.print(timeBrewed / 1000, 0); + u8g2.print("/"); + u8g2.print(totalBrewTime / 1000, 0); + u8g2.print(" s"); } - else { - // Brew Timer with optocoupler - // Shown brew time while machine is brewing and after the brewing during shotTimerDisplayDelay - if (machineState == kBrew || (millis() - lastBrewTimeMillis) < (shotTimerDisplayDelay * 1000)) { - u8g2.setCursor(34, 36); - u8g2.print(langstring_brew); - u8g2.setCursor(84, 36); - u8g2.print(timeBrewed / 1000, 0); - u8g2.print(" s"); - } + // Shown flush time while machine is flushing + if (machineState == kManualFlush) { + u8g2.setDrawColor(0); + u8g2.drawBox(34, 36, 100, 10); + u8g2.setDrawColor(1); + u8g2.setCursor(34, 36); + u8g2.print(langstring_manual_flush); + u8g2.setCursor(84, 36); + u8g2.print(timeBrewed / 1000, 0); + u8g2.print(" s"); + } +} +else { + // Brew Timer with optocoupler + + // Shown brew time while machine is brewing and after the brewing during shotTimerDisplayDelay + if (machineState == kBrew || (millis() - lastBrewTimeMillis) < (shotTimerDisplayDelay * 1000)) { + u8g2.setCursor(34, 36); + u8g2.print(langstring_brew); + u8g2.setCursor(84, 36); + u8g2.print(timeBrewed / 1000, 0); + u8g2.print(" s"); } +} #endif - // PID values over heat bar - u8g2.setCursor(38, 47); +// PID values over heat bar +u8g2.setCursor(38, 47); - u8g2.print(bPID.GetKp(), 0); - u8g2.print("|"); +u8g2.print(bPID.GetKp(), 0); +u8g2.print("|"); - if (bPID.GetKi() != 0) { - u8g2.print(bPID.GetKp() / bPID.GetKi(), 0); - } - else { - u8g2.print("0"); - } +if (bPID.GetKi() != 0) { + u8g2.print(bPID.GetKp() / bPID.GetKi(), 0); +} +else { + u8g2.print("0"); +} - u8g2.print("|"); - u8g2.print(bPID.GetKd() / bPID.GetKp(), 0); - u8g2.setCursor(96, 47); +u8g2.print("|"); +u8g2.print(bPID.GetKd() / bPID.GetKp(), 0); +u8g2.setCursor(96, 47); - if (pidOutput < 99) { - u8g2.print(pidOutput / 10, 1); - } - else { - u8g2.print(pidOutput / 10, 0); - } +if (pidOutput < 99) { + u8g2.print(pidOutput / 10, 1); +} +else { + u8g2.print(pidOutput / 10, 0); +} - u8g2.print("%"); +u8g2.print("%"); - // Show heater output in % - displayProgressbar(pidOutput / 10, 30, 60, 98); +// Show heater output in % +displayProgressbar(pidOutput / 10, 30, 60, 98); - u8g2.sendBuffer(); +u8g2.sendBuffer(); } diff --git a/src/languages.h b/src/languages.h index 9bde884b6..6a5327c2b 100644 --- a/src/languages.h +++ b/src/languages.h @@ -13,7 +13,9 @@ static const char* langstring_set_temp = "Soll: "; static const char* langstring_current_temp = "Ist: "; static const char* langstring_brew = "Bezug: "; +static const char* langstring_weight = "Gewicht: "; static const char* langstring_manual_flush = "Spuelen: "; +static const char* langstring_pressure = "Druck: "; static const char* langstring_uptime = "Uptime: "; #endif #if (DISPLAYTEMPLATE >= 20) // vertical templates @@ -39,7 +41,9 @@ static const char* langstring_backflush_finish = "um zu beenden..."; static const char* langstring_set_temp = "Set: "; static const char* langstring_current_temp = "Temp: "; static const char* langstring_brew = "Brew: "; +static const char* langstring_weight = "Weight: "; static const char* langstring_manual_flush = "Flush: "; +static const char* langstring_pressure = "Pressure: "; static const char* langstring_uptime = "Uptime: "; #endif #if (DISPLAYTEMPLATE >= 20) // vertical templates @@ -66,7 +70,9 @@ static const char* langstring_backflush_finish = "to finish..."; static const char* langstring_set_temp = "Obj: "; static const char* langstring_current_temp = "T: "; static const char* langstring_brew = "Brew: "; +static const char* langstring_weight = "Peso: "; static const char* langstring_manual_flush = "Fregar: "; +static const char* langstring_pressure = "Presión: "; static const char* langstring_uptime = "Uptime: "; #endif #if (DISPLAYTEMPLATE >= 20) // vertical templates diff --git a/src/main.cpp b/src/main.cpp index d06d0d688..d599df85d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -47,6 +47,11 @@ #include "defaults.h" #include "userConfig.h" // needs to be configured by the user +// Version of userConfig need to match, checked by preprocessor +#if (FW_VERSION != USR_FW_VERSION) || (FW_SUBVERSION != USR_FW_SUBVERSION) || (FW_HOTFIX != USR_FW_HOTFIX) +#error Version of userConfig file and main.cpp need to match! +#endif + hw_timer_t* timer = NULL; #if (FEATURE_PRESSURESENSOR == 1) @@ -68,11 +73,6 @@ hw_timer_t* timer = NULL; #include #endif -// Version of userConfig need to match, checked by preprocessor -#if (FW_VERSION != USR_FW_VERSION) || (FW_SUBVERSION != USR_FW_SUBVERSION) || (FW_HOTFIX != USR_FW_HOTFIX) -#error Version of userConfig file and main.cpp need to match! -#endif - MACHINE machine = (enum MACHINE)MACHINEID; #define HIGH_ACCURACY @@ -179,15 +179,12 @@ void updateStandbyTimer(void); void resetStandbyTimer(void); // system parameters -uint8_t pidON = 0; // 1 = control loop in closed loop +uint8_t pidON = 0; // 1 = control loop in closed loop +uint8_t usePonM = 0; // 1 = use PonM for cold start PID, 0 = use normal PID for cold start double brewSetpoint = SETPOINT; double brewTempOffset = TEMPOFFSET; double setpoint = brewSetpoint; double steamSetpoint = STEAMSETPOINT; -float scaleCalibration = SCALE_CALIBRATION_FACTOR; -float scale2Calibration = SCALE_CALIBRATION_FACTOR; -float scaleKnownWeight = SCALE_KNOWN_WEIGHT; -uint8_t usePonM = 0; // 1 = use PonM for cold start PID, 0 = use normal PID for cold start double steamKp = STEAMKP; double startKp = STARTKP; double startTn = STARTTN; @@ -196,6 +193,10 @@ double aggTn = AGGTN; double aggTv = AGGTV; double aggIMax = AGGIMAX; +// Scale +float scaleCalibration = SCALE_CALIBRATION_FACTOR; +float scale2Calibration = SCALE_CALIBRATION_FACTOR; +float scaleKnownWeight = SCALE_KNOWN_WEIGHT; double weightSetpoint = SCALE_WEIGHTSETPOINT; // PID - values for offline brew detection @@ -1163,7 +1164,7 @@ void setup() { .type = kDouble, .section = sBrewSection, .position = 21, - .show = [] { return true && FEATURE_SCALE == 1; }, + .show = [] { return true && FEATURE_SCALE == 1 && featureBrewControl == 1; }, .minValue = WEIGHTSETPOINT_MIN, .maxValue = WEIGHTSETPOINT_MAX, .ptr = (void*)&weightSetpoint}; @@ -1425,7 +1426,8 @@ void setup() { mqttVars["scaleTareOn"] = [] { return &editableVars.at("TARE_ON"); }; mqttVars["scaleCalibrationOn"] = [] { return &editableVars.at("CALIBRATION_ON"); }; - mqttSensors["currentWeight"] = [] { return weight; }; + mqttSensors["currWeight"] = [] { return currWeight; }; + mqttSensors["weightBrewed"] = [] { return weightBrewed; }; #endif #if FEATURE_PRESSURESENSOR == 1 diff --git a/src/mqtt.h b/src/mqtt.h index 83192c247..bdd8f90db 100644 --- a/src/mqtt.h +++ b/src/mqtt.h @@ -555,14 +555,16 @@ int sendHASSIODiscoveryMsg() { #if FEATURE_SCALE == 1 - DiscoveryObject currentWeight = GenerateSensorDevice("currentWeight", "Weight", "g", "weight"); + DiscoveryObject currWeight = GenerateSensorDevice("currWeight", "Weight", "g", "weight"); + DiscoveryObject weightBrewed = GenerateSensorDevice("weightBrewed", "Weight brewed", "g", "weight"); DiscoveryObject scaleCalibrateButton = GenerateButtonDevice("scaleCalibrationOn", "Calibrate Scale"); DiscoveryObject scaleTareButton = GenerateButtonDevice("scaleTareOn", "Tare Scale"); DiscoveryObject weightSetpoint = GenerateNumberDevice("weightSetpoint", "Weight setpoint", WEIGHTSETPOINT_MIN, WEIGHTSETPOINT_MAX, 0.1, "g"); - discoveryObjects.push_back(currentWeight); + discoveryObjects.push_back(currWeight); + discoveryObjects.push_back(weightBrewed); discoveryObjects.push_back(scaleCalibrateButton); discoveryObjects.push_back(scaleTareButton); discoveryObjects.push_back(weightSetpoint); diff --git a/src/scaleHandler.h b/src/scaleHandler.h index 906f2ba78..41ce32c3a 100644 --- a/src/scaleHandler.h +++ b/src/scaleHandler.h @@ -78,9 +78,9 @@ void checkWeight() { } #if SCALE_TYPE == 0 - weight = w1 + w2; + currWeight = w1 + w2; #else - weight = w1; + currWeight = w1; #endif if (scaleCalibrationOn) { @@ -177,24 +177,24 @@ void shottimerscale() { case 10: // waiting step for brew switch turning on if (preinfusionPause == 0 || preinfusion == 0) { if (timeBrewed > 0) { - weightPreBrew = weight; + weightPreBrew = currWeight; shottimerCounter = 20; } } else { if (timeBrewed > preinfusion * 1000) { - weightPreBrew = weight; + weightPreBrew = currWeight; shottimerCounter = 20; } else if (timeBrewed > 0) { - weightBrew = 0; + weightBrewed = 0; } } break; case 20: - weightBrew = weight - weightPreBrew; + weightBrewed = currWeight - weightPreBrew; if (timeBrewed == 0) { shottimerCounter = 10; From 2d1770a213f3b3dbc7c5c1497ccf9508f8f1bd57 Mon Sep 17 00:00:00 2001 From: Lorenz Uhlig <98092139+LoQue90@users.noreply.github.com> Date: Sun, 27 Oct 2024 23:18:54 +0100 Subject: [PATCH 22/23] move backflush settings into own section +cleanup +bugfixes --- data/js/app.js | 3 +- src/display/displayTemplateMinimal.h | 5 +- src/display/displayTemplateStandard.h | 106 +++++++++++++------------- src/display/displayTemplateUpright.h | 4 - src/main.cpp | 70 ++++++++++------- 5 files changed, 97 insertions(+), 91 deletions(-) diff --git a/data/js/app.js b/data/js/app.js index 6fc7e456f..c4222215b 100644 --- a/data/js/app.js +++ b/data/js/app.js @@ -79,7 +79,8 @@ const vueApp = Vue.createApp({ 3: 'Brew Control', 4: 'Scale Parameters', 5: 'Display Settings', - 6: 'Power Settings' + 6: 'Maintenance', + 7: 'Power Settings' } return sectionNames[sectionId] diff --git a/src/display/displayTemplateMinimal.h b/src/display/displayTemplateMinimal.h index 3deb69de5..78753f8a8 100644 --- a/src/display/displayTemplateMinimal.h +++ b/src/display/displayTemplateMinimal.h @@ -90,8 +90,6 @@ void printScreen() { u8g2.print(totalBrewTime / 1000, 0); } - // Flush time - // Shown flush time while machine is flushing if (machineState == kManualFlush) { u8g2.setDrawColor(0); @@ -102,9 +100,8 @@ void printScreen() { u8g2.print(timeBrewed / 1000, 0); } } - - // Brew Timer with optocoupler else { + // Brew Timer with optocoupler // Shown brew time while machine is brewing and after the brewing during shotTimerDisplayDelay if (machineState == kBrew || (millis() - lastBrewTimeMillis) < (shotTimerDisplayDelay * 1000)) { u8g2.setCursor(34, 44); diff --git a/src/display/displayTemplateStandard.h b/src/display/displayTemplateStandard.h index c26b4ded0..0e77da66a 100644 --- a/src/display/displayTemplateStandard.h +++ b/src/display/displayTemplateStandard.h @@ -64,69 +64,69 @@ void printScreen() { if (featureBrewControl) { // Shown brew time while machine is brewing and after the brewing during shotTimerDisplayDelay - u8g2.setCursor(34, 36); - u8g2.print(langstring_brew); - u8g2.setCursor(84, 36); - u8g2.print(timeBrewed / 1000, 0); - u8g2.print("/"); - u8g2.print(totalBrewTime / 1000, 0); - u8g2.print(" s"); + if (machineState == kBrew || (millis() - lastBrewTimeMillis) < (shotTimerDisplayDelay * 1000)) { + u8g2.setCursor(34, 36); + u8g2.print(langstring_brew); + u8g2.setCursor(84, 36); + u8g2.print(timeBrewed / 1000, 0); + u8g2.print("/"); + u8g2.print(totalBrewTime / 1000, 0); + u8g2.print(" s"); + } + // Shown flush time while machine is flushing + if (machineState == kManualFlush) { + u8g2.setDrawColor(0); + u8g2.drawBox(34, 36, 100, 10); + u8g2.setDrawColor(1); + u8g2.setCursor(34, 36); + u8g2.print(langstring_manual_flush); + u8g2.setCursor(84, 36); + u8g2.print(timeBrewed / 1000, 0); + u8g2.print(" s"); + } } + else { + // Brew Timer with optocoupler - // Shown flush time while machine is flushing - if (machineState == kManualFlush) { - u8g2.setDrawColor(0); - u8g2.drawBox(34, 36, 100, 10); - u8g2.setDrawColor(1); - u8g2.setCursor(34, 36); - u8g2.print(langstring_manual_flush); - u8g2.setCursor(84, 36); - u8g2.print(timeBrewed / 1000, 0); - u8g2.print(" s"); - } -} -else { - // Brew Timer with optocoupler - - // Shown brew time while machine is brewing and after the brewing during shotTimerDisplayDelay - if (machineState == kBrew || (millis() - lastBrewTimeMillis) < (shotTimerDisplayDelay * 1000)) { - u8g2.setCursor(34, 36); - u8g2.print(langstring_brew); - u8g2.setCursor(84, 36); - u8g2.print(timeBrewed / 1000, 0); - u8g2.print(" s"); + // Shown brew time while machine is brewing and after the brewing during shotTimerDisplayDelay + if (machineState == kBrew || (millis() - lastBrewTimeMillis) < (shotTimerDisplayDelay * 1000)) { + u8g2.setCursor(34, 36); + u8g2.print(langstring_brew); + u8g2.setCursor(84, 36); + u8g2.print(timeBrewed / 1000, 0); + u8g2.print(" s"); + } } -} #endif -// PID values over heat bar -u8g2.setCursor(38, 47); + // PID values over heat bar + u8g2.setCursor(38, 47); -u8g2.print(bPID.GetKp(), 0); -u8g2.print("|"); + u8g2.print(bPID.GetKp(), 0); + u8g2.print("|"); -if (bPID.GetKi() != 0) { - u8g2.print(bPID.GetKp() / bPID.GetKi(), 0); -} -else { - u8g2.print("0"); -} + if (bPID.GetKi() != 0) { + u8g2.print(bPID.GetKp() / bPID.GetKi(), 0); + } + else { + u8g2.print("0"); + } -u8g2.print("|"); -u8g2.print(bPID.GetKd() / bPID.GetKp(), 0); -u8g2.setCursor(96, 47); + u8g2.print("|"); + u8g2.print(bPID.GetKd() / bPID.GetKp(), 0); + u8g2.setCursor(96, 47); -if (pidOutput < 99) { - u8g2.print(pidOutput / 10, 1); -} -else { - u8g2.print(pidOutput / 10, 0); -} + if (pidOutput < 99) { + u8g2.print(pidOutput / 10, 1); + } + else { + u8g2.print(pidOutput / 10, 0); + } -u8g2.print("%"); + u8g2.print("%"); -// Show heater output in % -displayProgressbar(pidOutput / 10, 30, 60, 98); + // Show heater output in % + displayProgressbar(pidOutput / 10, 30, 60, 98); -u8g2.sendBuffer(); + u8g2.sendBuffer(); } diff --git a/src/display/displayTemplateUpright.h b/src/display/displayTemplateUpright.h index ffc27bc51..107925aed 100644 --- a/src/display/displayTemplateUpright.h +++ b/src/display/displayTemplateUpright.h @@ -99,8 +99,6 @@ void printScreen() { u8g2.print(" s"); } - // Flush time - // Shown flush time while machine is flushing if (machineState == kManualFlush) { u8g2.setDrawColor(0); @@ -113,9 +111,7 @@ void printScreen() { } } else { - // Brew Timer with optocoupler - // Shown brew time while machine is brewing and after the brewing during SHOTTIMERDISPLAYDELAY if (machineState == kBrew || (millis() - lastBrewTimeMillis) < SHOTTIMERDISPLAYDELAY) { u8g2.setCursor(1, 34); diff --git a/src/main.cpp b/src/main.cpp index d599df85d..7c4af5c04 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -303,10 +303,11 @@ double previousInput = 0; enum SectionNames { sPIDSection, sTempSection, - sBDSection, + sBrewPidSection, sBrewSection, sScaleSection, sDisplaySection, + sMaintenanceSection, sPowerSection, sOtherSection }; @@ -733,7 +734,6 @@ void handleMachineState() { case kPidDisabled: if (pidON == 1) { - // Enter regular PID operations machineState = kPidNormal; } @@ -777,29 +777,43 @@ void handleMachineState() { #if OLED_DISPLAY != 0 u8g2.setPowerSave(0); #endif + machineState = kBrew; + } - if (manualFlush()) { - pidON = 1; - resetStandbyTimer(); + if (manualFlush()) { + pidON = 1; + resetStandbyTimer(); #if OLED_DISPLAY != 0 - u8g2.setPowerSave(0); + u8g2.setPowerSave(0); #endif - } - - if (tempSensor->hasError()) { - machineState = kSensorError; - } - break; + machineState = kManualFlush; + } - case kSensorError: - machineState = kSensorError; - break; + if (backflushOn) { + resetStandbyTimer(); +#if OLED_DISPLAY != 0 + u8g2.setPowerSave(0); +#endif + machineState = kBackflush; + } - case kEepromError: - machineState = kEepromError; - break; + if (tempSensor->hasError()) { +#if OLED_DISPLAY != 0 + u8g2.setPowerSave(0); +#endif + machineState = kSensorError; } + break; + + case kSensorError: + machineState = kSensorError; + break; + + case kEepromError: + machineState = kEepromError; + break; } + if (machineState != lastmachinestate) { printMachineState(); lastmachinestate = machineState; @@ -1129,7 +1143,7 @@ void setup() { .hasHelpText = true, .helpText = "Number of cycles of filling and flushing during a backflush", .type = kInteger, - .section = sBrewSection, + .section = sMaintenanceSection, .position = 18, .show = [] { return true && featureBrewControl == 1; }, .minValue = BACKFLUSH_CYCLES_MIN, @@ -1140,7 +1154,7 @@ void setup() { .hasHelpText = true, .helpText = "Time in seconds the pump is running during one backflush cycle", .type = kDouble, - .section = sBrewSection, + .section = sMaintenanceSection, .position = 19, .show = [] { return true && featureBrewControl == 1; }, .minValue = BACKFLUSH_FILL_TIME_MIN, @@ -1151,7 +1165,7 @@ void setup() { .hasHelpText = true, .helpText = "Time in seconds the selenoid valve stays open during one backflush cycle", .type = kDouble, - .section = sBrewSection, + .section = sMaintenanceSection, .position = 20, .show = [] { return true && featureBrewControl == 1; }, .minValue = BACKFLUSH_FLUSH_TIME_MIN, @@ -1176,7 +1190,7 @@ void setup() { "high brew temperatures with boiler machines like Rancilio " "Silvia. Set to 0 for thermoblock machines."), .type = kDouble, - .section = sBDSection, + .section = sBrewPidSection, .position = 22, .show = [] { return true; }, .minValue = BREW_PID_DELAY_MIN, @@ -1187,7 +1201,7 @@ void setup() { .hasHelpText = true, .helpText = F("Use separate PID parameters while brew is running"), .type = kUInt8, - .section = sBDSection, + .section = sBrewPidSection, .position = 23, .show = [] { return true && FEATURE_BREWSWITCH == 1; }, .minValue = 0, @@ -1205,7 +1219,7 @@ void setup() { "installation-eines-temperatursensors-in-silvia-bruehgruppe.111093/" "#post-1453641' target='_blank'>Details)"), .type = kDouble, - .section = sBDSection, + .section = sBrewPidSection, .position = 24, .show = [] { return true && FEATURE_BREWSWITCH == 1 && useBDPID; }, .minValue = PID_KP_BD_MIN, @@ -1217,7 +1231,7 @@ void setup() { .helpText = F("Integral time constant (in seconds) for the PID when " "brewing has been detected."), .type = kDouble, - .section = sBDSection, + .section = sBrewPidSection, .position = 25, .show = [] { return true && FEATURE_BREWSWITCH == 1 && useBDPID; }, .minValue = PID_TN_BD_MIN, @@ -1229,7 +1243,7 @@ void setup() { .helpText = F("Differential time constant (in seconds) for the PID " "when brewing has been detected."), .type = kDouble, - .section = sBDSection, + .section = sBrewPidSection, .position = 26, .show = [] { return true && FEATURE_BREWSWITCH == 1 && useBDPID; }, .minValue = PID_TV_BD_MIN, @@ -1681,7 +1695,6 @@ void looppid() { } updateStandbyTimer(); - handleMachineState(); // Check if PID should run or not. If not, set to manual and force output to zero @@ -1726,7 +1739,7 @@ void looppid() { } } - // BD PID + // Brew PID if (machineState == kBrew) { if (brewPIDDelay > 0 && timeBrewed > 0 && timeBrewed < brewPIDDelay * 1000) { // disable PID for brewPIDDelay seconds, enable PID again with new tunings after that @@ -1762,7 +1775,6 @@ void looppid() { bPID.SetTunings(steamKp, 0, 0, 1); } - // sensor error OR Emergency Stop } void loopLED() { From 8c0b01fc1842e60920b5ed6b91b3c6b2e8ed8e16 Mon Sep 17 00:00:00 2001 From: LoQue90 <98092139+LoQue90@users.noreply.github.com> Date: Sun, 3 Nov 2024 14:06:47 +0100 Subject: [PATCH 23/23] enabled PID after brew was aborted adding TRACE log for brew PID --- src/main.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 7c4af5c04..e18f28027 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1654,12 +1654,13 @@ void looppid() { LOGF(TRACE, "Current PID diff'd input: %f", bPID.GetDeltaInput()); LOGF(TRACE, "Current PID D part: %f", bPID.GetLastDPart()); LOGF(TRACE, "Current PID kD: %f", bPID.GetKd()); - // Combined PID output LOGF(TRACE, "Current PID Output: %f", pidOutput); LOGF(TRACE, "Current Machinestate: %s", machinestateEnumToString(machineState)); + // Brew LOGF(TRACE, "timeBrewed %f", timeBrewed); LOGF(TRACE, "Brew detected %i", brew()); + LOGF(TRACE, "brewPIDdisabled %i", brewPIDDisabled); } } @@ -1765,6 +1766,13 @@ void looppid() { } } } + // Reset brewPIDdisabled if brew was aborted + if (machineState != kBrew && brewPIDDisabled) { + // enable PID again + bPID.SetMode(AUTOMATIC); + brewPIDDisabled = false; + LOG(DEBUG, "Enabled PID again after brew was manually stopped"); + } // Steam on if (machineState == kSteam) {