ESP32-S3 4.3inch Capacitive Touch Display from - waveshare

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 :confused:

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!