Der Log nach einem Reset zeigte alle Panel-Schritte fehlerfrei, aber
"i2c transaction failed" beim GT911. Bridge und Touch teilen sich den Bus:
Trifft ein Reset des P4 mitten in eine Übertragung, bleibt der Baustein in
seiner Bitausgabe stehen und hält SDA dauerhaft low. Beide hängen an
Dauerstrom, der Zustand überlebt also Reset und Flashen.
- ws7_i2c_bus_recover() taktet SCL vor dem Anlegen des Busses bis zu neunmal
von Hand, bis SDA freigegeben wird, und erzeugt dann eine Stop-Bedingung.
Bei freiem Bus läuft die Funktion wirkungslos durch.
- ws7_bridge_write() prüft den Rückgabewert. Bisher liefen fehlgeschlagene
Schreibzugriffe stillschweigend ins Leere - der eigentliche Grund, warum
das schwarze Bild keinerlei Spur hinterließ.
- pins_config.h: "#elsealle" statt "#else" seit 1.6.10 korrigiert. Der
Tippfehler traf nur den JC_PANEL_43-Zweig, der dadurch nicht mehr
übersetzbar war. Beide Panel-Varianten wieder gegengebaut.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018QoLDQeUh1dCQz7yYZVb4Y
Die Bridge-Abschaltfolge aus 1.6.11 hat den Fehler nicht behoben, sondern
verschlimmert: Nach C0/C2/AC = 0x00 kam das Panel auch direkt nach dem
Flashen nicht mehr hoch. Der Bringup entspricht wieder 1.6.10.
Stattdessen zwei Diagnosen zur Eingrenzung:
- esp_reset_reason() wird beim Hochlauf ausgegeben, um Kalt- von Warmstart
unterscheiden zu können.
- esp_ldo_acquire_channel() läuft nicht mehr ungeprüft durch, sondern meldet
einen Fehler über BSP_STEP. Es war der einzige Schritt ohne Prüfung.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018QoLDQeUh1dCQz7yYZVb4Y
Nach einem Reset des P4 blieb das Bild schwarz, die Hintergrundbeleuchtung
brannte; nur direkt nach dem Flashen lief es.
Die Bridge des Panels hat keine Reset-Leitung und hängt an Dauerstrom. Ein
Reset des P4 setzt sie nicht zurück - ihre Register standen noch auf den
Werten der vorigen Sitzung, während der P4 seine DSI-Strecke komplett neu
aufbaut. Beim Flashen wird die Versorgung getrennt, deshalb trat der Fehler
dort nicht auf.
ws7_bridge_pre_init() schaltet die Bridge jetzt zuerst definiert ab
(AB/AA, AD, dann AC/C2/C0), wartet WS7_BRIDGE_RESET_MS und schreibt erst
danach die Grundinitialisierung.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018QoLDQeUh1dCQz7yYZVb4Y
- WS7_PARTIAL_REFRESH = 1 auch im Auslieferungsstand. Am Gerät geprüft: kein
Flackern; von den drei Tempo-Maßnahmen aus 1.6.4 ist es der größte Gewinn.
- make_page() setzt einen deckenden Hintergrund in COL_BG statt LV_OPA_TRANSP.
Optisch identisch, spart LVGL beim Scrollen aber das Zeichnen und Mischen
der darunterliegenden Ebenen.
- Neuer Schalter WS7_PERF_MONITOR schaltet LV_USE_SYSMON/LV_USE_PERF_MONITOR
ein und blendet Bilder je Sekunde und Prozessorlast ein. Vorgabe 0, mit 1
gegengebaut.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018QoLDQeUh1dCQz7yYZVb4Y
Der GT9271 lässt gelegentlich einen Messzyklus aus oder liefert ein
unplausibles Paket. Der Hersteller-Treiber kann "gerade nichts Neues" nicht
von "Finger weg" unterscheiden und meldet beides als losgelassen. Seit die
Abtastrate mit 1.6.8 von 33 auf 16 ms gestiegen ist, wurde daraus sichtbar
Drücken-Loslassen-Drücken-Loslassen.
Vor den Treiber ist jetzt ein eigener get_xy-Aufsatz gesetzt: Er verwirft
unplausible Rohwerte und hält den letzten gültigen Punkt noch
WS7_TOUCH_HOLD_MS lang (Vorgabe 40 ms). Der Aufsatz wird zur Laufzeit in das
Touch-Handle eingehängt, die Herstellerdateien bleiben unverändert.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018QoLDQeUh1dCQz7yYZVb4Y
LV_DEF_REFR_PERIOD steuert nicht nur die Bildrate, sondern auch die
Abtastrate des Touch und die Schrittweite von Animationen. Mit 33 ms waren
das 30 Schritte je Sekunde - beim Ziehen mit dem Finger sichtbar ruckelig.
Für das Waveshare-Panel jetzt 16 ms, passend zu dessen 60 Hz. Kommt das
Zeichnen nicht hinterher, wird ein Bild später fertig; kaputt geht nichts.
Die JC-Panels bleiben unverändert bei 33 ms.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018QoLDQeUh1dCQz7yYZVb4Y
Eine Messung mit WS7_TOUCH_DEBUG hat gezeigt, dass die Touch-Zuordnung stimmt:
Der Tipp auf den Menü-Knopf landete bei X=66/Y=27, der Knopf liegt aber bei
X 8..56. Mit 48x36 Pixeln ist er auf dem 7-Zoll-Panel ein sehr kleines Ziel.
lv_obj_set_ext_click_area vergrößert die Trefferfläche um 20 Pixel, ohne den
Knopf optisch zu ändern. Die Vergrößerung wirkt nur innerhalb der Kopfleiste,
weil diese ihre Kinder beschneidet - dem Seiteninhalt darunter wird nichts
weggenommen, und bei offenem Menü liegt ohnehin der Vorhang darüber.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018QoLDQeUh1dCQz7yYZVb4Y
Der Menü-Knopf oben links reagiert am Waveshare-Panel nicht. Ob der Touch die
48x36 Pixel grosse Flaeche in der 44 Pixel hohen Kopfleiste ueberhaupt trifft,
liess sich bisher nicht nachsehen.
WS7_TOUCH_DEBUG in pins_config.h gibt jeden Berührpunkt roh und umgerechnet
über esp_rom_printf aus, also auch bei Core-Debug-Level "none". Vorgabe 0.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018QoLDQeUh1dCQz7yYZVb4Y
Zwei der drei Tempo-Maßnahmen aus 1.6.4 haben sich am Gerät als untauglich
erwiesen und stehen wieder auf ihrem alten Wert:
- WS7_COLOR_BITS = 24: Die Bridge dieses Panels nimmt kein RGB565 an.
- WS7_PARTIAL_REFRESH = 0: Der Menü-Vorhang ist halbtransparent und wird in
den gerade aktiven Bildpuffer eingemischt. Die nächste Zustandsmeldung der
S3 zeichnet in den zweiten Puffer, der ihn nie bekommen hat - der Vorhang
war damit sofort wieder weg und der Knopf schien wirkungslos. Nutzbar wäre
der Modus erst, wenn der LVGL-Port die geänderten Bereiche zwischen beiden
Puffern abgleicht.
Beide bleiben als Schalter erhalten, mit Notiz woran sie gescheitert sind.
WS7_PARALLEL_RENDER bleibt eingeschaltet - von den drei Maßnahmen trägt nur
diese.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018QoLDQeUh1dCQz7yYZVb4Y
1280x720 sind 2,4-mal so viele Pixel wie beim 4,3-Zöller, und bis 1.6.3 wurde
bei jeder Änderung das komplette Bild in 24 Bit neu gezeichnet. Drei Schalter
in pins_config.h, einzeln zurückstellbar:
- WS7_COLOR_BITS = 16: RGB565 statt RGB888, halbe Datenmenge je Bild.
lv_conf.h liest den Wert aus pins_config.h, damit Sketch und LVGL-Bibliothek
dieselbe Farbtiefe benutzen; display_hal.cpp sichert das per static_assert.
- WS7_PARTIAL_REFRESH = 1: Avoid-Tear-Mode 3 (Direct-Mode, zwei Puffer) statt
Vollbild-Neuzeichnen.
- WS7_PARALLEL_RENDER = 1: LV_USE_OS = FREERTOS und zwei Zeichen-Threads.
Framebuffer-Bedarf sinkt dadurch von rund 8,3 MB auf 3,7 MB PSRAM. Die
JC-Panels sind von allen drei Schaltern nicht betroffen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018QoLDQeUh1dCQz7yYZVb4Y
Nach dem ersten Betrieb am Waveshare ESP32-P4-Pico:
- UART zur Hauptplatine auf TX = GPIO20 / RX = GPIO21 (vorher GPIO17/18).
Die JC-Panels bleiben bei GPIO33/GPIO31.
- Das Bild steht in der tatsächlichen Einbaulage richtig herum, deshalb ist
WS7_ROTATE_180 wieder 0. Der Schalter bleibt für den Fall einer anderen
Montage erhalten.
- Der Touch war oben/unten spiegelverkehrt: Der Digitizer sitzt gegenüber dem
Bild um die Hochachse gedreht. WS7_TOUCH_MIRROR_RAW_X steht daher auf 1.
Bild- und Touch-Ausrichtung sind zwei getrennte Schalter, weil sie an diesem
Panel nicht zusammenfallen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018QoLDQeUh1dCQz7yYZVb4Y
Ein fehlgeschlagener Panel-Aufbau endete bisher in einem ESP_ERROR_CHECK
tief im LVGL-Port und damit in einem Speicherauszug ohne erkennbare Ursache.
- Die Schritte des Waveshare-Bringups melden ihren Fehler über esp_rom_printf,
also auch bei Core-Debug-Level "none". Zusätzlich werden PSRAM-Größe,
freier PSRAM, größter freier Block und der Framebuffer-Bedarf ausgegeben.
- jc_board_bringup() liefert jetzt einen Status. Kommt das Panel nicht hoch,
bleibt die Firmware ohne Anzeige lauffähig (UART + OTA), statt beim ersten
LVGL-Zugriff erneut abzustürzen.
- ui.cpp: alle öffentlichen Funktionen prüfen, ob ui_init gelaufen ist.
- Fehlerbehebung: esp_lcd_touch_new_i2c_gt911 setzt im Fehlerfall einen bereits
freigegebenen Zeiger. Das Handle wird vorbelegt und der Rückgabewert geprüft.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018QoLDQeUh1dCQz7yYZVb4Y
Der Ordner hieß JC_Display_Firmware, bedient seit 1.6.0 aber auch das
Waveshare 7inch DSI LCD (H) am ESP32-P4-Pico. Der Name führte in die Irre.
- JC_Display_Firmware/ -> P4_Display_Firmware/ (samt Sketch, den Arduino
gleichnamig zum Ordner verlangt)
- Doku/JC-Display_UART-Protokoll.md -> Doku/P4-Display_UART-Protokoll.md,
Verweise und Titel angepasst
- Verweise in CLAUDE.md, README und Quelltextköpfen nachgezogen
Nur Namen und Pfade, keine Logikänderung. Der Vendor-Ordner
JC_Display_Firmware_7zoll/ behält seinen Namen, ebenso die Bezeichner
JC_PANEL_TYPE/jc_board_bringup im Quelltext.
Enthält außerdem die bereits im Arbeitsverzeichnis liegende, noch nicht
committete Ergänzung des Git-Workflows in CLAUDE.md (PRs über die Gitea-API
statt der hängenden tea-CLI).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018QoLDQeUh1dCQz7yYZVb4Y
Das Panel ist auf dem Kopf eingebaut. WS7_ROTATE_180 in pins_config.h dreht
Bild und Touch gemeinsam; Vorgabe ist gedreht.
Die Drehung übernimmt der PPA-Grafikbeschleuniger (EXAMPLE_LVGL_PORT_PPA_
ROTATION_ENABLE), weil die Software-Rotation des LVGL-Ports nur RGB565
verarbeitet und für dieses RGB888-Panel nicht in Frage kommt. Der Touch wird
im process_coordinates-Hook mitgedreht, sonst läge die Bedienung
spiegelbildlich zum Bild.
MADCTL ist als WS7_MADCTL herausgezogen, falls die Bridge es doch auswertet.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018QoLDQeUh1dCQz7yYZVb4Y
Der 40-polige Header des ESP32-P4-Pico hat eine andere Belegung als die
Expansion-IO der JC-Panels. Für WS_PANEL_7H gilt jetzt TX = GPIO17,
RX = GPIO18; die JC-Panels bleiben bei GPIO33/GPIO31.
README und Changelog entsprechend ergänzt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018QoLDQeUh1dCQz7yYZVb4Y
Dieselbe P4-Firmware läuft jetzt zusätzlich auf einem Waveshare ESP32-P4-Pico
mit dem Waveshare 7inch DSI LCD (H) (1280x720). Auswahl über JC_PANEL_TYPE in
config.h (neu: WS_PANEL_7H, ab jetzt Vorgabe); JC_PANEL_43 und JC_PANEL_70
bleiben unverändert.
- board_bringup.c: DSI-Bus, DBI-Kommandokanal und DPI-Panel werden ohne
Hersteller-Panel-Treiber direkt angelegt (PLL_F20M, 2 Lanes zu 1250 Mbit/s,
80 MHz DPI, Austastlücken 64/64/64, RGB888). Panel-Freigabe und Helligkeit
über die Bridge auf I2C 0x45; Licht erst nach dem Start der DSI-Ausgabe.
- lv_conf.h leitet LV_COLOR_DEPTH aus JC_PANEL_TYPE ab (24 Bit für das
Waveshare-Panel, 16 Bit für die JC-Panels) und liest dafür config.h.
display_hal.cpp sichert das mit static_assert ab.
- Touch GT9271 (I2C 0x14) über den GT911-Treiber; Achsentausch und Begrenzung
auf die Bildfläche im process_coordinates-Hook.
- pins_config.h: Auflösung, DSI-Zeitbasis und Touch-Umrechnung als WS7_*-Werte.
- README und Changelog ergänzt.
Die UART-Pins zum S3 stehen für das Waveshare-Board noch auf den JC-Werten
(GPIO33/31) und müssen nach dem Header-Aufdruck gesetzt werden.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DxAvqVnrY6YSoGFrNGeRTi
Dieselbe Display-Firmware bedient jetzt wahlweise das bisherige 4,3-Zoll-Panel
JC4880P443C-I-W (ST7701, 480x800) oder das neue 7-Zoll-Panel JC1060P470C-I-W
(JD9165, 1024x600). Umgeschaltet wird über JC_PANEL_TYPE in config.h
(JC_PANEL_43 / JC_PANEL_70) oder per Compiler-Flag -DJC_PANEL_TYPE=70. Vorgabe
bleibt das 4,3-Zoll-Panel; dessen Verhalten ändert sich nicht.
- src/lcd/esp_lcd_jd9165.c/.h aus dem Hersteller-Paket übernommen;
board_bringup.c legt je nach Panel DSI-Bus, DPI-Zeitbasis und Herstellertreiber an.
- pins_config.h liefert Auflösung, LCD-Reset (4,3": GPIO5, 7,0": GPIO27) und
Ausrichtung panelabhängig. Das 7-Zoll-Panel ist nativ Querformat, deshalb
entfallen dort die 270-Grad-Rotation und die PPA-Beschleunigung.
- lvgl_port_v9.h bezieht LVGL_PORT_H/V_RES aus pins_config.h statt fest 480/800.
- Der GT911 des 7-Zöllers meldet Rohkoordinaten im Raster 800x480 statt 1024x600.
Die Umrechnung hängt am process_coordinates-Hook von esp_lcd_touch, damit die
Herstellerdatei esp_lcd_touch_gt911.c unverändert bleibt.
- ui.cpp rechnet nicht mehr mit fest verdrahteten 480 Pixeln Höhe, sondern mit
DISP_VER_RES. Layout und Schriften bleiben sonst unverändert.
- Hersteller-Paket des 7-Zöllers unter JC_Display_Firmware_7zoll/ abgelegt;
Werkzeuge, Archive und mitgelieferte Fremdbibliotheken per .gitignore
ausgeschlossen (587 MB im Original, 21 MB im Repo).
Kompiliertest ESP32-P4, beide Varianten:
4,3": 1.173.768 B Flash (37 %), 322.880 B RAM (98 %)
7,0": 1.138.752 B Flash (36 %), 322.600 B RAM (98 %)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Über den Schalter kam die Abfrage "Espresso oder Cold Extraction" zuverlässig,
über Antippen am Display nur manchmal. Ursache waren zwei unterschiedliche
Bedingungen für dieselbe Sache:
- askMode (zeigt die Auswahl im Dialog) verlangte zusätzlich cxArmable
- choiceRelevant (sendet "wakeEspresso" und schließt damit das Auswahlfenster
der S3) verlangte es nicht
In der Lücke dazwischen zeigte der Dialog nur "Aufwecken", unterdrückte aber
trotzdem die Rückfrage der S3 - die Frage war auf beiden Seiten weg. Der
Schalterweg hatte diese Lücke nie, weil er allein an der S3 hängt.
P4: beide Stellen benutzen jetzt wake_choice_offered(). Bot der Dialog die
Auswahl nicht an, sendet er "deactivateStandby"; dann öffnet die S3 ihr
eigenes Auswahlfenster und die Frage kommt trotzdem.
S3: Die Fensterentscheidung ist als Bedingungskette geschrieben und hält
Quelle und Ergebnis des letzten Aufweckens fest. /Cold-Extraction zeigt das
an - die bisherige Live-Liste zeigt nur den jetzigen Stand, der beim
Nachsehen längst wieder ein anderer sein kann.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die Abfrage erschien nicht, sobald der Cold-Extraction-Modus noch aktiv war — und
da er seit 5.3.1 persistent ist, war er das nach dem ersten kalten Bezug dauerhaft.
Damit erklärt sich, warum weder der Schalter- noch der Touch-Weg etwas zeigte.
Die Bedingung "Modus ist aus" war falsch gedacht ("sonst gibt es nichts zu fragen").
Die Auswahl muss in beide Richtungen gehen, also auch von kalt zurück auf Espresso.
Sonst hängt man nach dem ersten kalten Bezug im kalten Modus fest, ohne beim
Aufwecken je wieder gefragt zu werden.
- Bedingung aus beiden Öffnungspfaden entfernt (Standby-Übergang und Kaltstart).
- Das Fenster bleibt bei aktivem Modus offen; bisher schloss es sofort wieder.
- "wakeEspresso" beendet jetzt einen laufenden Modus, statt ihn nur nicht
einzuschalten — sonst wäre die Auswahl eine Einbahnstraße.
- Diagnose auf /Cold-Extraction listet den Modus nicht mehr als Voraussetzung,
sondern zeigt ihn als Ist-Zustand.
- P4: Der Cold-Knopf zeigt den Ist-Zustand ("aktiv lassen" und hervorgehoben, wenn
der Modus läuft).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die Abfrage hängt an fünf Bedingungen gleichzeitig (freigeschaltet, Abfrage
eingeschaltet, Display verbunden, Modus gerade aus, kein Wartungsmodus/Reinigung/
Tuning). Fehlt eine, passiert schlicht nichts, und von außen war nicht erkennbar
welche. Die Seite /Cold-Extraction zeigt sie jetzt live mit Haken bzw. Kreuz an,
dazu ob das Auswahlfenster gerade offen ist.
Zusätzlich eine echte Lücke geschlossen: Die Abfrage kam nur beim Standby-Übergang.
Wer die Maschine am Netzschalter einschaltet, durchläuft nie einen solchen Übergang
— dieser Weg war nicht abgedeckt. Jetzt öffnet das Fenster einmal pro Laufzeit auch
nach einem Kaltstart, sobald sich das Display gemeldet hat. Startet die Maschine in
den Standby hinein, bleibt es beim Standby-Übergang.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die Abfrage war eine reine Vorab-Abfrage des Displays und erschien nur beim
Antippen des Standby-Bildschirms. Beim Aufwecken über den Schalter ist der Standby
aber schon beendet, bevor das Display überhaupt fragen könnte — dieser Weg war nie
abgedeckt.
Die Steuerung hält jetzt nach dem Aufwecken ein Auswahlfenster offen (20 s): Der
Wasserkreis heizt in dieser Zeit nicht, das Display blendet die Auswahl von sich aus
ein und zeigt einen Countdown. Ohne Entscheidung wird danach normal geheizt, es geht
also nichts verloren, wenn niemand hinsieht.
Das Fenster öffnet nur mit angeschlossenem Display (sonst könnte niemand wählen),
bei freigeschalteter Funktion und aktiver Einstellung "Abfrage beim Aufwecken", und
nur wenn der Modus nicht ohnehin schon läuft. Es schließt bei Entscheidung,
Bezug/Spülen oder erneutem Standby.
Neue Aktion wakeEspresso (beendet Standby falls aktiv und schließt das Fenster) —
das Display sendet sie statt deactivateStandby, sobald die Auswahl relevant ist,
sonst würde direkt nach dem Aufwecken nochmal gefragt. Neue State-Felder
cxWakeChoice und cxWakeChoiceSec.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der Aufweck-Dialog am Touch-Display wird zur Auswahl: "Womit aufwecken?" mit
"Espresso" (heizt normal auf) und "Cold Extraction (Wasser bleibt kalt)". Damit
lässt sich bei jedem Aufwecken neu entscheiden, ohne vorher die Web-UI zu bedienen.
Bei der kalten Variante wird der Modus scharf geschaltet, bevor der Standby endet —
der Wasserkreis heizt also gar nicht erst an.
Abschaltbar über die neue Einstellung "Abfrage beim Aufwecken" (EEPROM 982), zu
finden auf /Cold-Extraction und auf der Cold-Extraction-Seite des Displays. Ist sie
aus, erscheint wieder der bisherige Dialog. Ohne angeschlossenes Display oder bei
nicht freigeschalteter Funktion hat sie keine Wirkung. Neues Feld cxAskOnWake im
State und in saveBrew.
Dazu: Die Meldungstexte der kalten Extraktion sind jetzt mit echten Umlauten
geschrieben ("nicht möglich" statt "nicht moeglich"). Für das OLED übersetzt die
neue Hilfsfunktion oledUmlauts() sie beim Rendern nach CP437 — dort hätte UTF-8
sonst zwei Fehlzeichen je Umlaut ergeben, weshalb die Texte ursprünglich
transliteriert waren. Web-UI und Touch-Display stellen UTF-8 direkt dar.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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 <noreply@anthropic.com>
Cold Extraction bekommt in beiden Oberflächen einen eigenen Menüpunkt statt eines
angehängten Blocks auf der Brew-Control-Seite. Die Parameter sind damit erstmals
auch am Touch-Display änderbar.
S3: neue Seite /Cold-Extraction, gegliedert in Grundeinstellung, Vorbenetzung,
Hauptbezug, Bezugsende und Pumpenschutz, jeder Abschnitt mit kurzer Begründung.
/Brew-Control verweist nur noch darauf. Das UART-Kommando saveBrew akzeptiert jetzt
die cx-Felder, und das State-JSON liefert die restlichen Parameter mit, damit das
Display seine Felder vorbelegen kann.
Wichtig: Der Speicher-Handler von /Brew-Control wertet die cx-Felder nicht mehr aus.
Er tat es bisher, und nach dem Verschieben der Checkbox hätte ein Speichern dort die
Freischaltung abgeschaltet, weil das Feld im Formular fehlt.
P4: neue Seite "Cold Extraction" mit allen Parametern; der Modus-Schalter ist von der
Temperatur-Seite dorthin umgezogen, damit es nur eine Stelle gibt. Die Brew-Control-
Seite ist neu gegliedert: jede Funktion in einer eigenen Karte mit Titel und einer
Zeile, die erklärt was sie tut, statt einer durchlaufenden Liste unter
Zwischenüberschriften. Neues Hilfsmakro group_card() für beide Seiten.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Messung an der Maschine: Nach 7 s Vorbenetzung kommen heiß 1-2 sirupartige Tropfen,
kalt bei voller Pumpenleistung rund 10 g dünne Brühe ohne Crema — etwa zehnfacher
Durchfluss trotz dreifacher Viskosität.
Die Ursache ist nicht die Viskosität, sondern das Kaffeebett: Kaltes Mehl quillt
nicht, ist schlecht benetzbar, es wandert kein Feinanteil und es lösen sich kaum
Feststoffe, die das Bett verdichten. Volle Leistung auf den trockenen kalten Puck
legt deshalb sofort Kanäle an, die sich — anders als bei heißem Bezug — nie wieder
schließen; der restliche Bezug läuft daran vorbei statt zu extrahieren.
Vorbenetzung und Hauptbezug pulsen jetzt beide, nur mit unterschiedlicher Leistung.
Neue Einstellung "Pumpenleistung Vorbenetzung" (Standard 10 %), Standard im
Hauptbezug von 30 % auf 20 % gesenkt. Bestehende Installationen behalten ihre Werte;
das neue Feld greift beim Update automatisch auf den Default zurück.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>