ESP32-S3 3.5-inch capacitive touch IPS module 320 * 480

The partial update problem is solved, performance is now normal, even with software rotation (swapping axes in hardware does not work.)

Touchscreen supported with PR:

Here is my test project, it was realy fun to do, i make use of the alterd driver from DerHam. later i will try to see how far i will get with the alterd driver from clydebarrow.

https://github.com/ageurtse/esphome-clock

1 Like

That looks good Arnold…

2024-10-13 13.23.37

I was going to look into how to dim the backlight, you’ve done that as well :+1:

Being new to this I’ve been learning github, c++, yaml, HA and sometimes it starts doing my head in :laughing:
I stil not quite sure what to do with… pip install puremagic ?

me to, but when googling on puremagic, it has somthing to do with the #number’s from github.

to me it looks it only works on the dev version from ESPhome.
maybee clydebarrow, could explain us a bit what he did, and how to use it, so we can learn a bit from it.

Can’t get your newly updates changes to work.
I don’t know what i’m doing wrond.
where and why do i need to install puremagic.

sorry, i’m not as good with github and programming, still learning and trying to understand.

i have includes your external components but the compilers give this error, can’t make anything about it.

INFO ESPHome 2024.11.0-dev
INFO Reading configuration /config/esphome/esphome-web-220778.yaml...
ERROR Unable to import component qspi_dbi.display:
Traceback (most recent call last):
  File "/esphome/esphome/loader.py", line 177, in _lookup_module
    module = importlib.import_module(f"esphome.components.{domain}")
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<frozen importlib._bootstrap>", line 1206, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1178, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1149, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 690, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 940, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "/data/external_components/534b7061/esphome/components/qspi_dbi/display.py", line 5, in <module>
    from esphome.const import (
ImportError: cannot import name 'CONF_INIT_SEQUENCE' from 'esphome.const' (/esphome/esphome/const.py)
Failed config

display.qspi_dbi: [source /config/esphome/esphome-web-220778.yaml:316]
  
  Platform not found: 'display.qspi_dbi'.
  platform: qspi_dbi
  model: AXS15231
  data_rate: 40MHz
  dimensions: 
    height: 480
    width: 320
  cs_pin: 
    number: 45
    ignore_strapping_warning: True
  auto_clear_enabled: False
  update_interval: never
  rotation: 270

That’s because there are core changes, which the external component does not bring in. You’ll need to wait at least until it’s merged into the Dev branch, then you can use the ESPHome Dev add-on in HA. Might be a week or two, outside my control.

The alternative right now is to clone my repo and use the CLI, but it sounds like that’s not part of your skill set ATM.

I will wait a while and try it in a week or 2
The cli is one step to much at the moment.

a short update, downloaded the latest dev version off esphome 2014.11.0-dev
and running the code below works out of the box, no external components needed.

@clydebarrow thanks for the work.
@derham, thanks for the first setup with a working example
buglloc, for the very first driver

the below clock, display’s a simple clock.
the font can be download from here. https://github.com/ageurtse/esphome-clock

################################################################################
# Substitution Variables
################################################################################
substitutions:
  device_internal_name: wekker
  device_wifi_name: esphome-wekker
  device_friendly_name: WEKKER
  device_ip_address: 192.168.0.128
  device_sampling_time: 30s

################################################################################
# Globals
################################################################################
globals: 
  - id: wifi_connection
    type: bool
    restore_value: no
    initial_value: "false"

  - id: bgcolor
    type: Color
    initial_value: "Color::random_color()"

  - id: my_selection
    type: int
    initial_value: "0"
################################################################################
# Board Configuration
################################################################################
esphome:
  name: ${device_internal_name}
  friendly_name: ${device_friendly_name}
  platformio_options:
    build_flags: "-DBOARD_HAS_PSRAM"
    board_build.arduino.memory_type: qio_opi
  on_boot:
      priority: -100
      then:
      - lvgl.widget.hide: boot_screen

psram:
  mode: octal
  speed: 120MHz

esp32:
  board: esp32s3box
  variant: ESP32S3
  flash_size: 8MB
  framework:
    type: esp-idf

################################################################################
# Bluethooth tracker
################################################################################
bluetooth_proxy:

################################################################################
# Enable logging
################################################################################
logger:
  logs:
    component: NONE

################################################################################
# Enable Home Assistant API
################################################################################
api:
  reboot_timeout: 0s

################################################################################
# OTA
################################################################################
ota:
- platform: esphome

################################################################################
# WiFi
################################################################################
wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  output_power: 10
  use_address: ${device_ip_address}
  on_connect:
    - lvgl.label.update:
        id: esphome_ip_label
        text:
          format: "IP Address: %s"
          args: [ 'id(ip_address).state.c_str()' ] 
        
  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: ${device_wifi_name}
    password: !secret esphome_pwd

captive_portal:

###############################################################################
# Web Server
################################################################################
web_server:
  port: 80
  version: 2
  include_internal: true

################################################################################
# Output
################################################################################
output:
  - platform: ledc
    pin:
      number: GPIO01
    id: lcdbacklight


################################################################################
# Switch
################################################################################
switch:
  - platform: restart
    name: "Restart"
    id: device_restart
  
  - platform: safe_mode
    name: Use Safe Mode
    id: device_safe_mode

################################################################################
# Light
################################################################################
light:
  - platform: monochromatic
    output: lcdbacklight
    name: "Display Backlight"
    id: back_light
    restore_mode: ALWAYS_ON

################################################################################
# Sensors
################################################################################
sensor:
  - platform: homeassistant
    id: light_brightness
    entity_id: light.your_dimmer
    attribute: brightness

  # WiFi
  - platform: wifi_signal
    name: "WiFi Signal Sensor"
    id: ${device_internal_name}_wifi_signal_sensor
    update_interval: ${device_sampling_time}

  # Uptime
  - platform: uptime
    name: "Uptime Sensor"
    id: ${device_internal_name}_uptime_sensor
    update_interval: ${device_sampling_time}
    internal: true
    on_raw_value:
      then:
        - text_sensor.template.publish:
            id: ${device_internal_name}_uptime_human
            state: !lambda |-
              int seconds = round(id(${device_internal_name}_uptime_sensor).raw_state);
              int days = seconds / (24 * 3600);
              seconds = seconds % (24 * 3600);
              int hours = seconds / 3600;
              seconds = seconds % 3600;
              int minutes = seconds /  60;
              seconds = seconds % 60;
              return (
                (days ? to_string(days) + "d " : "") +
                (hours ? to_string(hours) + "h " : "") +
                (minutes ? to_string(minutes) + "m " : "") +
                (to_string(seconds) + "s")
              ).c_str();

################################################################################
# Interval
################################################################################
interval:
  - interval: 10s
    then:
      - if:
          condition:
            wifi.connected:
          then:
            - lambda: |-
                id(wifi_connection) = true;

          else:
            - lambda: |-
                id(wifi_connection) = false;

time:
  - platform: homeassistant
    id: esptime
    on_time:
      - minutes: "*"
        then:
          - lvgl.label.update:
              id: clock_time
              text:
                format: "%s"
                args: [ 'id(current_time).state.c_str()' ] 

################################################################################
# Text Sensors
################################################################################
text_sensor:
  - platform: wifi_info
    ip_address:
      id: ip_address
      name: "IP Address"
      entity_category: diagnostic
    ssid:
      id: ssid
      name: "Connected SSID"
      entity_category: diagnostic
    mac_address:
      id: mac_address
      name: "Mac Address"
      entity_category: diagnostic


  - platform: version
    id: esphome_version
    name: "ESPHome Version"
    hide_timestamp: true
    on_value:
      then:
        - lvgl.label.update:
            id: esphome_version_label
            text: !lambda |-
              return ("ESPHome Version: " + id(esphome_version).state).c_str();

  - platform: template
    name: "Current Time"
    id: current_time
    update_interval: 60s
    lambda: return  id(esptime).now().strftime("%H:%M");

  #-------------------------------------------------------------------------------
  # Custom Text sensors
  #-------------------------------------------------------------------------------
  - platform: template
    name: Uptime Human Readable
    id: ${device_internal_name}_uptime_human
    icon: mdi:clock-start

################################################################################
# SPI and I2C
################################################################################
spi:
  id: display_qspi
  type: quad
  clk_pin: 47
  data_pins: [21,48,40,39]

i2c:
  sda: 4
  scl: 8
  id: touchscreen_bus
  frequency: 800khz

################################################################################
# Display and Touchscreen
################################################################################
display:
  - platform: qspi_dbi
    model: CUSTOM
    data_rate: 40MHz
    dimensions:
      height: 480
      width: 320
    transform:
      mirror_x: false
      mirror_y: false
    cs_pin:
      number: 45
      ignore_strapping_warning: true
    auto_clear_enabled: false
    update_interval: never
    draw_from_origin: true
    rotation: 270
    init_sequence:

touchscreen:
  platform: axs15231
  transform:
    swap_xy: true
    mirror_x: false
    mirror_y: true

################################################################################
# Image, Fonts and color
################################################################################
image:
  - file: https://esphome.io/_static/favicon-512x512.png
    id: boot_logo
    resize: 200x200
    type: RGB565
    use_transparency: true
    
color:
  - id: my_red
    red: 100%
    green: 0%
    blue: 0%
  - id: my_pink
    red: 100%
    green: 10%
    blue: 40%
  - id: my_yellow
    red: 100%
    green: 100%
    blue: 0%
  - id: my_green
    red: 0%
    green: 100%
    blue: 0%
  - id: my_blue
    red: 0%
    green: 0%
    blue: 100%
  - id: my_gray
    red: 50%
    green: 50%
    blue: 50%
  - id: my_white
    red: 100%
    green: 100%
    blue: 100%
  - id: my_black
    red: 0%
    green: 0%
    blue: 0%

font:
  - file: "fonts/digital-dismay.regular.otf"
    id: font_std
    size: 215
    glyphs: ":0123456789"
  - file: "arial.ttf"
    id: arial_98
    size: 98
  - file: "arial.ttf"
    id: arial_96
    size: 96
  - file: "arial.ttf"
    id: arial_134
    size: 134
  - file: "arial.ttf"
    id: arial_128
    size: 128
  - file: "arial.ttf"
    id: arial_48
    size: 48
  - file: "arial.ttf"
    id: arial_36
    size: 36
  - file: "arial.ttf"
    id: arial_24
    size: 24
  - file: "arial.ttf"
    id: arial_12
    size: 12
  - file: "gfonts://Roboto"
    id: roboto10
    size: 10
    bpp: 4

################################################################################
# LVGL
################################################################################
lvgl:
  bg_color: my_black
  text_font: arial_12
  width: 320
  height: 480
  align: center
  id: screen
  style_definitions:
    - id: date_style
      align: center
      text_color: 0x000000
      bg_opa: cover
      radius: 4
      pad_all: 2

  widgets:
    - label:
        id: clock_time
        text_font: font_std
        text_color: my_red
        align: CENTER
        text: "99:99"
        
        on_press:
          - lvgl.widget.show: boot_screen

    - obj:
        id: boot_screen
        x: 0
        y: 0
        width: 100%
        height: 100%
        bg_color: 0xffffff
        bg_opa: COVER
        radius: 0
        pad_all: 0
        border_width: 0
        widgets:
          - image:
              src: boot_logo
          - spinner:
              align: CENTER
              y: 95
              height: 50
              width: 50
              spin_time: 1s
              arc_length: 60deg
              arc_width: 8
              indicator:
                arc_color: 0x18bcf2
                arc_width: 8
          - label:
              x: 200
              y: 50  
              text:
                format: "MAC Address: %s"
                args: [ 'id(mac_address).state.c_str()' ]                
          - label:
              id: esphome_ip_label
              x: 200
              y: 65  
              text:
                format: "IP Address: %s"
                args: [ 'id(ip_address).state.c_str()' ]                
          - label:
              x: 200
              y: 110  
              id: esphome_version_label           
              text:
                format: "ESPHome Version: %s"
                args: [ 'id(esphome_version).state.c_str()' ]
        on_press:
          - lvgl.widget.hide: boot_screen

Well, 1 step forward and 2 back! My demo works fine under ESPHome 2024.9.2 but something has changed at 2024.10.0 - now the touchpad coordinates are out so the buttons don’t press in the right location anymore - graphics are fine though.
You can wind back the ESPHome version using this add-on…

I tried 2024.11 but was getting strange results there as well so I think I’ll keep to 9.2, for this device, until the full release version is available.

UPDATE:
My demo project is now working fine in all rotations using Clyde’s lastest axs15231 driver in Esphome Dev env. Great, thanks for the work on this.

1 Like

Also work with micropython lvgl too:

Hi,
Do you have exemple for 7" Waveshare ( [ESP32-S3-Touch-LCD-7] because I cannot use touchscreen?

Hi, yes, I’ve uploaded this example to my github, Scroll down to the bottom of the readme page for the link.
Please don’t forget to share your code and findings so we can all learn from each other.

1 Like

I’ve started another post for the ESP32-S3-Touch-LCD-7

1 Like

I played with another microcontroller with display with the help of which I extract the data from the Home Assistant server and display them on the 7-inch display. See in this video: https://youtu.be/iKTeAz46-Ds

Tried your code on a display, that I received recently - just black screen (Model JC3248W535C_I_Y).
Using EspHome 2024.11.3
When flashed, the screen is just black, and the COM port jumps up/down on the connected windows host.
Any clue what the issue could be ?
Re-flashing with firmware file JC3248W535C_I_Y_EN-80M.bin makes the display work again (factory file)

Sometimes it helps by clearing the buid files.
Did you compile it with these settings ?

psram:
  mode: octal
  speed: 120MHz

esp32:
  board: esp32s3box
  variant: ESP32S3
  flash_size: 8MB
  framework:
    type: esp-idf

If so, you don’t get any errors or warnings ?

This should be 80MHz. 120MHz doesn’t work, just silently falls back to 40MHz, which works, but isn’t quite as fast.

1 Like

Another thing to try is using the ESPHOME website to flask the device…
https://web.esphome.io/
and use Prepare For First Use.
That might give a clue to what’s happening.
When I’ve have the USB port continually dropping out it usually means it’s crashing on boot.

1 Like