Skip to content

Fix ESP32-S3 compilation: resolve LVGL widget dependencies#19

Open
youkorr wants to merge 19 commits intomainfrom
claude/fix-lvgl-esp32s3-Llg2P
Open

Fix ESP32-S3 compilation: resolve LVGL widget dependencies#19
youkorr wants to merge 19 commits intomainfrom
claude/fix-lvgl-esp32s3-Llg2P

Conversation

@youkorr
Copy link
Copy Markdown
Owner

@youkorr youkorr commented Mar 25, 2026

Summary

  • Fix compilation error on ESP32-S3: lv_image.h requires LV_USE_LABEL=1 but it was set to 0 when no label widget was explicitly used in the YAML config
  • Add automatic LVGL internal widget dependency resolution (e.g. IMG→LABEL, ANIMIMG→LABEL+IMG, DROPDOWN→LABEL, etc.)
  • Dependencies are also propagated to the build filter so the required .c source files are compiled

Problem

On ESP32-P4 the config works because all widgets happen to be enabled. On ESP32-S3, when the config uses image/animimage widgets without a label widget, the generated lv_conf.h sets LV_USE_LABEL=0. LVGL's lv_image.h has a compile-time check (#error) requiring LV_USE_LABEL=1, causing build failure.

Solution

Added a _WIDGET_DEPS map in __init__.py that declares LVGL's internal compile-time widget dependencies. After collecting used widgets, a transitive dependency resolution loop ensures all required widgets are enabled in both lv_conf.h defines and the PlatformIO build filter.

Test plan

  • Compile with ESP32-S3-Box-3 config (boxs3.yaml) — should no longer fail on lv_image.h
  • Compile with ESP32-P4 config (p4mini.yaml) — should continue working as before
  • Verify that a config using only image widgets correctly enables LV_USE_LABEL=1 in generated lv_conf.h

https://claude.ai/code/session_01SEGhHty2WhxmJfLeNGQnc9

claude added 19 commits March 25, 2026 00:01
lv_image.h requires LV_USE_LABEL=1 at compile time. When an ESP32-S3
config uses image widgets without explicitly using a label widget,
LV_USE_LABEL was set to 0, causing compilation errors. Add a dependency
resolution step that automatically enables required widgets (e.g. LABEL
for IMG/ANIMIMG) and their source files in the build filter.

https://claude.ai/code/session_01SEGhHty2WhxmJfLeNGQnc9
lvgl.h unconditionally includes lv_animimage.h → lv_image.h, which has
a compile-time #error requiring LV_USE_LABEL=1. This causes build
failures on ESP32-S3 regardless of which widgets are used. Add LABEL
to the default lv_uses set so it is always enabled.

https://claude.ai/code/session_01SEGhHty2WhxmJfLeNGQnc9
lv_theme_default.c unconditionally references lv_button_class and
lv_buttonmatrix_class. Since THEME_DEFAULT is always enabled, BTN and
BTNMATRIX must also always be in lv_uses to ensure their source files
are compiled and LV_USE_BTN/LV_USE_BTNMATRIX are set to 1.

https://claude.ai/code/session_01SEGhHty2WhxmJfLeNGQnc9
…e component

The LVGL component was emitting USE_IMAGE when the lv_image widget was
used, but USE_IMAGE is the define owned by the ESPHome image component.
This caused lvgl_esphome.h to try including esphome/components/image/image.h
even when the image: component was not in the YAML config.

Fix:
- Skip emitting USE_IMAGE from LVGL (USE_LVGL_IMAGE is sufficient)
- Guard image.h includes with both USE_LVGL_IMAGE and USE_IMAGE so
  the header is only included when both the LVGL widget AND the
  ESPHome image component are present

https://claude.ai/code/session_01SEGhHty2WhxmJfLeNGQnc9
Simple LVGL config with a header, label and button to verify
display and touch are working correctly.

https://claude.ai/code/session_01SEGhHty2WhxmJfLeNGQnc9
Logs added:
- setup() start, buffer allocation details (size, display dims, page count)
- show_page() call with page count
- setup() completion confirmation
- First 5 flush_cb calls with area coordinates

This helps diagnose whether LVGL is initializing, allocating buffers,
finding pages, and actually flushing to the display.

https://claude.ai/code/session_01SEGhHty2WhxmJfLeNGQnc9
Sample pixel values at corners and center of each flush buffer,
plus count non-zero pixels in the first row. This reveals whether
LVGL is rendering the expected colors (black bg = 0x0000) or
sending all-white data (0xFFFF).

https://claude.ai/code/session_01SEGhHty2WhxmJfLeNGQnc9
Tests ili9xxx display directly with colored rectangles and text
to verify the display hardware works independently of LVGL.

https://claude.ai/code/session_01SEGhHty2WhxmJfLeNGQnc9
- Remove all debug logs added for white screen investigation
  (flush_cb pixel sampling, setup progress, flush_count member)
- Fix test YAML: byte_order changed from little_endian to big_endian
  (ILI9341 display requires big-endian byte order)

https://claude.ai/code/session_01SEGhHty2WhxmJfLeNGQnc9
3-page demo showcasing LVGL 9.5 features:
- Dashboard: live clock, uptime, WiFi signal bar, arc gauge,
  control buttons with page navigation
- Controls: brightness slider (controls backlight), toggle switches,
  LED indicators, animated spinner
- Selectors: roller widget, dropdown, bar, navigation buttons

Features demonstrated: themes, style_definitions, page transitions
(MOVE_LEFT/RIGHT), arc, slider, switch, LED, spinner, roller,
dropdown, bar, button, label, sensor integration (uptime, WiFi RSSI,
SNTP time), lambda callbacks.

https://claude.ai/code/session_01SEGhHty2WhxmJfLeNGQnc9
Same issue as USE_IMAGE: LVGL widget defines (USE_SWITCH, USE_BUTTON)
collide with ESPHome component defines, causing the build to look for
component headers that aren't present. Add SWITCH and BUTTON to the
exclusion list so only USE_LVGL_SWITCH and USE_LVGL_BUTTON are emitted.

https://claude.ai/code/session_01SEGhHty2WhxmJfLeNGQnc9
The Controls page had no navigation buttons, making page_selector
unreachable via touchscreen. Added "< Dashboard" and "Selectors >"
buttons. Resized the LED indicators card to fit everything in 240px.

https://claude.ai/code/session_01SEGhHty2WhxmJfLeNGQnc9
These widgets were purely decorative with no real function.
Removing them simplifies the UI and frees space for nav buttons.

https://claude.ai/code/session_01SEGhHty2WhxmJfLeNGQnc9
- Remove uptime_sensor, add debug component for free heap and PSRAM
- Dashboard: uptime card → Free Heap card, arc_demo → PSRAM usage arc
- Controls: enlarge Mode Auto & Night Mode (h55→h70), move nav buttons
  down (y166→y186) to prevent overlap with switches

https://claude.ai/code/session_01SEGhHty2WhxmJfLeNGQnc9
The debug component must be declared standalone, update_interval
goes on the sensor platform instead.

https://claude.ai/code/session_01SEGhHty2WhxmJfLeNGQnc9
The ESP32-S3-BOX-3 has 16MB PSRAM (octal mode), not 8MB. The incorrect
8MB constant caused negative percentage values (-84%), which made the
arc knob disappear. Also added clamping to 0-100 range for safety.

https://claude.ai/code/session_01SEGhHty2WhxmJfLeNGQnc9
The font component already exists in this repo at components/font/.
Instead of pulling it from github://pr#12312, include it directly
from our own repo by adding 'font' to the components list.

Updated: demo_s3box3.yaml, boxs3.yaml, p4mini.yaml, waveshare_lottie.yaml,
test-lvgl9.yaml, waveshare (3).yaml

https://claude.ai/code/session_01SEGhHty2WhxmJfLeNGQnc9
New PAGE 4 with:
- Lottie widget (120x120) loading from /sdcard/animation.json
- Play/Pause/Stop control buttons
- Navigation back to Selectors page
- Updated Selectors page nav button to point to Lottie page

https://claude.ai/code/session_01SEGhHty2WhxmJfLeNGQnc9
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants