Waveshare ESP32-S3-Touch-LCD-2.8C working config?

Does anybody have a working config for this board? It seems like a really nice one and it uses parts there are already drivers for.

Display Size: 2.8 inch
Resolution: 480 × 480
Communication Interface: RGB
Driver: ICST7701
Touch Interface: I2C
Touch IC: GT911

Update 03/18/2025: It’s working!!

Thanks for all the help getting this working. I added to to my git repo

It actually seems to be very similar to this one.

I have the screen and touch working. I need more testing to see if there are other issues.

The touch screen is the same as the ESP32-S3-LCD-Driver-Board but the screen is a bit different. I can’t get it working. Has anybody else tried to get this screen working with ESPHome?

ESPHome is loading fine and the touch screen is working. I just can’t get the screen to work.

Looks like maybe only a few small differences.

Show your YAML.

I started off using the code @tdack wrote for the waveshare ESP32-S3-LCD-Driver-Board. This got the board to boot, the LCD backlight working and the touch screen working.

I looked at the code demo code for the ESP32-S3-Touch-LCD-2.8C from here

https://files.waveshare.com/wiki/ESP32-S3-Touch-LCD-2.8C/ESP32-S3-Touch-LCD-2.8C-Demo.zip

It looks like most of the pinout for the screen is the same but the way they do the chip select is different. I think waveshare is using the pca9554 instead of a direct ESP32 pin for this design. I don’t quite know enough about the C code to figure it out.

esphome:
  name: esp32s3

esp32:
  board: esp32-s3-devkitc-1
  flash_size: 8MB
  variant: esp32s3
  framework:
    type: esp-idf
    sdkconfig_options:
      CONFIG_ESPTOOLPY_FLASHFREQ: "80MHz" # this is needed for flashing
      CONFIG_ESPTOOLPY_FLASHMODE_QIO: y
      CONFIG_FLASHMODE_QIO: y
      CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240: y
      CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ: '240'
      CONFIG_SPIRAM_RODATA: "y"

# Enable PSRAM on ESP32-S3
psram:
  mode: octal
  speed: 80MHz

# Enable logging
logger:

# I2C bus configuration
i2c:
  - id: i2c_bus
    sda: GPIO15
    scl: GPIO07
    scan: true

# PCA9554 GPIO extender for display reset
pca9554:
  - id: p_c_a
    address: 0x20
    i2c_id: i2c_bus

# SPI bus configuration
spi:
  - id: spi_lcd
    clk_pin: GPIO02
    mosi_pin: GPIO01
    interface: spi3


# Backlight PWM output and light component
output:
  - platform: ledc
    pin: GPIO6
    id: display_backlight_pwm
    frequency: 2000Hz
    channel: 0

light:
  - platform: monochromatic
    output: display_backlight_pwm
    id: display_backlight
    name: "Display Backlight"
    gamma_correct: 1

# ST7701S Display configuration (adjust the init_sequence to match your display)
display:
  - platform: st7701s
    id: my_display
    spi_id: spi_lcd
    spi_mode: MODE1
    # pclk_frequency: 30MHz
    color_order: bgr
    auto_clear_enabled: false
    dimensions:
      width: 480
      height: 480
    cs_pin: GPIO42
    reset_pin:
      pca9554: p_c_a
      number: 3
    de_pin: GPIO40
    hsync_pin: GPIO38
    vsync_pin: GPIO39
    pclk_pin: GPIO41
    init_sequence:
      - [ 0xFF, 0x77, 0x01, 0x00, 0x00, 0x13 ]
      - [ 0xEF, 0x08 ]
      - [ 0xFF, 0x77, 0x01, 0x00, 0x00, 0x10 ]
      - [ 0xC0, 0x3B, 0x00 ]
      - [ 0xC1, 0x10, 0x0C ]
      - [ 0xC2, 0x07, 0x0A ]
      - [ 0xC7, 0x00 ]
      - [ 0xCC, 0x10 ]
      - [ 0xCD, 0x08 ]
      - [ 0xB0, 0x05, 0x12, 0x98, 0x0E, 0x0F, 0x07, 0x07, 0x09, 0x09, 0x23, 0x05, 0x52, 0x0F, 0x67, 0x2C, 0x11 ]
      - [ 0xB1, 0x0B, 0x11, 0x97, 0x0C, 0x12, 0x06, 0x06, 0x08, 0x08, 0x22, 0x03, 0x51, 0x11, 0x66, 0x2B, 0x0F ]
      - [ 0xFF, 0x77, 0x01, 0x00, 0x00, 0x11 ]
      - [ 0xB0, 0x5D ]
      - [ 0xB1, 0x3E ]
      - [ 0xB2, 0x81 ]
      - [ 0xB3, 0x80 ]
      - [ 0xB5, 0x4E ]
      - [ 0xB7, 0x85 ]
      - [ 0xB8, 0x20 ]
      - [ 0xC1, 0x78 ]
      - [ 0xC2, 0x78 ]
      - [ 0xD0, 0x88 ]
      - [ 0xE0, 0x00, 0x00, 0x02 ]
      - [ 0xE1, 0x06, 0x30, 0x08, 0x30, 0x05, 0x30, 0x07, 0x30, 0x00, 0x33, 0x33 ]
      - [ 0xE2, 0x11, 0x11, 0x33, 0x33, 0xF4, 0x00, 0x00, 0x00, 0xF4, 0x00, 0x00, 0x00 ]
      - [ 0xE3, 0x00, 0x00, 0x11, 0x11 ]
      - [ 0xE4, 0x44, 0x44 ]
      - [ 0xE5, 0x0D, 0xF5, 0x30, 0xF0, 0x0F, 0xF7, 0x30, 0xF0, 0x09, 0xF1, 0x30, 0xF0, 0x0B, 0xF3, 0x30, 0xF0 ]
      - [ 0xE6, 0x00, 0x00, 0x11, 0x11 ]
      - [ 0xE7, 0x44, 0x44 ]
      - [ 0xE8, 0x0C, 0xF4, 0x30, 0xF0, 0x0E, 0xF6, 0x30, 0xF0, 0x08, 0xF0, 0x30, 0xF0, 0x0A, 0xF2, 0x30, 0xF0 ]
      - [ 0xE9, 0x36, 0x01 ]
      - [ 0xEB, 0x00, 0x01, 0xE4, 0xE4, 0x44, 0x88, 0x40 ]
      - [ 0xED, 0xFF, 0x10, 0xAF, 0x76, 0x54, 0x2B, 0xCF, 0xFF, 0xFF, 0xFC, 0xB2, 0x45, 0x67, 0xFA, 0x01, 0xFF ]
      - [ 0xEF, 0x08, 0x08, 0x08, 0x45, 0x3F, 0x54 ]
      - [ 0xFF, 0x77, 0x01, 0x00, 0x00, 0x00 ]
      - delay 120ms
      - [ 0x11 ]
      - delay 120ms
      - [ 0x3A, 0x66 ]
      - [ 0x36, 0x00 ]
      - [ 0x35, 0x00 ]
      - [ 0x20 ]
      - delay 120ms
      - [ 0x29 ]
    data_pins:
      red:
        - 46       #r1
        - 3        #r2
        - 8        #r3
        - 18       #r4
        - 17       #r5
      green:
        - 14       #g0
        - 13       #g1
        - 12       #g2
        - 11       #g3
        - 10       #g4
        - 9        #g5
      blue:
        - 5        #b1
        - 45       #b2
        - 48       #b3
        - 47       #b4
        - 21       #b5

# GT911 Touchscreen Controller
touchscreen:
  - platform: gt911
    id: my_touchscreen
    i2c_id: i2c_bus
    reset_pin:
      pca9554: p_c_a
      number: 1
    interrupt_pin: GPIO16
    on_update:
        - lvgl.label.update:
            id: coord_text
            text: !lambda return str_sprintf("Touch points:\n id=%d x=%d, y=%d", touches[0].id, touches[0].x, touches[0].y);
        - lambda: |-
            for (auto touch: touches)  {
                if (touch.state <= 2) {
                  ESP_LOGI("Touch points:", "id=%d x=%d, y=%d", touch.id, touch.x, touch.y);
                }
            }
    on_release:
      - if:
          condition: lvgl.is_paused
          then:
            - logger.log: "LVGL resuming"
            - lvgl.resume:
            - lvgl.widget.redraw:
            - light.turn_on: 
                id: display_backlight
                brightness: 50%

# LVGL Configuration
lvgl:
  - id: lvgl_display
    displays:
      - my_display
    widgets:
      - label:
          id: coord_text
          align: CENTER
          text_align: CENTER
          text: 'Touch the screen'
    on_idle:
      timeout: !lambda "return (id(display_timeout).state * 1000);"
      then:
        - logger.log: "LVGL is idle"
        - light.turn_off:
            id: display_backlight
        - lvgl.pause:

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

If you look at the schematic diagram in the Wiki, there is a table of pin assignments. You have the wrong pin for LCD CS

But beware, Waveshare have this annoying habit of using 1-based numbering for extender pins, so your LCD_CS pin should be PCA9554 pin 2, not 3. Same for any other of the pins on the extender. You have the wrong pin for LCD RESET (should be PCA9554 pin 0) and GPIO42 for CS which should be PCA9554 pin 2.

Check the other pin assignments against the table. I would expect the SPI mode to be 3, not 1, as that is what other st7701s devices are, but you can experiment with that. The standard init sequence might work, again you can experiment with that vs. what you have.

2 Likes

Yeah that was it. This is the final working config. I did not need to change SPI mode. Just the CS and reset pins.

As always thanks for all the help!

# waveshare-esp32-s3-touch-lcd-2.8c

esphome:
  name: esp32s3

esp32:
  board: esp32-s3-devkitc-1
  flash_size: 8MB
  variant: esp32s3
  framework:
    type: esp-idf
    sdkconfig_options:
      CONFIG_ESPTOOLPY_FLASHFREQ: "80MHz" # this is needed for flashing
      CONFIG_ESPTOOLPY_FLASHMODE_QIO: y
      CONFIG_FLASHMODE_QIO: y
      CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240: y
      CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ: '240'
      CONFIG_SPIRAM_RODATA: "y"

# Enable PSRAM on ESP32-S3
psram:
  mode: octal
  speed: 80MHz

# Enable logging
logger:

api:

web_server:
  port: 80
  version: 3 

ota:
  platform: esphome

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password 

# I2C bus configuration
i2c:
  - id: i2c_bus
    sda: GPIO15
    scl: GPIO07

# PCA9554 GPIO extender for display reset
pca9554:
  - id: p_c_a
    address: 0x20
    i2c_id: i2c_bus

# SPI bus configuration
spi:
  - id: spi_lcd
    clk_pin: GPIO02
    mosi_pin: GPIO01
    interface: spi3

# Backlight PWM output and light component
output:
    # Backlight LED
  - platform: ledc
    pin: GPIO06
    id: GPIO06
    frequency: 2000Hz
    channel: 0

light:
  - platform: monochromatic
    output: GPIO06
    name: Display Backlight
    id: display_backlight
    restore_mode: ALWAYS_ON
    gamma_correct: 1

# ST7701S Display configuration (adjust the init_sequence to match your display)
display:
  - platform: st7701s
    id: my_display
    spi_id: spi_lcd
    spi_mode: MODE1
    color_order: bgr
    auto_clear_enabled: false
    show_test_card: true
    dimensions:
      width: 480
      height: 480
    cs_pin:
      pca9554: p_c_a
      number: 2
    reset_pin:
      pca9554: p_c_a
      number: 0
    de_pin: GPIO40
    hsync_pin: GPIO38
    vsync_pin: GPIO39
    pclk_pin: GPIO41
    init_sequence:
      - [ 0xFF, 0x77, 0x01, 0x00, 0x00, 0x13 ]
      - [ 0xEF, 0x08 ]
      - [ 0xFF, 0x77, 0x01, 0x00, 0x00, 0x10 ]
      - [ 0xC0, 0x3B, 0x00 ]
      - [ 0xC1, 0x10, 0x0C ]
      - [ 0xC2, 0x07, 0x0A ]
      - [ 0xC7, 0x00 ]
      - [ 0xCC, 0x10 ]
      - [ 0xCD, 0x08 ]
      - [ 0xB0, 0x05, 0x12, 0x98, 0x0E, 0x0F, 0x07, 0x07, 0x09, 0x09, 0x23, 0x05, 0x52, 0x0F, 0x67, 0x2C, 0x11 ]
      - [ 0xB1, 0x0B, 0x11, 0x97, 0x0C, 0x12, 0x06, 0x06, 0x08, 0x08, 0x22, 0x03, 0x51, 0x11, 0x66, 0x2B, 0x0F ]
      - [ 0xFF, 0x77, 0x01, 0x00, 0x00, 0x11 ]
      - [ 0xB0, 0x5D ]
      - [ 0xB1, 0x3E ]
      - [ 0xB2, 0x81 ]
      - [ 0xB3, 0x80 ]
      - [ 0xB5, 0x4E ]
      - [ 0xB7, 0x85 ]
      - [ 0xB8, 0x20 ]
      - [ 0xC1, 0x78 ]
      - [ 0xC2, 0x78 ]
      - [ 0xD0, 0x88 ]
      - [ 0xE0, 0x00, 0x00, 0x02 ]
      - [ 0xE1, 0x06, 0x30, 0x08, 0x30, 0x05, 0x30, 0x07, 0x30, 0x00, 0x33, 0x33 ]
      - [ 0xE2, 0x11, 0x11, 0x33, 0x33, 0xF4, 0x00, 0x00, 0x00, 0xF4, 0x00, 0x00, 0x00 ]
      - [ 0xE3, 0x00, 0x00, 0x11, 0x11 ]
      - [ 0xE4, 0x44, 0x44 ]
      - [ 0xE5, 0x0D, 0xF5, 0x30, 0xF0, 0x0F, 0xF7, 0x30, 0xF0, 0x09, 0xF1, 0x30, 0xF0, 0x0B, 0xF3, 0x30, 0xF0 ]
      - [ 0xE6, 0x00, 0x00, 0x11, 0x11 ]
      - [ 0xE7, 0x44, 0x44 ]
      - [ 0xE8, 0x0C, 0xF4, 0x30, 0xF0, 0x0E, 0xF6, 0x30, 0xF0, 0x08, 0xF0, 0x30, 0xF0, 0x0A, 0xF2, 0x30, 0xF0 ]
      - [ 0xE9, 0x36, 0x01 ]
      - [ 0xEB, 0x00, 0x01, 0xE4, 0xE4, 0x44, 0x88, 0x40 ]
      - [ 0xED, 0xFF, 0x10, 0xAF, 0x76, 0x54, 0x2B, 0xCF, 0xFF, 0xFF, 0xFC, 0xB2, 0x45, 0x67, 0xFA, 0x01, 0xFF ]
      - [ 0xEF, 0x08, 0x08, 0x08, 0x45, 0x3F, 0x54 ]
      - [ 0xFF, 0x77, 0x01, 0x00, 0x00, 0x00 ]
      - delay 120ms
      - [ 0x11 ]
      - delay 120ms
      - [ 0x3A, 0x66 ]
      - [ 0x36, 0x00 ]
      - [ 0x35, 0x00 ]
      - [ 0x20 ]
      - delay 120ms
      - [ 0x29 ]
    data_pins:
      red:
        - 46       #r1
        - 3        #r2
        - 8        #r3
        - 18       #r4
        - 17       #r5
      green:
        - 14       #g0
        - 13       #g1
        - 12       #g2
        - 11       #g3
        - 10       #g4
        - 9        #g5
      blue:
        - 5        #b1
        - 45       #b2
        - 48       #b3
        - 47       #b4
        - 21       #b5
   

# GT911 Touchscreen Controller
touchscreen:
  - platform: gt911
    id: my_touchscreen
    i2c_id: i2c_bus
    reset_pin:
      pca9554: p_c_a
      number: 1
    interrupt_pin: GPIO16
    on_update:
        # - lvgl.label.update:
            # id: coord_text
            # text: !lambda return str_sprintf("Touch points:\n id=%d x=%d, y=%d", touches[0].id, touches[0].x, touches[0].y);
        - lambda: |-
            for (auto touch: touches)  {
                if (touch.state <= 2) {
                  ESP_LOGI("Touch points:", "id=%d x=%d, y=%d", touch.id, touch.x, touch.y);
                }
            }


#LVGL Configuration
# lvgl:
  # - id: lvgl_display
    # displays:
      # - my_display
    # widgets:
      # - label:
          # id: coord_text
          # align: CENTER
          # text_align: CENTER
          # text: 'Touch the screen'