Check the device logs to see if the action is being sent; check the HA logs to see if there are any errors there. Does the button change state when you switch the light from elsewhere?
Holy crap! I left it unplugged for a couple hours, then I plugged it back in just now to see if it would change state when I turned the light on, and the dang thing is working. But apparently blue is off and red is on, which I guess makes sense. But I literally made no changes to my code.
Okay, and now Iām noticing something else. Itās really flaky. Iāll let the screen go to sleep for a minute or so, when it wakes the screen comes up blank before refreshing the button and I can click the button a few times (and it will change state on the screen) while nothing happens to the light. Then all of a sudden it will start working again. But if I let it go to sleep and then immediately wake it back up, the screen comes up with the button on it and it still remains functional. Any idea what that might be about?
Well, I refer you to my previous answer about checking logs. But it sounds like you have some flakey communications.
A couple of unrelated things - you donāt need the on_boot action to show the main page, that happens by default (and you only have one page anyway.) Instead of using the global variable and an interval to control the backlight, use the LVGL on_idle trigger - see the cookbook for examples.
Okay, yeah, I was just taking the code from above for the blanking. But following your suggestion, I dug into the LVGL tips and tricks and moved to that method. That seems to be working well. I AM having some sort of communications issues though, but Iām unsure of how to move forward with the troubleshootingā¦
my new yaml:
esphome:
name: waveshare-esp32-s3-touch
friendly_name: Waveshare-ESP32-S3-Touch
platformio_options:
build_flags: "-DBOARD_HAS_PSRAM"
board_build.arduino.memory_type: qio_opi
board_build.flash_mode: dio
board_upload.maximum_ram_size: 524288
esp32:
board: esp32-s3-devkitc-1
variant: esp32s3
framework:
type: esp-idf
sdkconfig_options:
CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240: y
CONFIG_ESP32S3_DATA_CACHE_64KB: y
CONFIG_SPIRAM_FETCH_INSTRUCTIONS: y
CONFIG_SPIRAM_RODATA: y
# Enable logging
logger:
level: DEBUG
# Enable Home Assistant API
api:
encryption:
key: "<secret>"
ota:
- platform: esphome
password: "<secret>"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Waveshare-Esp32-S3-Touch"
password: "<secret>"
ch422g:
- id: ch422g_hub
psram:
mode: octal
speed: 80MHz
i2c:
sda: 8
scl: 9
scan: true
frequency: 400kHz
# Switch to turn backlight back on
switch:
- platform: gpio
name: backlight
id: display_backlight
pin:
ch422g: ch422g_hub
number: 2
mode:
output: true
inverted: False
restore_mode: ALWAYS_ON
# Antiburn Switch
- platform: template
name: Antiburn
id: switch_antiburn
icon: mdi:television-shimmer
optimistic: true
entity_category: "config"
turn_on_action:
- logger.log: "Starting Antiburn"
- if:
condition: lvgl.is_paused
then:
- lvgl.resume:
- lvgl.widget.redraw:
- lvgl.pause:
show_snow: true
turn_off_action:
- logger.log: "Stopping Antiburn"
- if:
condition: lvgl.is_paused
then:
- lvgl.resume:
- lvgl.widget.redraw:
# Timer for Antiburn
time:
- platform: homeassistant
on_time:
- hours: 2,3,4,5
minutes: 5
seconds: 0
then:
- switch.turn_on: switch_antiburn
- hours: 2,3,4,5
minutes: 35
seconds: 0
then:
- switch.turn_off: switch_antiburn
# Number to track backlight timeout
number:
- platform: template
name: LVGL Screen timeout
optimistic: true
id: display_timeout
unit_of_measurement: "s"
initial_value: 45
restore_value: true
min_value: 10
max_value: 180
step: 5
mode: box
touchscreen:
- platform: gt911
id: my_touchscreen
interrupt_pin: 4
reset_pin:
ch422g:
number: 1
on_release:
- if:
condition: lvgl.is_paused
then:
- logger.log: "LVGL resuming"
- lvgl.resume:
- lvgl.widget.redraw:
- switch.turn_on: display_backlight
display:
- platform: rpi_dpi_rgb
id: rpi_disp
# update_interval: never
auto_clear_enabled: false
color_order: RGB
pclk_frequency: 16MHz
dimensions:
width: 800
height: 480
reset_pin:
ch422g:
number: 3
enable_pin:
id: enable_pin_display
ch422g:
number: 2
de_pin:
number: 5
hsync_pin:
number: 46
ignore_strapping_warning: true
vsync_pin:
number: 3
ignore_strapping_warning: true
pclk_pin: 7
hsync_back_porch: 30
hsync_front_porch: 210
hsync_pulse_width: 30
vsync_back_porch: 4
vsync_front_porch: 4
vsync_pulse_width: 4
data_pins:
red: [1, 2, 42, 41, 40]
blue: [14, 38, 18, 17, 10]
green: [39, 0, 45, 48, 47, 21]
# Draw the dashboard
lvgl:
displays:
- rpi_disp
touchscreens:
- my_touchscreen
on_idle:
timeout: !lambda "return (id(display_timeout).state * 1000);"
then:
- logger.log: "LVGL is idle"
- switch.turn_off: display_backlight
- lvgl.pause:
pages:
- id: main_page
width: 100%
bg_color: 0x000000
bg_opa: cover
widgets:
- button:
id: office_corner_light_btn
align: CENTER
width: 150
height: 70
checkable: true
widgets:
- label:
align: CENTER
text: 'Office Corner Lights'
on_click:
- logger.log: "Toggle Button Pressed"
- homeassistant.action:
action: light.toggle
data:
entity_id: light.lifx_bulb
I was preparing to paste a ton of logs in here when I stumbled upon this in the homeassistant logs:
Can't connect to ESPHome API for waveshare-esp32-s3-touch @ 192.168.0.132: waveshare-esp32-s3-touch @ 192.168.0.132: The connection dropped immediately after encrypted hello; Try enabling encryption on the device or turning off encryption on the client (Home Assistant 2025.3.2). (HandshakeAPIError)
So⦠any idea where I fix that? I can only assume that the waveshare is connecting to homeassistant through my apache reverse proxy, which is totally fine with me, but since itās not leaving the house, I can just as easily connect directly to it if I know where to configure that ![]()
No idea, and itās not a display issue, personally I would start by deleting the device in HA and adding it again.
So thatās exactly what I did. Deleted it all, went and re-initialized it through web.esphome.io and then re-added to home assistant and re-installed my yaml. Seems to work until it doesnāt. But as you said, doesnāt seem to be a display issue. Iāll have to make a new post outlining whatās going on, because thereās something fishy going on, and it seems like the whole device is going to sleep instead of just the screen, and then when it wakes up it struggles to connect or something. Thanks for all the help though, at least Iāve gotten it to a point where it seems like my yaml is working. That was a huge step forward!
With this code
esphome:
name: esp-display
friendly_name: ESP Display
platformio_options:
build_flags: "-DBOARD_HAS_PSRAM"
board_build.arduino.memory_type: qio_opi
board_build.flash_mode: dio
board_upload.maximum_ram_size: 524288
esp32:
board: esp32-s3-devkitc-1
variant: esp32s3
framework:
type: esp-idf
sdkconfig_options:
CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240: y
CONFIG_ESP32S3_DATA_CACHE_64KB: y
CONFIG_SPIRAM_FETCH_INSTRUCTIONS: y
CONFIG_SPIRAM_RODATA: y
# Enable logging
logger:
level: DEBUG
# Enable Home Assistant API
api:
encryption:
key: "KEY"
ota:
- platform: esphome
password: "PASSWORD"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Esp-Display Fallback Hotspot"
password: "PASSWORD"
ch422g:
- id: ch422g_hub
psram:
mode: octal
speed: 80MHz
i2c:
sda: 8
scl: 9
scan: true
frequency: 400kHz
# Switch to turn backlight back on
switch:
- platform: gpio
name: backlight
id: display_backlight
pin:
ch422g: ch422g_hub
number: 2
mode:
output: true
inverted: False
restore_mode: ALWAYS_ON
# Antiburn Switch
- platform: template
name: Antiburn
id: switch_antiburn
icon: mdi:television-shimmer
optimistic: true
entity_category: "config"
turn_on_action:
- logger.log: "Starting Antiburn"
- if:
condition: lvgl.is_paused
then:
- lvgl.resume:
- lvgl.widget.redraw:
- lvgl.pause:
show_snow: true
turn_off_action:
- logger.log: "Stopping Antiburn"
- if:
condition: lvgl.is_paused
then:
- lvgl.resume:
- lvgl.widget.redraw:
# Timer for Antiburn
time:
- platform: homeassistant
on_time:
- hours: 2,3,4,5
minutes: 5
seconds: 0
then:
- switch.turn_on: switch_antiburn
- hours: 2,3,4,5
minutes: 35
seconds: 0
then:
- switch.turn_off: switch_antiburn
# Number to track backlight timeout
number:
- platform: template
name: LVGL Screen timeout
optimistic: true
id: display_timeout
unit_of_measurement: "s"
initial_value: 45
restore_value: true
min_value: 10
max_value: 180
step: 5
mode: box
touchscreen:
- platform: gt911
id: my_touchscreen
interrupt_pin: GPIO4
reset_pin:
ch422g:
number: 1
on_touch:
- lambda: |-
ESP_LOGI("Touch", "Touch detected at x=%d, y=%d", touch.x, touch.y);
on_release:
- if:
condition: lvgl.is_paused
then:
- logger.log: "LVGL resuming"
- lvgl.resume:
- lvgl.widget.redraw:
- switch.turn_on: display_backlight
display:
- platform: rpi_dpi_rgb
id: rpi_disp
# update_interval: never
auto_clear_enabled: false
color_order: RGB
pclk_frequency: 16MHz
dimensions:
width: 800
height: 480
reset_pin:
ch422g:
number: 3
enable_pin:
id: enable_pin_display
ch422g:
number: 2
de_pin:
number: 5
hsync_pin:
number: 46
ignore_strapping_warning: true
vsync_pin:
number: 3
ignore_strapping_warning: true
pclk_pin: 7
hsync_back_porch: 30
hsync_front_porch: 210
hsync_pulse_width: 30
vsync_back_porch: 4
vsync_front_porch: 4
vsync_pulse_width: 4
data_pins:
red: [1, 2, 42, 41, 40]
blue: [14, 38, 18, 17, 10]
green: [39, 0, 45, 48, 47, 21]
# Draw the dashboard
lvgl:
displays:
- rpi_disp
touchscreens:
- my_touchscreen
on_idle:
timeout: !lambda "return (id(display_timeout).state * 1000);"
then:
- logger.log: "LVGL is idle"
- switch.turn_off: display_backlight
- lvgl.pause:
pages:
- id: main_page
width: 100%
bg_color: 0x000000
bg_opa: cover
widgets:
- button:
id: office_light_btn
align: CENTER
width: 200
height: 100
checkable: true
widgets:
- label:
align: CENTER
text: 'Office Light'
on_click:
- logger.log: "Toggle Button Pressed"
- homeassistant.action:
action: light.toggle
data:
entity_id: light.office_light
text_sensor:
- platform: wifi_info
ip_address:
name: IP Address
ssid:
name: Connected SSID
bssid:
name: Connected BSSID
mac_address:
name: Mac Wifi Address
scan_results:
name: Latest Scan Results
sensor:
- platform: wifi_signal
name: "WiFi Signal Sensor"
update_interval: 60s
- platform: wifi_signal # Reports the WiFi signal strength/RSSI in dB
name: "WiFi Signal dB"
id: wifi_signal_db
update_interval: 60s
entity_category: "diagnostic"
Everything is working but after the screen wakes up it take 5-10 seconds before the button will do anything. Any ideas how to speed that up?
Does anyone happen to have a basic working ESPHome example for the Waveshare 4.3" Touch Display? Iāve tried multiple selections from above but after flashing Iām getting nothing and HA is not recognizing my diplay.
This works for the 7" version. Is that what you have?
I have the 4.3" version.
try this one
substitutions:
name: waveshare-s3-touch
friendly_name: Waveshare S3 4.3
esphome:
name: "${name}"
platformio_options:
board_build.flash_mode: dio
esp32:
board: esp32-s3-devkitc-1
variant: esp32s3
framework:
type: esp-idf
sdkconfig_options:
CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240: "y"
CONFIG_ESP32S3_DATA_CACHE_64KB: "y"
CONFIG_SPIRAM_FETCH_INSTRUCTIONS: y
CONFIG_SPIRAM_RODATA: y
logger:
ch422g:
psram:
mode: octal
speed: 80MHz
i2c:
sda: 8
scl: 9
scan: true
frequency: 400kHz
touchscreen:
- platform: gt911
id: my_touchscreen
interrupt_pin: 4
reset_pin:
ch422g:
number: 1
display:
- platform: rpi_dpi_rgb
id: rpi_disp
update_interval: never
auto_clear_enabled: false
color_order: RGB
pclk_frequency: 16MHz
dimensions:
width: 800
height: 480
reset_pin:
ch422g:
number: 3
enable_pin:
ch422g:
number: 2
de_pin:
number: 5
hsync_pin:
number: 46
ignore_strapping_warning: true
vsync_pin:
number: 3
ignore_strapping_warning: true
pclk_pin: 7
hsync_back_porch: 30
hsync_front_porch: 210
hsync_pulse_width: 30
vsync_back_porch: 4
vsync_front_porch: 4
vsync_pulse_width: 4
data_pins:
red: [1, 2, 42, 41, 40]
blue: [14, 38, 18, 17, 10]
green: [39, 0, 45, 48, 47, 21]
lvgl:
Iāve flashed it and I see nothing.
Just want to make sure Iām flashing correctly. Iām holding down the boot button while powering up and then flashing with ESPHome Flasher 1.4 (Iām old fashioned and like using it). Afterwards, Iām moving the USB C cable to the USB port to power it on.
When doing so, I hear the PC Iām plugged into continually beep over and over again like the diplay is restarting.
I see nothing on the display but I can see the two red LEDs on the back and the backlight appears to be on.
Maybe Iām not following the correct flash/power on procedure?
You donāt have enough power to power it.
Get a USB brick
Yeah, Iām using a 20W USB block. Still nothingā¦
Turns out you canāt use ESPHome Flasher to flash these devicesā¦it needs to be flashed via ESPHome Web.
Thank you so much.Good.
I am trying to configure my Waveshare ESP32-S3 3.4inch capacitive display (which works fine in other scenarios) to start with as a simple display (for example to display a value from a temperature gauge elsewhere on my ESPHome system).
Here is my YAML code:
esphome:
name: esp-display-4-3
friendly_name: ESP_Display_4_3
esp32:
board: esp32s3box
framework:
type: esp-idf
Enable logging
logger:
Enable Home Assistant API
api:
encryption:
key: āā
ota:
- platform: esphome
password: āā
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: āEsp-Display-4-3 Fallback Hotspotā
password: āā
captive_portal:
display:
- platform: rpi_dpi_rgb
id: my_display
auto_clear_enabled: false
update_interval: never
color_order: RGB
pclk_frequency: 16MHz
dimensions:
width: 800
height: 480
de_pin:
number: 5
hsync_pin:
number: 46
ignore_strapping_warning: true
vsync_pin:
number: 3
ignore_strapping_warning: true
pclk_pin: 7
hsync_back_porch: 30
hsync_front_porch: 210
hsync_pulse_width: 30
vsync_back_porch: 4
vsync_front_porch: 4
vsync_pulse_width: 4
data_pins:
red:
- 1 #r3
- 2 #r4
- 42 #r5
- 41 #r6
- 40 #r7
blue:
- 14 #b3
- 38 #b4
- 18 #b5
- 17 #b6
- 10 #b7
green:
- 39 #g2
- 0 #g3
- 45 #g4
- 48 #g5
- 47 #g6
- 21 #g7
lambda: |-
it.print(0, 0, id(roboto), āHello World!ā);
font:
- file: āgfonts://Robotoā
id: roboto
size: 12
Everything seems to work: it compiles and uploads the code, initially via USB cable. I can then ping the device even when only on WiFi but the display remains steadfastly black.
Can anyone help/advise?
esphome:
name: esp-display-4-3
friendly_name: ESP_Display_4_3
esp32:
board: esp32s3box
framework:
type: esp-idf
# Enable logging
logger:
# Enable Home Assistant API
api:
encryption:
key: "Za7Or6x3kP/DknOF6uT7IFr3tLQbmdOuFtl1dAvfxEI="
ota:
- platform: esphome
password: "7c9f894bc1e58f621bdaad35a3a2ae68"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Esp-Display-4-3 Fallback Hotspot"
password: "GcQJoVjqjPrM"
captive_portal:
display:
- platform: rpi_dpi_rgb
id: my_display
auto_clear_enabled: false
update_interval: never
color_order: RGB
pclk_frequency: 16MHz
dimensions:
width: 800
height: 480
de_pin:
number: 5
hsync_pin:
number: 46
ignore_strapping_warning: true
vsync_pin:
number: 3
ignore_strapping_warning: true
pclk_pin: 7
hsync_back_porch: 30
hsync_front_porch: 210
hsync_pulse_width: 30
vsync_back_porch: 4
vsync_front_porch: 4
vsync_pulse_width: 4
data_pins:
red:
- 1 #r3
- 2 #r4
- 42 #r5
- 41 #r6
- 40 #r7
blue:
- 14 #b3
- 38 #b4
- 18 #b5
- 17 #b6
- 10 #b7
green:
- 39 #g2
- 0 #g3
- 45 #g4
- 48 #g5
- 47 #g6
- 21 #g7
lambda: |-
it.print(0, 0, id(roboto), "Hello World!");
font:
- file: "gfonts://Roboto"
id: roboto
size: 12
The resulting logs:
[17:02:04]I (314) cpu_start: Starting app cpu, en\xc4\xf8ESP-ROM:esp32s3-20210327
[17:02:04]Build:Mar 27 2021
[17:02:04]rst:0x3 (RTC_SW_SYS_RST),boot:0x8 (SPI_FAST_FLASH_BOOT)
[17:02:04]Saved PC:0x403764fb
WARNING Decoded 0x403764fb: esp_restart_noos_dig at /data/cache/platformio/packages/framework-espidf/components/esp_system/port/esp_system_chip.c:57 (discriminator 1)
[17:02:04]SPIWP:0xee
[17:02:04]mode:DIO, clock div:1
[17:02:04]load:0x3fce3818,len:0x1750
[17:02:04]load:0x403c9700,len:0x4
[17:02:04]load:0x403c9704,len:0xbe4
[17:02:04]load:0x403cc700,len:0x2d34
[17:02:04]entry 0x403c9908
[17:02:04]I (31) boot: ESP-IDF 5.1.5 2nd stage bootloader
[17:02:04]I (31) boot: compile time May 4 2025 22:16:30
[17:02:04]I (31) boot: Multicore bootloader
[17:02:04]I (34) boot: chip revision: v0.2
[17:02:04]I (38) boot.esp32s3: Boot SPI Speed : 80MHz
[17:02:04]I (43) boot.esp32s3: SPI Mode : DIO
[17:02:04]I (48) boot.esp32s3: SPI Flash Size : 8MB
[17:02:04]I (52) boot: Enabling RNG early entropy source...
[17:02:04]I (58) boot: Partition Table:
[17:02:04]I (61) boot: ## Label Usage Type ST Offset Length
[17:02:04]I (69) boot: 0 otadata OTA data 01 00 00009000 00002000
[17:02:04]I (76) boot: 1 phy_init RF data 01 01 0000b000 00001000
[17:02:04]I (83) boot: 2 app0 OTA app 00 10 00010000 001c0000
[17:02:04]I (91) boot: 3 app1 OTA app 00 11 001d0000 001c0000
[17:02:04]I (98) boot: 4 nvs WiFi data 01 02 00390000 0006d000
[17:02:04]I (106) boot: End of partition table
[17:02:04]I (110) esp_image: segment 0: paddr=001d0020 vaddr=3c0b0020 size=317fch (202748) map
[17:02:04]I (155) esp_image: segment 1: paddr=00201824 vaddr=3fc98200 size=045c4h ( 17860) load
[17:02:04]I (159) esp_image: segment 2: paddr=00205df0 vaddr=40374000 size=0a228h ( 41512) load
[17:02:04]I (170) esp_image: segment 3: paddr=00210020 vaddr=42000020 size=a0628h (656936) map
[17:02:04]I (288) esp_image: segment 4: paddr=002b0650 vaddr=4037e228 size=09f54h ( 40788) load
[17:02:04]I (306) boot: Loaded app from partition at offset 0x1d0000
[17:02:04]I (306) boot: Disabling RNG early entropy source...
[17:02:04]I (307) cpu_start: Multicore app
[17:02:04]I (311) cpu_start: Pro cpu up.
Start with a known good config from earlier in this thread. Yours appears to be missing important things like psram and a backlight, and you are using the wrong serial connector (use the one marked USB)