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

125 lines
6.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
> Historical investigation on a single panel. For a new screen, see [README.md](README.md)
> and [the five-point calibration](docs/CALIBRATING.md); 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
```sh
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
```sh
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):
```sh
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.