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

1 Like

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'

Hello, sorry to ask for help here, but I haven’t found a solution through Google or ChatGPT.
I’m using an ESP32-S3-Touch-LCD-1.28 display. It works well with Arduino code, but I’d like to migrate to ESPHome.
Would I be lucky enough to get your help? Thank you very much!

There are not that many screens that use the GC9A01A display chip. So you’re probably going to have an uphill battle getting this working. Have you considered using the Waveshare ESP32-S3-Touch-LCD-2.8C? It’s a lot bigger!

If you really want to get the one you have start a new thread with the name of the screen. Posting about a different screen then a post is about is very confusing!!

Post all the info you have on the screen such as what touch controller and screen chip it uses.

Also take a look at this thread.

This screen has a similar video chip to yours. it may work.

1 Like

ok thank you Andrew.

I have the 2.1" version of this display. viz : https://www.waveshare.com/wiki/ESP32-S3-Touch-LCD-2.1

Can’t seem to get text to display on the screen. It works with the Arduino demo though. I have found the touchscreen device is actually CST820 and seems to work fine and sends coordinates to debug UART ok.

Using the latest version of Esphome. lvgl version seems to be 8.4 from build logs.

log :

[12:50:53][C][pca9554:048]: PCA9554:
[12:50:53][C][pca9554:048]:   I/O Pins: 8
[12:50:53][C][pca9554:052]:   Address: 0x20
[12:50:53][C][logger:246]: Logger:
[12:50:53][C][logger:246]:   Max Level: DEBUG
[12:50:53][C][logger:246]:   Initial Level: DEBUG
[12:50:53][C][logger:252]:   Log Baud Rate: 115200
[12:50:53][C][logger:252]:   Hardware UART: USB_SERIAL_JTAG
[12:50:53][C][logger:259]:   Task Log Buffer Size: 768
[12:50:53][C][i2c.idf:083]: I2C Bus:
[12:50:53][C][i2c.idf:084]:   SDA Pin: GPIO15
[12:50:53][C][i2c.idf:084]:   SCL Pin: GPIO7
[12:50:53][C][i2c.idf:084]:   Frequency: 50000 Hz
[12:50:53][C][i2c.idf:094]:   Recovery: bus successfully recovered
[12:50:53][I][i2c.idf:104]: Results from bus scan:
[12:50:53][I][i2c.idf:110]: Found device at address 0x20
[12:50:53][I][i2c.idf:110]: Found device at address 0x51
[12:50:53][I][i2c.idf:110]: Found device at address 0x6B
[12:50:53][C][spi:069]: SPI bus:
[12:50:53][C][spi:070]:   CLK Pin: GPIO2
[12:50:53][C][spi:071]:   SDI Pin: 
[12:50:53][C][spi:072]:   SDO Pin: GPIO1
[12:50:53][C][spi:077]:   Using HW SPI: SPI3_HOST
[12:50:53][C][ledc.output:151]: Output:
[12:50:53][C][ledc.output:152]:   Pin GPIO6
[12:50:53][C][ledc.output:153]:   Channel: 0
[12:50:53][C][ledc.output:153]:   PWM Frequency: 2000.0 Hz
[12:50:53][C][ledc.output:153]:   Phase angle: 0.0°
[12:50:53][C][ledc.output:153]:   Bit depth: 14
[12:50:53][C][light:092]: Light 'Display Backlight'
[12:50:53][C][light:094]:   Default Transition Length: 1.0s
[12:50:53][C][light:094]:   Gamma Correct: 1.00
[12:50:53][C][psram:016]: PSRAM:
[12:50:53][C][psram:019]:   Available: YES
[12:50:53][C][psram:021]:   Size: 8192 KB
[12:50:53][C][:179]: ST7701S RGB LCD
[12:50:53][C][display.st7701s:180]:   Height: 480
[12:50:53][C][display.st7701s:180]:   Width: 480
[12:50:53][C][display.st7701s:184]:   CS Pin: 2 via PCA9554
[12:50:53][C][display.st7701s:186]:   DE Pin: GPIO40
[12:50:53][C][display.st7701s:187]:   Reset Pin: 0 via PCA9554
[12:50:53][C][display.st7701s:190]:   Data pin 0: GPIO11
[12:50:53][C][display.st7701s:190]:   Data pin 1: GPIO10
[12:50:53][C][display.st7701s:190]:   Data pin 2: GPIO9
[12:50:53][C][display.st7701s:190]:   Data pin 3: GPIO5
[12:50:53][C][display.st7701s:190]:   Data pin 4: GPIO45
[12:50:53][C][display.st7701s:190]:   Data pin 5: GPIO48
[12:50:53][C][display.st7701s:190]:   Data pin 6: GPIO47
[12:50:53][C][display.st7701s:190]:   Data pin 7: GPIO21
[12:50:53][C][display.st7701s:190]:   Data pin 8: GPIO46
[12:50:53][C][display.st7701s:190]:   Data pin 9: GPIO3
[12:50:53][C][display.st7701s:190]:   Data pin 10: GPIO8
[12:50:53][C][display.st7701s:190]:   Data pin 11: GPIO18
[12:50:53][C][display.st7701s:190]:   Data pin 12: GPIO17
[12:50:53][C][display.st7701s:190]:   Data pin 13: GPIO14
[12:50:53][C][display.st7701s:190]:   Data pin 14: GPIO13
[12:50:53][C][display.st7701s:190]:   Data pin 15: GPIO12
[12:50:53][C][display.st7701s:191]:   SPI Data rate: 1MHz
[12:50:53][C][cst816.touchscreen:074]: CST816 Touchscreen:
[12:50:53][C][cst816.touchscreen:075]:   Address: 0x15
[12:50:53][C][cst816.touchscreen:076]:   Interrupt Pin: GPIO16
[12:50:53][C][cst816.touchscreen:077]:   Reset Pin: 1 via PCA9554
[12:50:53][C][cst816.touchscreen:078]:   X Raw Min: 0, X Raw Max: 480
[12:50:53][C][cst816.touchscreen:078]:   Y Raw Min: 0, Y Raw Max: 480
[12:50:53][C][cst816.touchscreen:106]:   Chip type: CST820
[12:50:53][C][lvgl:088]: LVGL:
[12:50:53][C][lvgl:088]:   Display width/height: 480 x 480
[12:50:53][C][lvgl:088]:   Buffer size: 100%
[12:50:53][C][lvgl:088]:   Rotation: 0
[12:50:53][C][lvgl:088]:   Draw rounding: 2
[12:50:53][C][web_server:310]: Web Server:
[12:50:53][C][web_server:310]:   Address: esp32s3.local:80
[12:50:53][C][esphome.ota:073]: Over-The-Air updates:
[12:50:53][C][esphome.ota:073]:   Address: esp32s3.local:3232
[12:50:53][C][esphome.ota:073]:   Version: 2
[12:50:53][C][safe_mode:018]: Safe Mode:
[12:50:53][C][safe_mode:019]:   Boot considered successful after 60 seconds
[12:50:53][C][safe_mode:019]:   Invoke after 10 boot attempts
[12:50:53][C][safe_mode:019]:   Remain for 300 seconds
[12:50:53][C][api:207]: API Server:
[12:50:53][C][api:207]:   Address: esp32s3.local:6053
[12:50:53][C][api:217]:   Using noise encryption: NO
[12:50:53][C][mdns:122]: mDNS:
[12:50:53][C][mdns:122]:   Hostname: esp32s3

yaml :

# 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: XXXXXXXXXXXXXXXXXXXX
  password: XXXXXXXXXX

# 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
    #update_interval: never
    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
   

# CST820 Touchscreen Controller
touchscreen:
  - platform: cst816
    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'

Backlight works and is dimmable from the web UI but no text. IO table in the schematic seems to be the same as the 2.8 version.

Did you manage to get this working? I’m considering getting the same display.

Yes. You’ll need to use this snippet :

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

display:
  - platform: st7701s
    id: screen
    spi_mode: MODE0
    data_rate: 40Mhz #10MHz # 40Mhz
    color_order: RGB
    auto_clear_enabled: false
    update_interval: never
    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
    #ignore_strapping_warning: true
    pclk_frequency: 16Mhz #15Mhz #30MHz  VERY Important to set to 16Mhz otherwise get tearing.
    pclk_inverted: false
    hsync_pulse_width: 8 #10
    hsync_back_porch:  10
    hsync_front_porch: 50 #10 
    vsync_pulse_width:  3 #2
    vsync_back_porch:  8 #12
    vsync_front_porch: 8 #14
    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
    init_sequence:
      # Reference: wireless-tag sample code: 
      # https://github.com/wireless-tag-com/ZX2D10GE01R-V4848/blob/ad21b3659527618fdd752cc0801b0a36f6c5e52c/main/screen.c
      - [0xFF, 0x77, 0x01, 0x00, 0x00, 0x13]    # CMD2_BKSEL (command bank select BK3, BK func enabled)
      - [0xEF, 0x08]
      - [0xFF, 0x77, 0x01, 0x00, 0x00, 0x10]    # CMD2_BKSEL (command bank select BK0, BK func disabled)
      - [0xC0, 0x3B, 0x00]                      # Scan line
      - [0xC1, 0x0B, 0x02]                      # VBP
      - [0xC2, 0x07, 0x02]
      - [0xCC, 0x10]
      - [0xCD, 0x08]                            # RGB format | ?565??? 666??
      - [0xB0, 0x00, 0x11, 0x16, 0x0e, 0x11, 0x06, 0x05, 0x09, 0x08, 0x21, 0x06, 0x13, 0x10, 0x29, 0x31, 0x18]   # IPS | 255 | 251 | 247 down | 239 | 231 | 203 | 175 | 147 | 108 | 80 | 52 | 24 | 16 | 8 down | 4 | 0
      - [0xB1, 0x00, 0x11, 0x16, 0x0e, 0x11, 0x07, 0x05, 0x09, 0x09, 0x21, 0x05, 0x13, 0x11, 0x2a, 0x31, 0x18]   # IPS | 255 | 251 | 247 down | 239 | 231 | 203 | 175 | 147 | 108 | 80 | 52 | 24 | 16 | 8 down | 4 | 0
      - [0xFF, 0x77, 0x01, 0x00, 0x00, 0x11]
      - [0xB0, 0x6d]                            # VOP  3.5375+ *x 0.0125 | 5D
      - [0xB1, 0x37]                            # VCOM amplitude setting
      - [0xB2, 0x81]                            # VGH Voltage setting | 12V
      - [0xB3, 0x80]
      - [0xB5, 0x43]                            # VGL Voltage setting | -8.3V
      - [0xB7, 0x85]
      - [0xB8, 0x20]
      - [0xC1, 0x78]
      - [0xC2, 0x78]
      - [0xD0, 0x88]
      - [0xE0, 0x00, 0x00, 0x02]
      - [0xE1, 0x03, 0xA0, 0x00, 0x00, 0x04, 0xA0, 0x00, 0x00, 0x00, 0x20, 0x20]
      - [0xE2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
      - [0xE3, 0x00, 0x00, 0x11, 0x00]
      - [0xE4, 0x22, 0x00]
      - [0xE5, 0x05, 0xEC, 0xA0, 0xA0, 0x07, 0xEE, 0xA0, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
      - [0xE6, 0x00, 0x00, 0x11, 0x00]
      - [0xE7, 0x22, 0x00]
      - [0xE8, 0x06, 0xED, 0xA0, 0xA0, 0x08, 0xEF, 0xA0, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
      - [0xEB, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00]
      - [0xED, 0xFF, 0xFF, 0xFF, 0xBA, 0x0A, 0xBF, 0x45, 0xFF, 0xFF, 0x54, 0xFB, 0xA0, 0xAB, 0xFF, 0xFF, 0xFF]
      - [0xEF, 0x10, 0x0D, 0x04, 0x08, 0x3F, 0x1F]
      - [0xFF, 0x77, 0x01, 0x00, 0x00, 0x13]    # CMD2_BKSEL (command bank select BK3, BK func enabled)
      - [0xEF, 0x08]
      - [0xFF, 0x77, 0x01, 0x00, 0x00, 0x00]    # CMD2_BKSEL (command bank select BK0, BK func disabled)
      - [0x36, 0x00]                            # MADCTL_CMD (already in esphome ST7701S::write_init_sequence_)
      - [0x3A, 0x66]                            # COLMOD 55/50=16bit(RGB565); 66=18bit(RGB666); 77?????3AH?=24bit(RGB888)
      # - [0x11]                                  # SLEEP_OUT (already in esphome)
      # - delay 120ms
      # - [0x29]                                  # DISPLAY_ON (already in esphome)
      # - delay 20ms
      #

# CST820 Touchscreen Controller
touchscreen:
  - platform: cst816
    calibration:
      x_min: 0
      x_max: 430  # touchscreen is non linear on LHS!
      y_min: 0
      y_max: 480
    id: my_touchscreen
    i2c_id: i2c_bus
    reset_pin:
      pca9554: p_c_a
      number: 1
    interrupt_pin: GPIO16

FYI in my case my touchscreen is non-linear on the left hand side. I had to poor over the provided sample code source to work this out.

1 Like

Thanks for this. I ordered my display yesterday and look forward to trying this out.
What do you mean when you say the touchscreen is non-linear?

Bottom left and top right in particular in my case do not report correct coordinates and seems uncorrectable via calibration. If you use big buttons it may not matter.

I’ll keep that in mind and see if I have the same issue. Thanks!

1 Like

I have the 2.8" version of that screen working and a library built for it.

I like it better because it’s bigger!

Hi all, apologies to resurrect an old thread but this is the closest I’ve got to getting my Waveshare 2.1" working!

I’ve taken the snippet kindly provided by wineds above but am still getting nothing on the display. The device boots and connects to Home Assistant, the backlight is working and can be switched.

This is my full YAML code, if you have a moment, could you cast your eyes over it and tell me if there is something obviously wrong!?

Thanks!

esphome:
  name: desk-round-display-21--left
  friendly_name: Desk Round Display 2.1 - Left
  on_boot:
    priority: 800
    then:
      - switch.turn_on: backlight_sw

esp32:
  board: esp32-s3-devkitc-1
  flash_size: 8MB
  variant: esp32s3
  framework:
    type: esp-idf
    sdkconfig_options:
      CONFIG_ESPTOOLPY_FLASHFREQ: "80MHz"
      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"

psram:
  mode: octal
  speed: 80MHz

logger:
  baud_rate: 0        # use USB-CDC, not UART
  level: DEBUG        # or VERY_VERBOSE if you want all the firehose

api:
  encryption:
    key: "<<REDACTED>>"

ota:
  - platform: esphome
    password: "<<REDACTED>>"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  ap:
    ssid: "Desk-Round-Display-21--Left"
    password: "<<REDACTED>>"

captive_portal:

# I2C for touch + IO expander
i2c:
  - id: i2c_bus
    sda: GPIO15
    scl: GPIO07           
    scan: true
    frequency: 400kHz
# --- SPI for the ST7701S command bus (3-wire: CLK/MOSI/CS) ---
spi:
  - id: spi_lcd
    clk_pin: GPIO02      # LCD_SCL
    mosi_pin: GPIO01     # LCD_SDA
    interface: spi3    
    #mode: MODE3

# PCA/TCA9554 (EXIO pins)
pca9554:
  - id: p_c_a
    address: 0x20
    i2c_id: i2c_bus

# Backlight control (GPIO6)
switch:
  - platform: gpio
    id: backlight_sw
    pin: GPIO6
    name: "Backlight"
    restore_mode: ALWAYS_ON
  
color:
  - id: my_light_red
    red: 100%
    green: 20%
    blue: 25%
    white: 0%

display:
  - platform: st7701s
    id: screen
    spi_mode: MODE0
    data_rate: 40Mhz #10MHz # 40Mhz
    color_order: RGB
    auto_clear_enabled: false
    update_interval: never
    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
    #ignore_strapping_warning: true
    pclk_frequency: 16Mhz #15Mhz #30MHz  VERY Important to set to 16Mhz otherwise get tearing.
    pclk_inverted: false
    hsync_pulse_width: 8 #10
    hsync_back_porch:  10
    hsync_front_porch: 50 #10 
    vsync_pulse_width:  3 #2
    vsync_back_porch:  8 #12
    vsync_front_porch: 8 #14
    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
    init_sequence:
      # Reference: wireless-tag sample code: 
      # https://github.com/wireless-tag-com/ZX2D10GE01R-V4848/blob/ad21b3659527618fdd752cc0801b0a36f6c5e52c/main/screen.c
      - [0xFF, 0x77, 0x01, 0x00, 0x00, 0x13]    # CMD2_BKSEL (command bank select BK3, BK func enabled)
      - [0xEF, 0x08]
      - [0xFF, 0x77, 0x01, 0x00, 0x00, 0x10]    # CMD2_BKSEL (command bank select BK0, BK func disabled)
      - [0xC0, 0x3B, 0x00]                      # Scan line
      - [0xC1, 0x0B, 0x02]                      # VBP
      - [0xC2, 0x07, 0x02]
      - [0xCC, 0x10]
      - [0xCD, 0x08]                            # RGB format | ?565??? 666??
      - [0xB0, 0x00, 0x11, 0x16, 0x0e, 0x11, 0x06, 0x05, 0x09, 0x08, 0x21, 0x06, 0x13, 0x10, 0x29, 0x31, 0x18]   # IPS | 255 | 251 | 247 down | 239 | 231 | 203 | 175 | 147 | 108 | 80 | 52 | 24 | 16 | 8 down | 4 | 0
      - [0xB1, 0x00, 0x11, 0x16, 0x0e, 0x11, 0x07, 0x05, 0x09, 0x09, 0x21, 0x05, 0x13, 0x11, 0x2a, 0x31, 0x18]   # IPS | 255 | 251 | 247 down | 239 | 231 | 203 | 175 | 147 | 108 | 80 | 52 | 24 | 16 | 8 down | 4 | 0
      - [0xFF, 0x77, 0x01, 0x00, 0x00, 0x11]
      - [0xB0, 0x6d]                            # VOP  3.5375+ *x 0.0125 | 5D
      - [0xB1, 0x37]                            # VCOM amplitude setting
      - [0xB2, 0x81]                            # VGH Voltage setting | 12V
      - [0xB3, 0x80]
      - [0xB5, 0x43]                            # VGL Voltage setting | -8.3V
      - [0xB7, 0x85]
      - [0xB8, 0x20]
      - [0xC1, 0x78]
      - [0xC2, 0x78]
      - [0xD0, 0x88]
      - [0xE0, 0x00, 0x00, 0x02]
      - [0xE1, 0x03, 0xA0, 0x00, 0x00, 0x04, 0xA0, 0x00, 0x00, 0x00, 0x20, 0x20]
      - [0xE2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
      - [0xE3, 0x00, 0x00, 0x11, 0x00]
      - [0xE4, 0x22, 0x00]
      - [0xE5, 0x05, 0xEC, 0xA0, 0xA0, 0x07, 0xEE, 0xA0, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
      - [0xE6, 0x00, 0x00, 0x11, 0x00]
      - [0xE7, 0x22, 0x00]
      - [0xE8, 0x06, 0xED, 0xA0, 0xA0, 0x08, 0xEF, 0xA0, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
      - [0xEB, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00]
      - [0xED, 0xFF, 0xFF, 0xFF, 0xBA, 0x0A, 0xBF, 0x45, 0xFF, 0xFF, 0x54, 0xFB, 0xA0, 0xAB, 0xFF, 0xFF, 0xFF]
      - [0xEF, 0x10, 0x0D, 0x04, 0x08, 0x3F, 0x1F]
      - [0xFF, 0x77, 0x01, 0x00, 0x00, 0x13]    # CMD2_BKSEL (command bank select BK3, BK func enabled)
      - [0xEF, 0x08]
      - [0xFF, 0x77, 0x01, 0x00, 0x00, 0x00]    # CMD2_BKSEL (command bank select BK0, BK func disabled)
      - [0x36, 0x00]                            # MADCTL_CMD (already in esphome ST7701S::write_init_sequence_)
      - [0x3A, 0x66]                            # COLMOD 55/50=16bit(RGB565); 66=18bit(RGB666); 77?????3AH?=24bit(RGB888)
      # - [0x11]                                  # SLEEP_OUT (already in esphome)
      # - delay 120ms
      # - [0x29]                                  # DISPLAY_ON (already in esphome)
      # - delay 20ms
      #

    lambda: |-
      it.fill(my_light_red);
      it.circle(20, 40, 10);
      it.filled_circle(20, 75, 10);

# CST820 Touchscreen Controller
touchscreen:
  - platform: cst816
    calibration:
      x_min: 0
      x_max: 430  # touchscreen is non linear on LHS!
      y_min: 0
      y_max: 480
    id: my_touchscreen
    i2c_id: i2c_bus
    reset_pin:
      pca9554: p_c_a
      number: 1
    interrupt_pin: GPIO16

@RexNoctis Sounds like you are using a different screen then the one this thread is for.

Start a new topic with the exact model number of your screen and we can help you get it working.