From 334896b9cf3d0a6cbdb4b9214faf0d858609892b Mon Sep 17 00:00:00 2001 From: raw-designs Date: Wed, 12 Aug 2026 00:51:48 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20Zielgewicht=20bei=20Cold=20Extraction=20?= =?UTF-8?q?=C3=BCberall=20korrekt=20anzeigen=20(S3=205.4.1=20/=20P4=201.2.?= =?UTF-8?q?1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Während einer kalten Extraktion stand als Zielgewicht überall noch der Brew-by-Weight-Wert des normalen Espresso-Bezugs. OLED, Web-Dashboard und Touch-Display griffen alle direkt auf brewByWeightTargetGrams zu — die kalte Extraktion ersetzt Brew-by-Weight aber und stoppt nach coldExtractionTargetGrams. Neue Hilfsfunktion activeTargetWeightGrams() liefert das Ziel des aktuellen bzw. nächsten Bezugs. Das UART-Feld targetWeight führt jetzt diesen Wert; bbwTarget bleibt unverändert die Roh-Einstellung, damit die Brew-Control-Seite weiter das Richtige anzeigt. Zusätzlich hing die Gewichtsanzeige selbst an "Brew-by-Weight aktiv" — das ist bei kalter Extraktion typischerweise aus, obwohl ein Ziel existiert. OLED, Waage-Kachel und Live-Bezugsschirm zeigen Gewicht und Fortschritt jetzt auch beim kalten Bezug. Co-Authored-By: Claude Opus 5 --- Changelog.txt | 10 ++++++++++ Dual-PID.ino | 20 +++++++++++++++----- JC_Display_Firmware/Changelog.txt | 7 +++++++ JC_Display_Firmware/config.h | 2 +- JC_Display_Firmware/ui.cpp | 19 +++++++++++++------ 5 files changed, 46 insertions(+), 12 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index b151506..54446c5 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -1,3 +1,13 @@ +Version 5.4.1: +- Bug-Fix: Während einer kalten Extraktion stand als Zielgewicht überall noch der Brew-by-Weight-Wert + des normalen Espresso-Bezugs. Betroffen waren OLED, Web-Dashboard und Touch-Display, weil alle drei + direkt brewByWeightTargetGrams anzeigten - die kalte Extraktion ersetzt Brew-by-Weight aber und stoppt + nach coldExtractionTargetGrams. Neue Hilfsfunktion activeTargetWeightGrams() liefert jetzt das Ziel + des aktuellen bzw. nächsten Bezugs; das UART-Feld "targetWeight" führt diesen Wert (bbwTarget bleibt + unverändert die Roh-Einstellung). +- Auf dem OLED wird während eines kalten Bezugs jetzt überhaupt Gewicht angezeigt: Die Anzeige hing an + „Brew-by-Weight aktiv", das bei kalter Extraktion typischerweise aus ist - trotz vorhandenem Ziel. + Version 5.4.0: - Cold Extraction hat eine eigene Seite: /Cold-Extraction, eigener Eintrag im Menü. Auf /Brew-Control steht nur noch ein Verweis darauf - die Seite war mit dem angehängten Block unübersichtlich geworden. diff --git a/Dual-PID.ino b/Dual-PID.ino index 196e928..7cde42a 100644 --- a/Dual-PID.ino +++ b/Dual-PID.ino @@ -369,7 +369,7 @@ Adafruit_SH1106G display = Adafruit_SH1106G(128, 64, &Wire); * Firmware-Informationen ************************************************************************************/ -String version = "5.4.0"; +String version = "5.4.1"; String versionHersteller = "Thomas Müller"; String versionHerstellerMail = "thomas@mueller.black"; @@ -4060,6 +4060,14 @@ bool coldExtractionTemperatureOk() { return (InputWasser < (double)limit); } +// Zielgewicht des aktuellen bzw. naechsten Bezugs. Bei aktiver Cold Extraction ist das +// coldExtractionTargetGrams - brewByWeightTargetGrams gilt dann nicht, weil die kalte +// Extraktion Brew-by-Weight ersetzt. Alle Anzeigen (OLED, Web, Display) muessen diesen +// Wert nehmen, sonst steht dort das Espresso-Ziel waehrend eines kalten Bezugs. +float activeTargetWeightGrams() { + return coldExtractionModeActive ? coldExtractionTargetGrams : brewByWeightTargetGrams; +} + // Steht eine nutzbare Waage bereit? Ohne sie laeuft die kalte Extraktion rein zeitgesteuert: // Zielgewicht und Stillstands-Erkennung greifen nicht, es bleibt nur die maximale Bezugsdauer. // Bewusst kein Sperrgrund - ein kurz abgemeldeter HX711 soll die Funktion nicht blockieren. @@ -6566,7 +6574,9 @@ if (scaleModeActive) { // Wenn die Zustandsmaschine nicht aktiv ist, zeige den laufenden Shot oder die Temperaturen else if (shotActive) { // Priorität: Shot läuft *aktuell*? - if (brewByWeightEnabled && scaleConnected) { + // Auch ein kalter Bezug hat ein Gewichtsziel - unabhaengig von Brew-by-Weight, + // das die Cold Extraction ersetzt. + if ((brewByWeightEnabled || coldExtractionShotActive) && scaleConnected) { display.setTextSize(1); display.setCursor(0, 0); display.println(F("Bezug aktiv:")); @@ -6583,7 +6593,7 @@ if (scaleModeActive) { netWeight = 0.0; } char weightBuffer[15]; - snprintf(weightBuffer, sizeof(weightBuffer), "%.1f/%.1fg", netWeight, brewByWeightTargetGrams); + snprintf(weightBuffer, sizeof(weightBuffer), "%.1f/%.1fg", netWeight, activeTargetWeightGrams()); // --- ENDE ÄNDERUNG --- display.setCursor(0, 30); @@ -16325,7 +16335,7 @@ void buildDashboardJson(char *buffer, size_t bufferSize) { // Plattformdaten dtostrf(getWeightReadingForUi(), 4, 1, floatBuf); offset += snprintf(buffer + offset, bufferSize - offset, "\"weight\":%s,", floatBuf); - dtostrf(brewByWeightTargetGrams, 4, 1, floatBuf); offset += snprintf(buffer + offset, bufferSize - offset, "\"targetWeight\":%s,", floatBuf); + dtostrf(activeTargetWeightGrams(), 4, 1, floatBuf); offset += snprintf(buffer + offset, bufferSize - offset, "\"targetWeight\":%s,", floatBuf); // bei Cold Extraction das kalte Ziel offset += snprintf(buffer + offset, bufferSize - offset, "\"scaleEnabled\":%s,", scaleEnabled ? "true" : "false"); offset += snprintf(buffer + offset, bufferSize - offset, "\"scaleType\":%u,", (unsigned int)scaleType); offset += snprintf(buffer + offset, bufferSize - offset, "\"scaleConnected\":%s,", scaleConnected ? "true" : "false"); @@ -16610,7 +16620,7 @@ static void buildTouchUartStateJson(char *buffer, size_t bufferSize) { } dtostrf(getWeightReadingForUi(), 4, 1, floatBuf); offset += snprintf(buffer + offset, bufferSize - offset, "\"weight\":%s,", floatBuf); - dtostrf(brewByWeightTargetGrams, 4, 1, floatBuf); offset += snprintf(buffer + offset, bufferSize - offset, "\"targetWeight\":%s,", floatBuf); + dtostrf(activeTargetWeightGrams(), 4, 1, floatBuf); offset += snprintf(buffer + offset, bufferSize - offset, "\"targetWeight\":%s,", floatBuf); // bei Cold Extraction das kalte Ziel // Endgewicht des letzten Bezugs inkl. Offset (identisch zur OLED: Netto beim Stopp + Offset). // Nur bei gewichtsbasiertem Bezug aussagekraeftig -> lastShotByWeight signalisiert das dem P4. dtostrf(lastShotFinalNetWeight + brewByWeightOffsetGrams, 4, 1, floatBuf); offset += snprintf(buffer + offset, bufferSize - offset, "\"lastShotWeight\":%s,", floatBuf); diff --git a/JC_Display_Firmware/Changelog.txt b/JC_Display_Firmware/Changelog.txt index bf85ddc..d141daf 100644 --- a/JC_Display_Firmware/Changelog.txt +++ b/JC_Display_Firmware/Changelog.txt @@ -1,3 +1,10 @@ +Version 1.2.1: +- Bug-Fix: Während einer kalten Extraktion zeigten Waage-Kachel und Live-Bezugsschirm das Zielgewicht + des normalen Espresso-Bezugs (bbwTarget) statt des Ziels der kalten Extraktion (cxTarget). Außerdem + erschienen Gewichtsanzeige und Fortschrittsbalken nur, wenn Brew-by-Weight aktiv war - bei kalter + Extraktion ist das typischerweise aus, obwohl ein Ziel existiert. Beide Anzeigen nutzen jetzt + cxTarget, sobald cxShot gesetzt ist. + Version 1.2.0: - Neue Seite „Cold Extraction" mit eigenem Menüeintrag (braucht S3-Firmware ab 5.4.0). Dort stehen jetzt alle Parameter der kalten Extraktion und lassen sich direkt am Display ändern: Freigabetemperatur, diff --git a/JC_Display_Firmware/config.h b/JC_Display_Firmware/config.h index 20d9d12..4cbbce5 100644 --- a/JC_Display_Firmware/config.h +++ b/JC_Display_Firmware/config.h @@ -65,7 +65,7 @@ // ------------------------------------------------------------------------------------- // Firmware // ------------------------------------------------------------------------------------- -#define DISPLAY_FW_VERSION "1.2.0" // Firmware-Stand der P4-Display-Steuerung (Info-Seite) +#define DISPLAY_FW_VERSION "1.2.1" // Firmware-Stand der P4-Display-Steuerung (Info-Seite) // ------------------------------------------------------------------------------------- // Protokoll diff --git a/JC_Display_Firmware/ui.cpp b/JC_Display_Firmware/ui.cpp index d424bc0..e8ba70f 100644 --- a/JC_Display_Firmware/ui.cpp +++ b/JC_Display_Firmware/ui.cpp @@ -1858,12 +1858,16 @@ static void brew_live_tick() { } // Zielfortschritt: Brew-by-Weight (Gewicht) vor Brew-by-Time (Zeit), sonst versteckt if (g_bzBarRow && g_bzBar && g_bzBarLbl) { - bool bbw = scale && g_state.bbwEnabled && g_state.bbwTarget > 0.0f; + // Ein kalter Bezug hat sein eigenes Ziel (cxTarget) und ersetzt Brew-by-Weight - + // sonst stuende hier das Espresso-Ziel. + const bool cxShotNow = g_state.cxShot && g_state.cxTarget > 0.0f; + const float wTarget = cxShotNow ? g_state.cxTarget : g_state.bbwTarget; + bool bbw = scale && (cxShotNow || (g_state.bbwEnabled && g_state.bbwTarget > 0.0f)); if (bbw || (g_shotBbtMode && g_bbtTarget > 0.0f)) { int pct; if (bbw) { - pct = (int)(w / g_state.bbwTarget * 100.0f + 0.5f); - snprintf(b, sizeof(b), "%.1f g / %.1f g", w, g_state.bbwTarget); + pct = (int)(w / wTarget * 100.0f + 0.5f); + snprintf(b, sizeof(b), "%.1f g / %.1f g", w, wTarget); } else { pct = (int)(el / g_bbtTarget * 100.0f + 0.5f); snprintf(b, sizeof(b), "%.1f s / %.1f s", el, g_bbtTarget); @@ -3915,7 +3919,10 @@ void ui_update(const MachineState& st) { else lv_obj_add_flag(cellBezug, LV_OBJ_FLAG_HIDDEN); } if (lblBezug) { - bool bbwShot = st.shotActive && st.bbwEnabled && st.bbwTarget > 0.0f; + // Bei kaltem Bezug zaehlt cxTarget, nicht das Brew-by-Weight-Ziel + const bool cxShotNow = st.cxShot && st.cxTarget > 0.0f; + const float shotTarget = cxShotNow ? st.cxTarget : st.bbwTarget; + bool bbwShot = st.shotActive && (cxShotNow || (st.bbwEnabled && st.bbwTarget > 0.0f)); // Winzige negative Messwerte (z.B. -0.04 g) oder negatives Float-Null wuerden von // "%.1f" als "-0.0" dargestellt -> auf 0.0 normalisieren (kein fuehrendes Minus). float wDisp = st.weight; @@ -3924,14 +3931,14 @@ void ui_update(const MachineState& st) { lv_label_set_text(lblBezug, "--"); } else if (bbwShot) { // Waehrend des Bezugs mit Brew-by-Weight: Ist oben, Ziel darunter (zweizeilig) - lv_label_set_text_fmt(lblBezug, "%.1f g\n/ %.1f g", wDisp, st.bbwTarget); + lv_label_set_text_fmt(lblBezug, "%.1f g\n/ %.1f g", wDisp, shotTarget); } else { lv_label_set_text_fmt(lblBezug, "%.1f g", wDisp); } // Fortschrittsbalken Gewicht/Ziel (nur waehrend BBW-Bezug) if (g_bbwBar) { if (bbwShot) { - int pct = (int)(st.weight / st.bbwTarget * 100.0f + 0.5f); + int pct = (int)(st.weight / shotTarget * 100.0f + 0.5f); if (pct < 0) pct = 0; if (pct > 100) pct = 100; lv_bar_set_value(g_bbwBar, pct, LV_ANIM_OFF); lv_obj_remove_flag(g_bbwBar, LV_OBJ_FLAG_HIDDEN); -- 2.54.0