Keep the empty edge band out of LVGL so a quick swipe gets its samples (0.2.35)

On 0.2.29 the edge swipe flipped pages, but about half of the quick flicks
on Studio 1 ended with "randveeg niet gevuurd: 5 px naar binnen": every
touch lasted about 160 ms and produced a single sample. A press in the
empty band landed on tile_scroll or the page, and the theme gives every
object a pressed style, so LVGL repainted nearly the whole screen on press
and on release, blocking the loop and the 20 ms touch polling for as long
as the flick took. The page and the tile container are no longer
clickable: no state change, no repaint, no events, and the edge swipe on
the touchscreen triggers does not need them. While an edge swipe is armed
every sample is logged, and the press line carries the contact id, so the
sampling can be read from the log. Firmware 0.2.30 for both boards.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Max Gramser
2026-09-14 14:02:47 +02:00
parent 7564e612bb
commit 61ceb40075
9 changed files with 76 additions and 8 deletions
+8
View File
@@ -177,6 +177,14 @@ staan iconen in de browser uit het midden); draai daarna `generate_packages.py`.
De substituties `MDI_GLYPH_*` zijn vervallen: `TILEn_ICON` in handmatige
profielen moet uit de set komen. Geen gewijzigde preferences of sleutels.
### Compatibiliteit 0.2.35 / firmware 0.2.30
Alleen firmware (Guition). `on_boot` haalt `LV_OBJ_FLAG_CLICKABLE` van `home_page` en
`tile_scroll`: een druk buiten de tegels heeft geen LVGL-object meer (geen pressed-stijl,
geen hertekening, geen events); de randveeg loopt via de touchscreen-triggers en heeft dat
niet nodig, `lv_indev_wait_release` werkt ook zonder actief object. Trace-regels `veeg …`
op INFO alleen zolang `edge_swipe.armed()`. Verder ongewijzigd.
### Compatibiliteit 0.2.34 / firmware 0.2.29
Alleen firmware. LVGL 9.5.0's `send_event()` in `lv_indev.c` stuurt het invoerapparaat
+38
View File
@@ -0,0 +1,38 @@
# Testresultaten app 0.2.35 / firmware 0.2.30 (2026-09-14)
Vervolg op 0.2.34, live op Studio 1 (firmware 0.2.29): de randveeg wisselt (14 wissels in
één reeks), maar ongeveer de helft van de snelle vegen eindigde met `randveeg niet gevuurd:
1…17 px naar binnen` terwijl de vinger verder ging. Elke aanraking duurde van druk tot
wissel of loslaten 147–199 ms en leverde maar één meting op; geen LVGL-waarschuwingen
(de drempel daarvan groeit mee tot 200 ms, dus stalls van 100 ms zijn onzichtbaar).
## Diagnose
- Een druk in de lege rand landt op `tile_scroll` (of `home_page`), beide met de thema-stijl
`obj: pressed: bg_opa: 45%`: LVGL hertekent bij indrukken en loslaten een vlak van
480×348 px met blending. Op een tegel is diezelfde hertekening klein (de guard zag daar
wel 73 px drift), in de rand blokkeert hij de ESPHome-loop en daarmee de 20 ms-polling
van de GT911 precies zolang een flick duurt.
## Wat veranderde
- `on_boot`: `LV_OBJ_FLAG_CLICKABLE` af van `home_page` en `tile_scroll`. Een druk buiten
de tegels heeft geen LVGL-object meer: geen pressed-stijl, geen hertekening, geen events.
De randveeg loopt via de touchscreen-triggers en `lv_indev_wait_release` werkt zonder
actief object.
- Trace: zolang een randveeg gewapend is logt `on_update` elke meting (`veeg id= st= x= y=`),
en `GT911 press` meldt het contact-id.
## Geautomatiseerd
- C++ `test_cyd_ui` PASS (geen wijziging in de klassen); Python: 91 tests OK
(`FIRMWARE_VERSION` 0.2.30); `generate_packages.py --check` groen.
- ESPHome 2026.6.2 compile: `easy-guition-device.yaml` SUCCESS in 42 s (RAM 32,0%, flash
18,3%), `easy-cyd-device.yaml` SUCCESS in 39 s (RAM 31,0%, flash 76,1%); geen nieuwe
waarschuwingen.
## Te controleren op Studio 1
- Snelle vegen vanaf beide randen: het log moet per veeg meerdere `veeg`-regels (elke ~20 ms)
tonen en `randveeg: pagina …` binnen 40 px. Blijft het bij één meting, dan zit de
bemonstering elders (I2C, GT911-frame-rate) en is de trace de volgende aanwijzing.
+10 -2
View File
@@ -1,7 +1,7 @@
# Guition ESP32-S3-4848S040 / 4-inch EU wallbox, 480x480 IPS + GT911.
# Use guition-device.yaml; see docs/GUITION.md. CYD hardware is a separate profile.
substitutions:
SCREEN_FIRMWARE_VERSION: "0.2.29"
SCREEN_FIRMWARE_VERSION: "0.2.30"
# 0: no drift limit; LVGL decides, releasing inside the tile is a tap, leaving it is not
# (like iOS). The CYD keeps a limit because its resistive panel jumps.
TOUCH_MOVE_LIMIT_PX: "0"
@@ -598,6 +598,11 @@ esphome:
- lambda: |-
cyd::touch_guard.configure(${TOUCH_MOVE_LIMIT_PX}, ${TOUCH_MIN_PRESS_MS});
cyd::edge_swipe.configure(${DISPLAY_W}, ${DISPLAY_H}, ${EDGE_SWIPE_BAND_PX}, ${EDGE_SWIPE_TRAVEL_PX});
// The page and the tile container take no presses: the theme's pressed style would
// otherwise repaint nearly the whole screen twice per touch in the empty edge band,
// starving the touch polling for the whole length of a quick swipe.
lv_obj_remove_flag(id(home_page)->obj, LV_OBJ_FLAG_CLICKABLE);
lv_obj_remove_flag(id(tile_scroll), LV_OBJ_FLAG_CLICKABLE);
id(last_touch_ms) = millis();
id(display_dimmed) = false;
lv_obj_set_style_pad_row(id(vacuum_actions), 4, 0);
@@ -1872,12 +1877,15 @@ touchscreen:
id(touch_down) = true;
cyd::touch_guard.begin(millis(), touch.x, touch.y, touch.id);
cyd::edge_swipe.begin(touch.x, touch.y, static_cast<int>(id(screen_lvgl).get_rotation()));
ESP_LOGI("touch", "GT911 press x=%u y=%u test=%d", touch.x, touch.y, id(calibration_active));
ESP_LOGI("touch", "GT911 press x=%u y=%u id=%u test=%d", touch.x, touch.y, (unsigned) touch.id, id(calibration_active));
on_update:
- lambda: |-
id(last_touch_ms) = millis();
// Only the contact that started the touch counts; the guard ignores other ids.
for (const auto &point : touches) {
// Trace every sample of an edge touch: the log then shows how often the panel delivers.
if (cyd::edge_swipe.armed())
ESP_LOGI("touch", "veeg id=%u st=%u x=%u y=%u", (unsigned) point.id, (unsigned) point.state, point.x, point.y);
cyd::touch_guard.update(point.x, point.y, point.id);
if (point.id != cyd::touch_guard.contact()) continue;
// Swiping in from a side edge flips the page ("Vegen tussen pagina's"); the tap
+1 -1
View File
@@ -58,7 +58,7 @@
############################################################
substitutions:
SCREEN_FIRMWARE_VERSION: "0.2.29"
SCREEN_FIRMWARE_VERSION: "0.2.30"
# A tap survives a finger that drifts up to this far (320 px over 58 mm: 1 cm); further is a swipe.
TOUCH_MOVE_LIMIT_PX: "56"
# Shortest contact that counts as a tap; a resistive panel bounces, a capacitive one does not.
+1 -1
View File
@@ -59,7 +59,7 @@
############################################################
substitutions:
SCREEN_FIRMWARE_VERSION: "0.2.29"
SCREEN_FIRMWARE_VERSION: "0.2.30"
# A tap survives a finger that drifts up to this far (320 px over 58 mm: 1 cm); further is a swipe.
TOUCH_MOVE_LIMIT_PX: "56"
# Shortest contact that counts as a tap; a resistive panel bounces, a capacitive one does not.
+10 -2
View File
@@ -2,7 +2,7 @@
# Guition ESP32-S3-4848S040 / 4-inch EU wallbox, 480x480 IPS + GT911.
# Use guition-device.yaml; see docs/GUITION.md. CYD hardware is a separate profile.
substitutions:
SCREEN_FIRMWARE_VERSION: "0.2.29"
SCREEN_FIRMWARE_VERSION: "0.2.30"
# 0: no drift limit; LVGL decides, releasing inside the tile is a tap, leaving it is not
# (like iOS). The CYD keeps a limit because its resistive panel jumps.
TOUCH_MOVE_LIMIT_PX: "0"
@@ -602,6 +602,11 @@ esphome:
- lambda: |-
cyd::touch_guard.configure(${TOUCH_MOVE_LIMIT_PX}, ${TOUCH_MIN_PRESS_MS});
cyd::edge_swipe.configure(${DISPLAY_W}, ${DISPLAY_H}, ${EDGE_SWIPE_BAND_PX}, ${EDGE_SWIPE_TRAVEL_PX});
// The page and the tile container take no presses: the theme's pressed style would
// otherwise repaint nearly the whole screen twice per touch in the empty edge band,
// starving the touch polling for the whole length of a quick swipe.
lv_obj_remove_flag(id(home_page)->obj, LV_OBJ_FLAG_CLICKABLE);
lv_obj_remove_flag(id(tile_scroll), LV_OBJ_FLAG_CLICKABLE);
id(last_touch_ms) = millis();
id(display_dimmed) = false;
lv_obj_set_style_pad_row(id(vacuum_actions), 4, 0);
@@ -1803,12 +1808,15 @@ touchscreen:
id(touch_down) = true;
cyd::touch_guard.begin(millis(), touch.x, touch.y, touch.id);
cyd::edge_swipe.begin(touch.x, touch.y, static_cast<int>(id(screen_lvgl).get_rotation()));
ESP_LOGI("touch", "GT911 press x=%u y=%u test=%d", touch.x, touch.y, id(calibration_active));
ESP_LOGI("touch", "GT911 press x=%u y=%u id=%u test=%d", touch.x, touch.y, (unsigned) touch.id, id(calibration_active));
on_update:
- lambda: |-
id(last_touch_ms) = millis();
// Only the contact that started the touch counts; the guard ignores other ids.
for (const auto &point : touches) {
// Trace every sample of an edge touch: the log then shows how often the panel delivers.
if (cyd::edge_swipe.armed())
ESP_LOGI("touch", "veeg id=%u st=%u x=%u y=%u", (unsigned) point.id, (unsigned) point.state, point.x, point.y);
cyd::touch_guard.update(point.x, point.y, point.id);
if (point.id != cyd::touch_guard.contact()) continue;
// Swiping in from a side edge flips the page ("Vegen tussen pagina's"); the tap
+6
View File
@@ -1,3 +1,9 @@
## 0.2.35 (firmware 0.2.30)
- **Snelle randveeg pakt nu ook in één keer (Guition).** Op 0.2.29 wisselde de veeg wel, maar ongeveer de helft van de snelle vegen eindigde met `randveeg niet gevuurd: 5 px naar binnen` terwijl de vinger duidelijk verder ging; elke aanraking duurde in de firmware bijna exact 160 ms en leverde maar één meting op. Een druk in de lege rand landde op de achtergrondcontainer en de pagina, en het thema geeft elk object een ingedrukte-stijl (45% dekking): bijna het hele scherm werd bij indrukken en loslaten opnieuw getekend, wat de touch-polling precies zo lang blokkeerde als een flick duurt. De pagina en de tegelcontainer nemen nu geen drukken meer aan (`LV_OBJ_FLAG_CLICKABLE` uit), dus geen hertekening en de metingen komen elke 20 ms door.
- Zolang een randveeg gewapend is, logt de firmware elke meting (`veeg id=0 st=2 x=.. y=..`) en de eerste druk meldt zijn contact-id, zodat de bemonstering uit het log te lezen is.
- Firmware 0.2.30 voor beide borden; de app biedt de update aan. Alleen de doelversie verandert in de app.
## 0.2.34 (firmware 0.2.29)
- **Randveeg werkte in 0.2.32 en 0.2.33 helemaal niet, hersteld.** De veeg was daar op de pointer-events van LVGL gezet, maar de LVGL 9.5.0 die ESPHome meelevert stuurt het invoerapparaat wel PRESSED en RELEASED maar geen PRESSING, dus de veeg kreeg nooit positie-updates (live gezien op Studio 1: wel `GT911 press`, verder niets). De Guition volgt de veeg weer via ESPHome's touchscreen-triggers, zoals in 0.2.24 (dat werkte live zodra de kaartfix uit 0.2.32 erbij zat), met de eigen rotatiemapping gelijk aan die van ESPHome's LVGL-component, de 45°-regel, `end()` bij loslaten (een niet-afgemaakte veeg kan daardoor niet meer bij de volgende aanraking afgaan) en de logregels `randveeg genegeerd: …` en `randveeg niet gevuurd: …`.
+1 -1
View File
@@ -16,7 +16,7 @@ WEEKDAYS = ['ma', 'di', 'wo', 'do', 'vr', 'za', 'zo']
REPO = 'https://github.com/MaxGramser/homeassistant_espscreen'
REFS = {'cyd': 'main', 'guition': 'main'}
# Firmware shipped with this app release; screens below it get an update offer.
FIRMWARE_VERSION = '0.2.29'
FIRMWARE_VERSION = '0.2.30'
ATTRS = frozenset('brightness percentage current_position current_temperature temperature current_humidity min_temp max_temp target_temp_step supported_color_modes hvac_modes hvac_action hs_color color_temp_kelvin min_color_temp_kelvin max_color_temp_kelvin fan_speed_list unit_of_measurement battery_level fan_speed volume_level is_volume_muted media_title options min max step temperature_unit supported_features device_class next_rising next_setting finishes_at duration remaining humidity wind_speed wind_speed_unit apparent_temperature fan_modes swing_modes fan_mode swing_mode'.split())
# Attributes whose boolean value the screen needs; every other bool stays behind.
BOOL_ATTRS = frozenset(['is_volume_muted'])
+1 -1
View File
@@ -1,5 +1,5 @@
name: ESP Screen Manager
version: "0.2.34"
version: "0.2.35"
slug: esp_screen_manager
description: Kies tegels voor je CYD en Guition touchscreen, zonder opnieuw flashen.
url: https://github.com/MaxGramser/homeassistant_espscreen