Files
homeassistant_espscreen/CYD_STABILITY.md
T
Max Gramser 3e959b3df9 Put ESP Screens in English and keep layouts when entity IDs change (0.2.40)
Everything a user sees or reads is now English: both boards' labels,
status replies and logs, the ESP Screens editor and Alerts cheatsheet,
and the README and guides (docs/TILES.md, CALIBRATING.md, ACCEPTANCE.md
and TROUBLESHOOTING.md replace the Dutch file names). Labels follow
Home Assistant's own English names (Heat/Cool modes, Heating/Cooling
actions, Away, Returning to dock, weather conditions), dates use English
abbreviations and the top bar writes numbers the English way. Docs use
HA 2026.9's menu names (Settings -> Apps, App store, Settings -> Tools).
Unused legacy files (home-like.yaml, buttons.yaml, a.out) are removed.

Firmware 0.2.34 names its entities in English. Home Assistant registers
a renamed ESPHome entity under a new entity ID, so the inbox
text.<screen>_tegelinstellingen becomes text.<screen>_tile_settings and
the layout stored under the old ID would be lost. The manager now
recognises the screen by its device, during a run or after a restart,
and moves its layout and update history along; the Update button and
the nightly round follow the screen through the rename. Screens that
still run 0.2.33 or older keep working: both languages are matched.

Main is the only release branch from now on.

Tested on a Home Assistant Yellow (HA 2026.9.1) with both bench boards:
see docs/TEST_RESULTS_0240.md.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-15 02:08:43 +02:00

6.4 KiB
Raw Blame History

Historical investigation on a single panel. For a new screen, see README.md and the five-point calibration; don't reuse these measurements.

ESP32-2432S028: stable operation

Use home-like-2432s028.yaml for the connected 2.8-inch CYD with ILI9341 and XPT2046. The Wi-Fi, API, and OTA secrets stay in secrets.yaml.

Operation

  • Set TILE_COUNT to the number of tiles in use (1–10). With six tiles or fewer, both page buttons and the page indicator disappear; higher tile numbers stay hidden.
  • Page 1 holds tiles 1–6; page 2 holds 7–10. Use the Previous and Next buttons at the bottom. Swiping is disabled.
  • A short tap runs the tile's existing action. A long press opens the existing light, climate, or vacuum card, or the configured long-press action.
  • Standby starts after ten minutes without touch (AUTO_DIM_TIMEOUT: "600").
  • The first tap on the dimmed screen wakes the screen.
  • Contacts shorter than TOUCH_MIN_PRESS_MS (60 ms on the CYD, 20 ms on the Guition) are ignored. One touch can produce at most one tile action; a movement greater than TOUCH_MOVE_LIMIT_PX (56 px, about 1 cm, on the CYD; 0 on the Guition: no limit, LVGL decides and releasing inside the tile counts) relative to the settled first contact point cancels the tap; only the first contact counts; the same tile is protected against contact bounce for 600 ms. A rejected tap is logged with its reason (tag touch).
  • The thermostat sends the rounded, clamped temperature it displays. A local temperature or mode choice gets three seconds to sync with HA. An active control press prevents automatic dimming.
  • Pippa uses the real vacuum.s8 status, so docking, cleaning, pausing, and returning are distinguished. Missing HA states are shown as Unavailable.

Technical choices

ESPHome 2026.6.2 with ESP-IDF; no Arduino components are needed. The display bus runs at 40 MHz, like ESPHome's standard CYD profile. XPT2046 is polled every 20 ms without the GPIO36 interrupt. The pressure threshold is 800, after a suspect corner reading at pressure 422. A local XPT2046 driver requires three consistent ADC samples for a new touch, ignores isolated outliers, and waits for two pressure-free samples before release. This adds about 40–60 ms on touch and prevents an unstable first reading from being immediately interpreted as a different button. The driver lives under components/. The stock interrupt driver tries to enable an unavailable internal pull-up on that input-only pin; the old firmware logged a GPIO error for this.

LVGL gets a 12% draw buffer. No scroll animations and no extra flash pulse after each tap. Tile backgrounds are opaque. Updates within 100 ms are coalesced; unchanged tile labels and colors are not redrawn. UI initialization only runs after LVGL has started. The clock refreshes immediately on time sync. Roboto is bundled locally in fonts/, including the OFL license.

The active layout is 320×240. The old, commented-out portrait presets are not adapted page layouts yet: with a different orientation, also reserve 34 pixels at the bottom for navigation and check the tile positions.

Building and flashing

esphome compile home-like-2432s028.yaml
esphome upload home-like-2432s028.yaml --device /dev/cu.usbserial-130
esphome logs home-like-2432s028.yaml --device /dev/cu.usbserial-130

Close any running serial log reader before flashing. The previous configuration is stored locally in diagnostics/before-2432s028.yaml.bak; the corresponding previous factory binary is in diagnostics/before-2432s028.factory.bin. These local backups are not included in Git. You can roll back by restoring the backup as the configuration and rebuilding/flashing; restore the old Arduino toolchain if you build the old configuration.

Tests

clang++ -std=c++17 -Wall -Wextra -Werror tests/test_cyd_ui.cpp -o /tmp/test_cyd_ui
/tmp/test_cyd_ui
python3 tests/test_layout.py
clang++ -std=c++17 -Wall -Wextra -Werror tests/test_touch_filter.cpp -o /tmp/test_touch_filter
/tmp/test_touch_filter

The C++ test checks contact bounce, short noise pulses, consecutive tiles, repetition within a single touch, millis() overflow, and temperature rounding. The layout test checks overlap, screen bounds, space for navigation, and the filter ahead of both handlers for all ten tiles.

With ESPHome's Python environment (with aioesphomeapi, PyYAML, and pyserial):

python diagnostics/capture_serial.py --reset --seconds 120 > diagnostics/runtime.log
python diagnostics/run_ui_test.py --host cyd-2432s028.local

The API test reads the encryption key internally from secrets.yaml and doesn't print it. It switches pages ten times and draws the five overlays on each round. It doesn't call any Home Assistant actions. Don't touch the screen during these roughly 11 seconds. This is a rendering/memory test; it doesn't replace a physical check of the touch calibration or a test of HA service effects.

Diagnostics logs free heap and the largest free memory block every 30 seconds. DEBUG is useful temporarily for touch and connection diagnostics. For everyday use, logger.level can go back to INFO once physical operation is confirmed good.

Touch diagnostics

python diagnostics/control_ui.py touch_diagnostics opens a separate screen with four crosshairs. During this measurement, touches can't trigger a tile action. Tap accurately, in order: top-left, top-right, bottom-right, and bottom-left. The raw and normalized coordinates appear in the serial logs with tag touch. Exit with python diagnostics/control_ui.py end_touch_diagnostics. The crosshairs sit at (20,20), (299,20), (299,219), and (20,219) for 320×240 landscape.

The current calibration (X 225–3800, Y 274–3609) is derived from the three repeated measurements at top-right and bottom-left on this physical board. The earlier top-left measurements were unstable and were deliberately not used, to avoid shifting the entire screen to the wrong position.

On top of that, set_raw_correction(...) in on_boot corrects the measured skew. The fit uses the filtered corner medians (830,556), (544,3461), (3410,3391), and (3492,372). After correction, the four medians land within five pixels of their measurement target in the regression test. These are board-specific coefficients; don't carry them over blindly to another panel. The raw= logs still show the physical, filtered ADC readings.