From 0ec3d89973194d7ea9dbf5dc1284414f4b91320b Mon Sep 17 00:00:00 2001 From: raw-designs Date: Thu, 3 Sep 2026 13:02:35 +0200 Subject: [PATCH] =?UTF-8?q?diag(P4):=20Messpunkte=20f=C3=BCr=20den=20Still?= =?UTF-8?q?stand=20beim=20Standby-Wechsel=20(1.9.7)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Beim Wechsel in den Standby bleibt das Display stehen: Bild bleibt auf der alten Seite, keine Bedienung, auch der S3 weckt nicht mehr auf. Der Log bricht nach dem letzten Bildaufbau ab, ohne Panic. Statt zu raten, Messpunkte: - Herzschlag alle 2 s aus dem Arduino-loop (freier Heap) und aus einem lv_timer im LVGL-Task (lv_mem_monitor). Bleibt nur einer aus, ist klar, welcher Task steht. - ui_fade_in() der Standby-Uhr wird eingeklammert: "wird eingeblendet" / "eingeblendet, N ms". - hal_backlight() wird gemessen; über 50 ms wird die Dauer gemeldet. Der Bridge-Schreibzugriff läuft über denselben I2C-Bus wie der Touch. Außerdem entfernt: die LV_EVENT_INVALIDATE_AREA-Callbacks aus 1.9.5. Das Event geht per lv_display_send_event an das Display, nicht an Objekte - die Callbacks konnten nie feuern, ihr Ausbleiben war kein Beweis. Beide Panel-Varianten mit arduino-cli gegengebaut. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01NeFMr439WcLMdebE3kU7fS --- P4_Display_Firmware/Changelog.txt | 13 +++++++++++++ P4_Display_Firmware/P4_Display_Firmware.ino | 15 +++++++++++++++ P4_Display_Firmware/ui.cpp | 19 +++++++++++-------- 3 files changed, 39 insertions(+), 8 deletions(-) diff --git a/P4_Display_Firmware/Changelog.txt b/P4_Display_Firmware/Changelog.txt index 2e42a9a..3f7f158 100644 --- a/P4_Display_Firmware/Changelog.txt +++ b/P4_Display_Firmware/Changelog.txt @@ -1,3 +1,16 @@ +Version 1.9.7: +- Messpunkte für den Stillstand beim Wechsel in den Standby: Beide Abläufe - der Haupt- und + der Zeichenablauf - melden jetzt alle zwei Sekunden einen Herzschlag mit Speicherstand. + Bleibt nur einer von beiden aus, ist klar, welcher stehen bleibt. +- Das Einblenden der Standby-Uhr meldet Anfang und Ende mit Dauer. Bleibt die zweite Meldung + aus, hängt es genau dort. +- Jeder Helligkeitswechsel, der länger als 50 ms braucht, wird mit seiner Dauer gemeldet. Der + Schreibzugriff geht über denselben Bus wie der Touch - ein Verdacht für die bekannte + Verzögerung von ein bis zwei Sekunden. +- Die Rückmeldung aus 1.9.5, die einen komplett ungültigen Inhaltsbereich melden sollte, ist + wieder entfernt. Sie konnte nie auslösen: LVGL schickt diese Meldung an das Display, nicht + an einzelne Elemente. Ihr Ausbleiben war also kein Beweis. + Version 1.9.6: - Die Darstellungseinstellungen haben einen eigenen Menüpunkt „Darstellung" bekommen. Sie standen bisher oben auf der Info-Seite, zwischen Sachen, mit denen sie nichts zu tun diff --git a/P4_Display_Firmware/P4_Display_Firmware.ino b/P4_Display_Firmware/P4_Display_Firmware.ino index 69d57bc..b4aa866 100644 --- a/P4_Display_Firmware/P4_Display_Firmware.ino +++ b/P4_Display_Firmware/P4_Display_Firmware.ino @@ -67,11 +67,25 @@ static void onState(const MachineState& st) { } if (bl < 0) bl = 0; if (bl > 100) bl = 100; if (bl != s_lastBacklight) { + // Vermessen: Rund um jeden Helligkeitswechsel hing die Bedienung bisher ein bis + // zwei Sekunden. Der Schreibzugriff geht ueber denselben I2C-Bus wie der Touch. + uint32_t t0 = millis(); hal_backlight(bl); + uint32_t dt = millis() - t0; + if (dt > 50) Serial.printf("[HAL] Helligkeit %d %% gesetzt, %u ms\n", bl, (unsigned)dt); s_lastBacklight = bl; } } +// Herzschlag aus dem Haupt-Ablauf. Zusammen mit dem Herzschlag aus dem Zeichen-Ablauf +// laesst sich unterscheiden, welcher der beiden stehen bleibt, wenn nichts mehr geht. +static void main_heartbeat() { + static uint32_t s_last = 0; + if (millis() - s_last < 2000) return; + s_last = millis(); + Serial.printf("[Haupt] Herzschlag, freier Speicher %u Byte\n", (unsigned)ESP.getFreeHeap()); +} + static void onAck(uint32_t id, bool ok, const String& message) { // Automatische/Heartbeat-Acks nicht als Toast zeigen (pong, Handshake, Listen-Refresh). bool routine = ok && (message == "pong" || message == "hello" || @@ -332,6 +346,7 @@ static unsigned long s_lastDbgMs = 0; #endif void loop() { + main_heartbeat(); g_client.loop(); // UART lesen, hello/heartbeat, state -> UI hal_loop(); // realer Modus: leer; Stub-Modus: lv_timer_handler() diff --git a/P4_Display_Firmware/ui.cpp b/P4_Display_Firmware/ui.cpp index 90cd73b..d8d52fa 100644 --- a/P4_Display_Firmware/ui.cpp +++ b/P4_Display_Firmware/ui.cpp @@ -3565,12 +3565,10 @@ static void refr_ready_cb(lv_event_t*) { (int)g_refrArea[i].y1, (int)g_refrArea[i].y2); } -// Meldet, wenn ein ganzer Container ungueltig gemacht wird. Damit laesst sich unterscheiden, -// ob eine einzelne Beschriftung den Bildaufbau ausloest oder ob gleich der komplette -// Inhaltsbereich neu gezeichnet werden soll - zwei verschiedene Ursachen. -static void inval_watch_cb(lv_event_t* e) { - const char* name = (const char*)lv_event_get_user_data(e); - esp_rom_printf("[UI] %s wird komplett ungueltig\n", name); +static void ui_heartbeat_cb(lv_timer_t*) { + lv_mem_monitor_t m; lv_mem_monitor(&m); + esp_rom_printf("[UI] Herzschlag, LVGL-Speicher frei %u von %u Byte, groesster Block %u\n", + (unsigned)m.free_size, (unsigned)m.total_size, (unsigned)m.free_biggest_size); } static void refr_monitor_install() { @@ -3984,8 +3982,7 @@ void ui_init(ProtocolClient* client) { if (g_client) g_client->sendListProfiles(); refr_monitor_install(); - if (g_content) lv_obj_add_event_cb(g_content, inval_watch_cb, LV_EVENT_INVALIDATE_AREA, (void*)"Inhaltsbereich"); - if (g_pages[PG_DASH]) lv_obj_add_event_cb(g_pages[PG_DASH], inval_watch_cb, LV_EVENT_INVALIDATE_AREA, (void*)"Dashboard-Seite"); + lv_timer_create(ui_heartbeat_cb, 2000, nullptr); g_uiReady = true; } @@ -4175,8 +4172,14 @@ void ui_update(const MachineState& st) { if (shouldShow) { label_set_if_changed(g_standbyClock, zeit.length() ? zeit.c_str() : "--:--"); if (!g_standbyShown) { + // Vermessen: Das Einblenden der Uhr ist der Moment, in dem das Display + // zuletzt stehen geblieben ist. Bleibt die zweite Zeile aus, haengt es hier. + esp_rom_printf("[UI] Standby-Uhr wird eingeblendet\n"); + uint32_t t0 = lv_tick_get(); ui_fade_in(g_standbyScreen, UI_FADE_MS); // Einschlaf-Animation g_standbyShown = true; + esp_rom_printf("[UI] Standby-Uhr eingeblendet, %u ms\n", + (unsigned)(lv_tick_get() - t0)); } // Frueher wurde die Uhr hier bei JEDER Zustandsmeldung nach vorn geholt. Das // ordnet die Ebenen neu und laesst LVGL den gesamten Bildschirm neu zeichnen - -- 2.54.0