ESP32-S3 Arduino LVGL WIFI&Bluetooth Development Board 4.0 "480 * 480 Smart Display 4.0 inch LCD TFT Module Capacitive Touch

https://www.aliexpress.com/item/1005006318227573.html?spm=a2g0o.order_list.order_list_main.5.20de1802UBmBZy

Just to see how this works, I bought this 4" display. Idea is to place it in the living room and enable it to switch lights on and off (and dim). And more, if I finally understand how to make this thing intelligent.

So, I got ESPhome installed and got the device functional (online).

Any ideas how I get it to show something?
Like a light switch?

Much appreciated!

1 Like

Good luck. They don’t even list what display module it is.

Hopefully it is one of these: https://esphome.io/index.html#touchscreen-components

get anywhere on it yet? I’ve seen these and was tempted to get one to try out, but figured it was a huge longshot to get esphome on it given that afaik esphome cannot do anything with a fancy gui interface like it needs.

Does the shop don’t know what type of display it is? It’s a nice device that is not to expensive

The model of the module/board in the description on Ali Ex is: ESP32-4848S040 and a search for that indicates the display driver chip is a ST7701.

So no ESPHome at this stage.

Looks like there is in tasmota already code to get the display working

Hello all, a month after my initial post I’m still at the same point, didn’t have much time to furter play with it. I did see a post somewhere where the OS was replaced with an Android version (8 I believe) which than was used to run the HA app (with the Kiosk app to control on/off etc. if you like). When I have time, I will take a look and see if that will work on this device. I will also look into the github suggestion by kroonen.

I got one of these and it’s a very cool little screen and very cheap ($25). It’s powered by 120v and has a relay to control a light.

I got it working fairly quickly using openHASP and their Guition ESP32-S3-4848S040 image. This is the info

That image says
Flash:16 MB
Display:ST7701S
Touch: GT911

This page also has a lot of info on this screen

ESPhome Supports ST7701S and GT911 so it’s just a matter of getting a config file for this device. I don’t know quite enough to get it all working.

1 Like

I took a wrack at getting this working. Based on these other projects that got it working already there is a lot on information available on this screen. I created the code below with all the info I gathered about the pinout but it doesn’t build.

Anybody see what I’m missing?

esphome:
  name: esp32s3
  friendly_name: esp32s3

esp32:
  board: esp32-s3-devkitc-1
  framework:
    type: esp-idf
  flash_size: 16MB    

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "75BPcrp4DpO6QMWcvUiQuZMml5ePMk7AidkCzTWx9VY="

ota:
  password: "b94b562281f06b5162bfe38b47d6f8f5"

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

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Esp32S3 Fallback Hotspot"
    password: "UT27cXnwGaSk"

captive_portal:

font:
  - file: "gfonts://Roboto"
    id: roboto30
    size: 30

spi:
  clk_pin: 48
  mosi_pin: 47


display:
  - platform: st7701s
    auto_clear_enabled: false
    update_interval: never
    spi_mode: MODE3
    color_order: RGB
    dimensions:
      width: 480
      height: 480
    invert_colors: true
    transform:
      mirror_x: true
      mirror_y: true
    cs_pin: 39
    de_pin: 18
    hsync_pin: 16
    vsync_pin: 17
    pclk_pin: 21
    init_sequence:
      - 1 # select canned init sequence number 1
      - [ 0xE0, 0x1F ]  # Set sunlight readable enhancement
    data_pins:
      red:
        - 4         #r1
        - 3         #r2
        - 2         #r3
        - 1         #r4
        - 0         #r5
      green:
        - 10        #g0
        - 9         #g1
        - 8         #g2
        - 7         #g3
        - 6         #g4
        - 5         #g5
      blue:
        - 15        #b1
        - 14        #b2
        - 13        #b3
        - 12        #b4
        - 11        #b5
    lambda: |-
      it.print(0, 0, id(roboto30), Color(55, 183, 220), TextAlign::TOP_LEFT, "Hello World!");	

I managed to get it building, but there is no output on the display.

I`m using esphome 2024.4.0 dev.

I don’t have the device myself, but looking into it. But, I don’t see where you setup the blacklight pin. The backlight enable is located on the gpio expander chip exio2 per the schematic with the LCD reset pin. That doesn’t look like it’s in the esphome per this GitHub issue Support for WCH(Jiangsu Qin Heng) CH422G I/O Expander · Issue #2671 · esphome/feature-requests · GitHub

There is quite some info on this device in the following zip file:
ZFile and select the 4.0inch version.
Probably you’ve already seen this file, but just to be sure…
It;s a great screen, so I hope that it will work with HASS some day.

I got the display to almost work fine :slight_smile:
Here my configuration

captive_portal:

time:
  - platform: homeassistant
    timezone: "Australia/Melbourne"
    id: esptime

# Need to turn on backlight as by default is not on
output:
  - platform: ledc
    pin: 38
    id: gpio_38_backlight_pwm
light:
  - platform: monochromatic
    output: gpio_38_backlight_pwm
    name: "Display Backlight"
    id: back_light
    restore_mode: ALWAYS_ON

psram:
  mode: octal
  speed: 80MHz

spi:
  clk_pin: 48
  mosi_pin: 47
  miso_pin: 41

display:
  - platform: st7701s
    spi_mode: MODE3
    color_order: bgr
    dimensions:
      width: 480
      height: 480
    cs_pin: 39
    de_pin: 18
    hsync_pin: 16
    hsync_pulse_width: 8
    hsync_front_porch: 1
    hsync_back_porch: 1
    vsync_pin: 17
    vsync_pulse_width: 8
    vsync_front_porch: 1
    vsync_back_porch: 1
    pclk_pin: 21
    #pclk_frequency: 8MHz
    #pclk_inverted: false
    update_interval: 1s
    auto_clear_enabled: false
    data_rate: 1MHz
    init_sequence:
      - 1 # select canned init sequence number 1
      - [ 0xE0, 0x1F ]  # Set sunlight readable enhancement
    data_pins:
      red:
        - 4         #r1
        - 5         #r2
        - 6         #r3
        - 7         #r4
        - 15         #r5
      green:
        - 8        #g0
        - 20         #g1
        - 3         #g2
        - 46         #g3
        - 9         #g4
        - 10         #g5
      blue:
        - 11        #b1
        - 12        #b2
        - 13        #b3
        - 14        #b4
        - 0        #b5
    lambda: |-
      auto blue = Color(255, 0, 0);
      auto green = Color(0, 255, 0);
      auto red = Color(0, 0, 255);
      it.rectangle(230, 230, 100, 100, green);
      it.rectangle(231, 231, 98, 98, red);
      it.rectangle(231, 232, 96, 96, red);
      it.rectangle(233, 233, 94, 94, green);
      it.rectangle(30, 30, 100, 100, green);
      it.rectangle(31, 31, 98, 98, green);
      it.rectangle(32, 32, 96, 96, green);
      it.rectangle(33, 33, 94, 94, green);
      it.rectangle(34, 34, 92, 92, green);
      it.rectangle(35, 35, 90, 90, green);

2 Likes

Using the above configuration my device just goes into a boot loop displaying this in the ESP log:

SPIWP:0xee
mode:QIO, clock div:1
load:0x3fce3808,len:0x1658
ets_loader.c 78 
ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0x10 (RTCWDT_RTC_RST),boot:0x18 (SPI_FAST_FLASH_BOOT)
SPIWP:0xee
mode:QIO, clock div:1
load:0x3fce3808,len:0x1658
ets_loader.c 78 
ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0x7 (TG0WDT_SYS_RST),boot:0x18 (SPI_FAST_FLASH_BOOT)
Saved PC:0x400454d5
SPIWP:0xee
mode:QIO, clock div:1
load:0x3fce3808,len:0x1658
ets_loader.c 78

Here with the touchscreen working as well:



captive_portal:

time:
  - platform: homeassistant
    timezone: "Australia/Melbourne"
    id: esptime

# Need to turn on backlight as by default is not on
output:
  - platform: ledc
    pin: 38
    id: gpio_38_backlight_pwm
light:
  - platform: monochromatic
    output: gpio_38_backlight_pwm
    name: "Display Backlight"
    id: back_light
    restore_mode: ALWAYS_ON

sensor:
  - platform: uptime
    name: "$devicename Uptime"
  - platform: wifi_signal
    name: "$devicename WiFi Signal"
    update_interval: 60s 
  - platform: homeassistant
    id: devils_ivy_moisture
    entity_id: sensor.flower_care_moisture
  - platform: homeassistant
    id: outdoor_temperature
    entity_id: sensor.temperature_humidity_sensor_f402_temperature

# Example configuration entry
i2c:
  - id: bus_a
    sda: 19
    scl: 45
    scan: false
    frequency: 10kHz

psram:
  mode: octal
  speed: 80MHz

spi:
  clk_pin: 48
  mosi_pin: 47
  miso_pin: 41

font:
  - file: 'fonts/arial.ttf'
    id: font_16
    size: 16
  - file: 'fonts/arial.ttf'
    id: font_24
    size: 24
  - file: 'fonts/arial.ttf'
    id: font_32
    size: 32

color:
  - id: my_red
    red: 100%
    green: 1%
    blue: 1%
  - id: my_green
    red: 3%
    green: 100%
    blue: 5%
  - id: my_blue
    red: 3%
    green: 5%
    blue: 100%
  - id: my_white
    red: 100%
    green: 100%
    blue: 100%
  - id: my_black
    red: 1%
    green: 1%
    blue: 1%

touchscreen:
  platform: gt911
  id: touchscreen_4_inches
  i2c_id: bus_a
  on_touch:
    then:
      - display.page.show_next: display_4_inches
      - component.update: display_4_inches
      - logger.log: "Touch, go to next page"

display:
  - platform: st7701s
    id: display_4_inches
    spi_mode: MODE3
    color_order: bgr
    #invert_colors: true
    dimensions:
      width: 480
      height: 480
    cs_pin: 39
    de_pin: 18
    hsync_pin: 16
    hsync_pulse_width: 9
    hsync_front_porch: 10
    hsync_back_porch: 50
    vsync_pin: 17
    vsync_pulse_width: 9
    vsync_front_porch: 10
    vsync_back_porch: 20
    pclk_pin: 21
    #pclk_frequency: 8MHz
    #pclk_inverted: false
    update_interval: never
    auto_clear_enabled: false
    #data_rate: 75kHz
    #init_sequence:
    #  - 1 # select canned init sequence number 1
    #  - [ 0xE0, 0x1F ]  # Set sunlight readable enhancement
    data_pins:
      blue:
        - 11        #b1
        - 12        #b2
        - 13        #b3
        - 14        #b4
        - 0        #b5
      green:
        - 8        #g0
        - 20         #g1
        - 3         #g2
        - 46         #g3
        - 9         #g4
        - 10         #g5
      red:
        - 4         #r1
        - 5         #r2
        - 6         #r3
        - 7         #r4
        - 15         #r5
    pages:
      - id: page1
        lambda: |-
          it.filled_rectangle(0, 0, 241, 241, my_black);
          it.strftime(120,70, id(font_24), id(my_blue), TextAlign::CENTER, "%A %b %d", id(esptime).now());
          it.strftime(120,120, id(font_32), TextAlign::CENTER, "%I:%M %p", id(esptime).now());
          it.printf(120, 170, id(font_32), id(my_green), TextAlign::CENTER, "Now: %.1f°", id(outdoor_temperature).state);
          it.circle(120, 120, 117, id(my_white));
          it.circle(120, 120, 118, id(my_white));
      - id: page2
        lambda: |-
          it.filled_rectangle(0, 0, 241, 241, my_black);
          it.print(120, 100, id(font_32),  id(my_white), TextAlign::CENTER, "Zanzibar Gem");
          it.printf(120, 150, id(font_32), id(my_green), TextAlign::CENTER, "%.1f %%", id(devils_ivy_moisture).state);
          if (id(devils_ivy_moisture).state>15) {
            it.circle(120, 120, 115, id(my_green));
            it.circle(120, 120, 116, id(my_green));
            it.circle(120, 120, 117, id(my_green));
            it.circle(120, 120, 118, id(my_green));
            it.circle(120, 120, 119, id(my_green));
            it.circle(120, 120, 120, id(my_green));
          } else {
            it.circle(120, 120, 115, id(my_red));
            it.circle(120, 120, 116, id(my_red));
            it.circle(120, 120, 117, id(my_red));
            it.circle(120, 120, 118, id(my_red));
            it.circle(120, 120, 119, id(my_red));
            it.circle(120, 120, 120, id(my_red));
          }

Sorry, nOOb question.

I’ve flashed the right Tosmato version, but where should I paste the config txt? Not in the HASS config file it seems.

This file is for ESPhome not Tosmato.

There is no way, Android will ever run on an ESP32 chip. The information you found applies to a device that is called “Sonoff NSPanel Pro” that looks the same but sells for close to $100. The NSPannel Pro has an ARM chips inside. (Like the chip in youe phone) With this ESP32-based device, if you want it to do graphics, you will have to write grapics software

openHASP uses LVGL to render widget & pictures. Works quite well on the ESP32-S3 4 inch module. Still exploring what is possible with this device.
A screenshot of the thermostat page:
thermostat

1 Like

Boot loop with my board too:

[23:56:47]ESP-ROM:esp32s3-20210327
[23:56:47]Build:Mar 27 2021
[23:56:47]rst:0x7 (TG0WDT_SYS_RST),boot:0x18 (SPI_FAST_FLASH_BOOT)
[23:56:47]Saved PC:0x400454d5
[23:56:47]SPIWP:0xee
[23:56:47]mode:QIO, clock div:1
[23:56:47]load:0x3fce3808,len:0x1658
[23:56:47]ets_loader.c 78 
[23:56:47]ESP-ROM:esp32s3-20210327
[23:56:47]Build:Mar 27 2021
[23:56:47]rst:0x10 (RTCWDT_RTC_RST),boot:0x18 (SPI_FAST_FLASH_BOOT)
[23:56:47]SPIWP:0xee
[23:56:47]mode:QIO, clock div:1
[23:56:47]load:0x3fce3808,len:0x1658
[23:56:47]ets_loader.c 78 
[23:56:48]ESP-ROM:esp32s3-20210327
[23:56:48]Build:Mar 27 2021
[23:56:48]rst:0x7 (TG0WDT_SYS_RST),boot:0x18 (SPI_FAST_FLASH_BOOT)
[23:56:48]Saved PC:0x400454d5
[23:56:48]SPIWP:0xee
[23:56:48]mode:QIO, clock div:1
[23:56:48]load:0x3fce3808,len:0x1658
[23:56:48]ets_loader.c 78

I’d like to understand why it works for some people but not for us.

YAML config

esphome:
  name: 480x480
  friendly_name: 480x480

esp32:
  board: esp32-s3-devkitc-1
  framework:
    type: esp-idf
    version: recommended
    # Custom sdkconfig options
    sdkconfig_options:
      COMPILER_OPTIMIZATION_SIZE: y
    # Advanced tweaking options
    advanced:
      ignore_efuse_mac_crc: false

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "**************************"

ota:
  password: "7267d8b91c798f050f17d37473c2aedc"

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

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "480X480 Fallback Hotspot"
    password: "c5Zlxtp2uTme"

captive_portal:

time:
  - platform: homeassistant
    timezone: "Europe/Paris"
    id: esptime

# Need to turn on backlight as by default is not on
output:
  - platform: ledc
    pin: 38
    id: gpio_38_backlight_pwm
light:
  - platform: monochromatic
    output: gpio_38_backlight_pwm
    name: "Display Backlight"
    id: back_light
    restore_mode: ALWAYS_ON

sensor:
  - platform: uptime
    name: "$devicename Uptime"
  - platform: wifi_signal
    name: "$devicename WiFi Signal"
    update_interval: 60s 
  - platform: homeassistant
    id: devils_ivy_moisture
    entity_id: sensor.flower_care_moisture
  - platform: homeassistant
    id: outdoor_temperature
    entity_id: sensor.temperature_humidity_sensor_f402_temperature

# Example configuration entry
i2c:
  - id: bus_a
    sda: 19
    scl: 45
    scan: false
    frequency: 10kHz

psram:
  mode: octal
  speed: 80MHz

spi:
  clk_pin: 48
  mosi_pin: 47
  miso_pin: 41

font:
  - file: 'fonts/arial.ttf'
    id: font_16
    size: 16
  - file: 'fonts/arial.ttf'
    id: font_24
    size: 24
  - file: 'fonts/arial.ttf'
    id: font_32
    size: 32

color:
  - id: my_red
    red: 100%
    green: 1%
    blue: 1%
  - id: my_green
    red: 3%
    green: 100%
    blue: 5%
  - id: my_blue
    red: 3%
    green: 5%
    blue: 100%
  - id: my_white
    red: 100%
    green: 100%
    blue: 100%
  - id: my_black
    red: 1%
    green: 1%
    blue: 1%

touchscreen:
  platform: gt911
  id: touchscreen_4_inches
  i2c_id: bus_a
  on_touch:
    then:
      - display.page.show_next: display_4_inches
      - component.update: display_4_inches
      - logger.log: "Touch, go to next page"

display:
  - platform: st7701s
    id: display_4_inches
    spi_mode: MODE3
    color_order: bgr
    #invert_colors: true
    dimensions:
      width: 480
      height: 480
    cs_pin: 39
    de_pin: 18
    hsync_pin: 16
    hsync_pulse_width: 9
    hsync_front_porch: 10
    hsync_back_porch: 50
    vsync_pin: 17
    vsync_pulse_width: 9
    vsync_front_porch: 10
    vsync_back_porch: 20
    pclk_pin: 21
    #pclk_frequency: 8MHz
    #pclk_inverted: false
    update_interval: never
    auto_clear_enabled: false
    #data_rate: 75kHz
    #init_sequence:
    #  - 1 # select canned init sequence number 1
    #  - [ 0xE0, 0x1F ]  # Set sunlight readable enhancement
    data_pins:
      blue:
        - 11        #b1
        - 12        #b2
        - 13        #b3
        - 14        #b4
        - 0        #b5
      green:
        - 8        #g0
        - 20         #g1
        - 3         #g2
        - 46         #g3
        - 9         #g4
        - 10         #g5
      red:
        - 4         #r1
        - 5         #r2
        - 6         #r3
        - 7         #r4
        - 15         #r5
    pages:
      - id: page1
        lambda: |-
          it.filled_rectangle(0, 0, 241, 241, my_black);
          it.strftime(120,70, id(font_24), id(my_blue), TextAlign::CENTER, "%A %b %d", id(esptime).now());
          it.strftime(120,120, id(font_32), TextAlign::CENTER, "%I:%M %p", id(esptime).now());
          it.printf(120, 170, id(font_32), id(my_green), TextAlign::CENTER, "Now: %.1f°", id(outdoor_temperature).state);
          it.circle(120, 120, 117, id(my_white));
          it.circle(120, 120, 118, id(my_white));
      - id: page2
        lambda: |-
          it.filled_rectangle(0, 0, 241, 241, my_black);
          it.print(120, 100, id(font_32),  id(my_white), TextAlign::CENTER, "Zanzibar Gem");
          it.printf(120, 150, id(font_32), id(my_green), TextAlign::CENTER, "%.1f %%", id(devils_ivy_moisture).state);
          if (id(devils_ivy_moisture).state>15) {
            it.circle(120, 120, 115, id(my_green));
            it.circle(120, 120, 116, id(my_green));
            it.circle(120, 120, 117, id(my_green));
            it.circle(120, 120, 118, id(my_green));
            it.circle(120, 120, 119, id(my_green));
            it.circle(120, 120, 120, id(my_green));
          } else {
            it.circle(120, 120, 115, id(my_red));
            it.circle(120, 120, 116, id(my_red));
            it.circle(120, 120, 117, id(my_red));
            it.circle(120, 120, 118, id(my_red));
            it.circle(120, 120, 119, id(my_red));
            it.circle(120, 120, 120, id(my_red));
          }