Testing T-Display-S3 with lvgl

Trying to get started with some LVGL testing on a T-Display-S3 (no touch), but the device gets into a boot loop with the minimal configuration. What am I doing wrong and does anyone have some complete examples I can learn from?

This is my current minimal config:

esphome:
  name: tdisplay-s3-lvgltesting
  friendly_name: tdisplay-s3-lvgltesting

esp32:
  board: esp32-s3-devkitc-1
  framework:
    type: esp-idf

spi:
  id: quad_spi
  type: quad
  clk_pin: 47
  data_pins:
    - 18
    - 7
    - 48
    - 5

# Enable logging
logger:

api:
  encryption:
    key: !secret api_secret

ota:
  - platform: esphome
    password: !secret ota_password

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

display:
  - platform: qspi_dbi
    id: my_display
    model: RM67162
    dimensions:
      height: 240
      width: 536
      offset_height: 0
      offset_width: 0
    transform:
      mirror_x: true
      mirror_y: false
      swap_xy: true
    color_order: rgb
    invert_colors: false
    brightness: 175
    cs_pin: 6
    reset_pin: 17
    enable_pin: 38
    auto_clear_enabled: false
    draw_from_origin: true

lvgl:

error I’m getting:

[15:59:11]ESP-ROM:esp32s3-20210327
[15:59:11][I][logger:171]: Log initialized
[15:59:11][C][safe_mode:079]: There have been 10 suspected unsuccessful boot attempts
[15:59:11][D][esp32.preferences:114]: Saving 1 preferences to flash...
[15:59:11][D][esp32.preferences:142]: Saving 1 preferences to flash: 0 cached, 1 written, 0 failed
[15:59:11][E][safe_mode:086]: Boot loop detected. Proceeding to safe mode
[15:59:11][E][component:164]: Component safe_mode set Error flag: unspecified

Just to make sure which display you are using? Do you have the T-Display S3 AMOLED V1.0 or the T-Display S3 AMOLED V2.0 or the T-Display S3 Pro or the T-Display S3 AMOLED Plus?

The T-Display S3 Pro or the T-Display S3 AMOLED Plus are totally different setups, I am linking working code for T-Display and T-Display S3 AMOLED V2.0

The code is for a blood glucose monitor display, You will need to comment out the sections for:

  - platform: homeassistant
    id: blood_sugar
    entity_id: sensor.blood_sugar_2
    accuracy_decimals: 0
    unit_of_measurement: mg/dL
    on_value:
      - lvgl.label.update:
          id: bg_level
          text:
            format: "%.0f"
            args: [x]
          text_color: !lambda |-
            if (x < 55 || x >= 260.0) return lv_color_hex(0xFF0000);
            if ((x >= 55.0 && x < 70.0) || (x >= 180.0 && x < 260.0)) return lv_color_hex(0xFFFF00);
            if (x >= 70.0 && x < 180.0) return lv_color_hex(0x00FF00);
            return lv_color_hex(0xFF00FF);

Make sure that you have the font file loaded in the config > esphome > fonts directory.

# Uses the following devices
# - LilyGo T-Display S3 AMOLED V2.0 with Touch
# - Blood_Sugar sensor from Home Assistant NightScout Integration
# touchscreen:
  # platform: cst816
# display:
  # - platform: qspi_amoled
    # model: RM67162

substitutions:
  disp_name: CGM Display Amoled

esphome:
  name: cgm-display-amoled
  friendly_name: cgm-display-amoled
  platformio_options:
    build_unflags: -Werror=all
    board_build.flash_mode: dio

esp32:
  board: esp32-s3-devkitc-1
  framework:
    type: esp-idf
    version: recommended
    sdkconfig_options:
      CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240: "y"
      CONFIG_ESP32S3_DATA_CACHE_64KB: "y"
      CONFIG_SPIRAM_FETCH_INSTRUCTIONS: y
      CONFIG_SPIRAM_RODATA: y
  flash_size: 16MB

logger:
  level: debug

api:

ota:
  platform: esphome

web_server:
  port: 80

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  manual_ip:
    static_ip: 192.168.0.34
    gateway: 192.168.0.1
    subnet: 255.255.255.0
  ap:
    ssid: "CGM Display Amoled"

spi:
  id: quad_spi
  type: quad
  clk_pin: 47
  data_pins: [18, 7, 48, 5]

i2c:
  sda: 3
  scl: 2

font:
  - file: 'fonts/arial.ttf'
    id: font1
    size: 156
    extras:
      - file: "fonts/materialdesignicons-webfont.ttf"
        glyphs: [
          "\U000F19B2", # ArrowUpThin
          "\U000F19B4", # ArrowTopRightThin
          "\U000F19B0", # ArrowRightThin
          "\U000F19B7", # ArrowBottomRightThin
          "\U000F19B3", # ArrowDownThin
          ]

  - file: 'fonts/roboto.ttf'
    id: font2
    size: 72

display:
  - platform: qspi_dbi
    model: RM67162
    id: my_display
    dimensions:
      height: 240
      width: 536
      offset_height: 0
      offset_width: 0
    transform:
      mirror_x: true
      swap_xy: true
    color_order: rgb
    brightness: 150
    cs_pin: 6
    reset_pin: 17
    enable_pin: 38
    update_interval: never
    auto_clear_enabled: false

lvgl:
  displays:
    - my_display

  pages:
    - id: main_page
      bg_color: 0X000000
      widgets:
        - label:
            id: trend_dir
            align: TOP_RIGHT
            pad_right: 55
            text_color: 0XFFFFFF
            text_font: font1
            text: " "
        - label:
            id: bg_level
            align: TOP_LEFT
            pad_left: 55
            text_font: font1
            text_color: 0x00FF00
            text: " "
        - label:
            id: my_time_label
            align: BOTTOM_MID
            text_color: 0XFFFFFF 
            text_font: font2
            text: " "

psram:
  mode: octal

time:
  - platform: homeassistant
    id: esptime
    on_time_sync:
      then:
        - lvgl.label.update:
            id: my_time_label
            text:
              time_format: "%I : %M %p"
              time: !lambda return id(esptime).now();
    on_time:
      - minutes: '*'
        seconds: 0
        then:
          - lvgl.label.update:
              id: my_time_label
              text:
                time_format: "%I : %M %p"
                time: !lambda return id(esptime).now();

switch:
  - platform: restart
    name: ${disp_name} Restart  

sensor: 
  - platform: wifi_signal
    name: ${disp_name} WiFi Status
    update_interval: 10s

  - platform: homeassistant
    id: blood_sugar
    entity_id: sensor.blood_sugar_2
    accuracy_decimals: 0
    unit_of_measurement: mg/dL
    on_value:
      - lvgl.label.update:
          id: bg_level
          text:
            format: "%.0f"
            args: [x]
          text_color: !lambda |-
            if (x < 55 || x >= 260.0) return lv_color_hex(0xFF0000);
            if ((x >= 55.0 && x < 70.0) || (x >= 180.0 && x < 260.0)) return lv_color_hex(0xFFFF00);
            if (x >= 70.0 && x < 180.0) return lv_color_hex(0x00FF00);
            return lv_color_hex(0xFF00FF);

text_sensor:
  - platform: homeassistant
    id: bg_direction
    entity_id: sensor.blood_sugar_2
    attribute: direction
    on_value:
      - lvgl.label.update:
          id: trend_dir
          text: !lambda |-
            if (x == "Flat") return "\U000F19B0";
            if (x == "SingleDown") return "\U000F19B3";
            if (x == "FortyFiveDown") return "\U000F19B7";
            if (x == "SingleUp") return "\U000F19B2";
            if (x == "FortyFiveUp") return "\U000F19B4";
            return " ";
  - platform: wifi_info
    ip_address:
      name: ESP IP Address
    ssid:
      name: ESP Connected SSID
    mac_address:
      name: ESP Mac Wifi Address

captive_portal:
    
# Uses the following devices
# - Lilygo T-Display s3-Pro
# - Blood_Sugar sensor from Home Assistant NightScout Integration
# touchscreen:
  # platform: CST226
# display:
  # - platform: ili9xxx
    # model: st7796
  # This display uses color_order: bgr
  # This display uses invert_colors: true

substitutions:
  disp_name: CGM T-Display S3 Pro1

esphome:
  name: cgm-display-s3-pro1
  friendly_name: cgm-display-s3-pro1
  platformio_options:
    build_unflags: -Werror=all
    board_build.flash_mode: dio
  on_boot:
    then:
      - output.set_level:
          id: gpio_48_backlight_pwm
          level: 50%

esp32:
  board: esp32-s3-devkitc-1
  framework:
    type: esp-idf
    version: recommended
    sdkconfig_options:
      CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240: "y"
      CONFIG_ESP32S3_DATA_CACHE_64KB: "y"
      CONFIG_SPIRAM_FETCH_INSTRUCTIONS: y
      CONFIG_SPIRAM_RODATA: y
  flash_size: 16MB

logger:
  level: DEBUG

api:

ota:
  - platform: esphome

web_server:
  port: 80

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  manual_ip:
    static_ip: 192.168.0.198
    gateway: 192.168.0.1
    subnet: 255.255.255.0
  ap:
    ssid: ${disp_name} Fallback

i2c:
  sda: 5
  scl: 6
  scan: false
  id: i2c_bus

spi:
  # cs_pin: 40
  miso_pin: 8
  mosi_pin: 17
  clk_pin: 18

psram:
  speed: 80MHz
  mode: octal

font:
  - file: 'fonts/arial.ttf'
    id: font1
    size: 144
    extras:
      - file: "fonts/materialdesignicons-webfont.ttf"
        glyphs: [
          "\U000F19B2", # ArrowUpThin
          "\U000F19B4", # ArrowTopRightThin
          "\U000F19B0", # ArrowRightThin
          "\U000F19B7", # ArrowBottomRightThin
          "\U000F19B3", # ArrowDownThin
          ]

  - file: 'fonts/roboto.ttf'
    id: font2
    size: 60

display:
  - platform: ili9xxx
    model: ST7796
    cs_pin: 39
    dc_pin: 9
    reset_pin: 47
    id: my_display
    data_rate: 2MHz
    dimensions:
      height: 222
      width: 480
      offset_width: 0
      offset_height: 49
    transform:
      mirror_y: false
      mirror_x: false
      swap_xy: true
    color_order: bgr
    invert_colors: true
    update_interval: never
    auto_clear_enabled: false

lvgl:
  displays:
    - my_display

  pages:
    - id: main_page
      bg_color: 0X000000
      widgets:
        - label:
            id: trend_dir
            align: TOP_RIGHT
            pad_top: 2
            text_color: 0XFFFFFF 
            text_font: font1
            text: " "
        - label:
            id: bg_level
            align: TOP_MID
            pad_top: 2
            text_font: font1
            text_color: 0x00FF00
            text: " "
        - label:
            id: my_time_label
            align: BOTTOM_MID
            text_color: 0XFFFFFF 
            text_font: font2
            text: " "

switch:
  - platform: restart
    name: ${disp_name} Restart  

time:
  - platform: homeassistant
    id: esptime
    on_time_sync:
      then:
        - lvgl.label.update:
            id: my_time_label
            text:
              time_format: "%I : %M %p"
              time: !lambda return id(esptime).now();
    on_time:
      - minutes: '*'
        seconds: 0
        then:
          - lvgl.label.update:
              id: my_time_label
              text:
                time_format: "%I : %M %p"
                time: !lambda return id(esptime).now();

output:
  - platform: ledc
    pin: 48
    id: gpio_48_backlight_pwm
    min_power: 0.25 # Any lower the Backlight Flashes
    max_power: 0.4

light:
  - platform: monochromatic
    output: gpio_48_backlight_pwm
    name: "Display Backlight"
    id: back_light
    restore_mode: always_on

sensor: 
  - platform: wifi_signal
    name: ${disp_name} WiFi Status
    update_interval: 10s
  - platform: homeassistant
    id: blood_sugar
    entity_id: sensor.blood_sugar_2
    accuracy_decimals: 0
    unit_of_measurement: mg/dL
    on_value:
      - lvgl.label.update:
          id: bg_level
          text:
            format: "%.0f"
            args: [x]
          text_color: !lambda |-
            if (x < 55 || x >= 260.0) return lv_color_hex(0xFF0000);
            if ((x >= 55.0 && x < 70.0) || (x >= 180.0 && x < 260.0)) return lv_color_hex(0xFFFF00);
            if (x >= 70.0 && x < 180.0) return lv_color_hex(0x00FF00);
            return lv_color_hex(0xFF00FF);

text_sensor:
  - platform: homeassistant
    id: bg_direction
    entity_id: sensor.blood_sugar_2
    attribute: direction
    on_value:
      - lvgl.label.update:
          id: trend_dir
          text: !lambda |-
            if (x == "Flat") return "\U000F19B0";
            if (x == "SingleDown") return "\U000F19B3";
            if (x == "FortyFiveDown") return "\U000F19B7";
            if (x == "SingleUp") return "\U000F19B2";
            if (x == "FortyFiveUp") return "\U000F19B4";
            return " ";
  - platform: wifi_info
    ip_address:
      name: ESP IP Address
    ssid:
      name: ESP Connected SSID
    mac_address:
      name: ESP Mac Wifi Address

sy6970:
  i2c_id: i2c_bus
  state_led_enable: false

external_components:
  - source: github://buglloc/esphome-components
    components: [ sy6970 ]

captive_portal: