ESP32 S3 Box3

I know there have been mixed results with getting the touchscreen (gt911) working, and with some hints from another post (can’t find it at the moment) that did some research in the datasheet, where the default address is 0x5D, but it’s actually selectable at init-time utilizing both the reset_pin and interrupt_pin to tell the chip which address it should use. The problem is that the reset_pin (LCD_RST, GPIO48+inverted) is shared between both the LCD panel and the CTP. I’ve tried various combinations of setting reset_pin in the ili9xxx driver, setting it in the gt911 driver, setting it in both using allow_other_uses: true, and not setting it in either driver.

Ultimately what was most stable was not setting it in either, however we then have a race condition where sometimes the interrupt pin just happens to be high at time of init, and sometimes it happens to be low. And that determines which i2c address the touchpanel will use. You can see the result of that flakiness if you enable i2c.scan, where sometimes it reports:

 [i2c.idf:100]: Found i2c device at address 0x18
 [i2c.idf:100]: Found i2c device at address 0x40
 [i2c.idf:100]: Found i2c device at address 0x5D <-- touchscreen (primary)
 [i2c.idf:100]: Found i2c device at address 0x68

and sometimes it reports:

 [i2c.idf:100]: Found i2c device at address 0x14 <-- touchscreen (alternate)
 [i2c.idf:100]: Found i2c device at address 0x18
 [i2c.idf:100]: Found i2c device at address 0x40
 [i2c.idf:100]: Found i2c device at address 0x68

This causes the touchscreen to work only some of the time, depending on the state of GPIO3 at boot.

To work around that, I added an on_boot automation that does the same check that i2c.scan does, in order to discover which address is active, and explicitly set the i2c address to whichever one responds. The result appears to be that it now successfully initializes regardless of which address was selected on startup.

  on_boot: 
    # Execute this after i2c_bus init, and before touchscreen init. Priorities are:
    # i2c:  BUS = 1000
    # ili9xxx LCD: HARDWARE = 800
    # gt911 CTP: (default) DATA = 600
    priority: 900
    then:
      # Address the race condition between LCD and Touchscreen, where the "real" i2c address
      # for the touchscreen is determined at init, by utilizing the interrupt_pin and reset_pin.
      # However, if we set reset_pin on either component (both need the same pin), then each init
      # corrupts the other. Not initializing the pin as part of component setup means the real
      # address could randomly switch at boot time.
      # To account for that, this checks each i2c address the same way that i2c.scan works. So if
      # 0x5d writes successfully, we'll use that, otherwise we use the fallback.
      - lambda: |-
          if (id(bus_a).writev(0x5d, nullptr, 0, true) == 0) {
            ESP_LOGCONFIG("gt911", "Setting gt911 address to 0x5d");
            id(gt911_touchscreen).set_i2c_address(0x5d);
            # id(gt911_i2c_address).publish_state("0x5d"); # template text_sensor for debugging
          } else if (id(bus_a).writev(0x14, nullptr, 0, true) == 0) {
            ESP_LOGCONFIG("gt911", "Setting gt911 address to 0x14");
            id(gt911_touchscreen).set_i2c_address(0x14);
            # id(gt911_i2c_address).publish_state("0x14");
          } else {
            ESP_LOGW("gt911", "Could not verify either i2c address!");
            # id(gt911_i2c_address).status_set_warning("Could not determine i2c address!");
          }

And this appears to work correctly every time now.

The espressif code and arduino code appear to do this also, by having the gt911 driver simply fall back automatically (tries 0x5d first, and if that fails, it switches to 0x14). But as the gt911 is not specific to the s3-box(3), it wouldn’t make sense to do that in the gt911 component, at least not without adding a fallback address in the config, and I was trying to avoid modifying the component itself.

A better solution would be to figure out the right way to make ili9xx and gt911 play nice together, and/or add an option for gt911 to fallback to 0x14 if 0x5d fails.

# This is the optional debugging template text sensor mentioned above.
text_sensor:
  - platform: template
    name: GT911 i2c address
    id: gt911_i2c_address
    internal: false
    disabled_by_default: true
    entity_category: diagnostic

Has anyone else found a better solution to this? Or do most people just not bother with the touchscreen? FWIW I’m not currently using the voice-assistant package yaml due to the issues with esp-adf for audio and mic, and other issues with all those external_components being unstable and outdated. So I’m just using it as plain esphome with lvgl.

1 Like

Hi, my box has always had this problem. I had to reboot every time so that my touch screen would work.

Hi all,
im try to determine why I cannot update my ESP32 S3 box to 2025.2.

the config fails with this:

Failed config

audio_adc.es7210: [source /data/packages/dec89df9/esp32-s3-box-3/esp32-s3-box-3.yaml:139]
  
  Too many candidates found for 'i2c_id' type 'i2c::I2CBus' Some are 'bus_a', 'bus_b'.
  platform: es7210
  id: es7210_adc
  bits_per_sample: 16.0
  sample_rate: 16000
  mic_gain: 24.0
  address: 0x40
audio_dac.es8311: [source /data/packages/dec89df9/esp32-s3-box-3/esp32-s3-box-3.yaml:145]
  
  Too many candidates found for 'i2c_id' type 'i2c::I2CBus' Some are 'bus_a', 'bus_b'.
  platform: es8311
  id: es8311_dac
  bits_per_sample: 16.0
  sample_rate: 48000
  mic_gain: 42DB
  use_mclk: True
  use_microphone: False
  address: 0x18

my entire yaml is here

any help would be appreciated, thanks.

I think that you assign more i2c busses then that there are available. If I recall well then there are 2 i2c busses and the mic and the speaker are using those

Today I updated my HA in SynologY VM to the latest build and while updating my ESP32 S3 Box 3 devices (M5Stack Atom Echo) I encountered non-validated errors.

Home Assistant

  • Core 2025.2.5
  • Supervisor 2025.02.1
  • Operating System 14.2
  • Frontend 20250221.0

ESPHome Device Builder (beta) (2025.2.0)

ESP32 S3 Box 3 Voice Assistant
Device info
voice-assistant
by esphome
Firmware: 24.7.4.1 (ESPHome 2024.10.0)
Hardware: 24.7.4.1

Validate esp32-s3-box-3.yaml :x:

INFO ESPHome 2025.2.0
INFO Reading configuration /config/esphome/esp32-s3-box-3.yaml...
INFO Updating https://github.com/esphome/esphome.git@pull/5230/head
WARNING GPIO0 is a strapping PIN and should only be used for I/O with care.
Attaching external pullup/down resistors to strapping pins can cause unexpected failures.
See https://esphome.io/guides/faq.html#why-am-i-getting-a-warning-about-strapping-pins
Failed config

image: [source /data/packages/c46f54c1/voice-assistant/esp32-s3-box-3.yaml:350]
  - file: https://github.com/idodov/esp32-s3-box-3/raw/main/fallout/error.png
    id: casita_error
    resize: 320x240
    
    Image type RGB24 is removed; replace with 'type: RGB'.
    type: RGB24
    
    [use_transparency] is an invalid option for [image]. Did you mean [transparency]?
    use_transparency: True
  - file: https://github.com/idodov/esp32-s3-box-3/raw/main/fallout/idle.png
    id: casita_idle
    resize: 320x240
    type: RGB24
    use_transparency: True

M5Stack Atom Echo
atom-echo-voice-assistant
by m5stack
Firmware: 24.7.24 (ESPHome 2024.10.0)
Hardware: 1.0

Validate m5stack-atom-echo-80b520.yaml :x:

INFO ESPHome 2025.2.0
INFO Reading configuration /config/esphome/m5stack-atom-echo-80b520.yaml...
INFO Updating https://github.com/esphome/esphome.git@pull/5230/head
INFO Updating https://github.com/jesserockz/esphome-components.git@None
Failed config

light.esp32_rmt_led_strip: [source /data/packages/c46f54c1/voice-assistant/m5stack-atom-echo.yaml:211]
  platform: esp32_rmt_led_strip
  id: led
  name: None
  disabled_by_default: True
  entity_category: config
  pin: GPIO27
  default_transition_length: 0s
  chipset: SK6812
  num_leds: 1
  rgb_order: grb
  
  This feature is not available for the IDF framework version 5.
  rmt_channel: 0
  effects: 
    - pulse:

hi I saw your message there were updates of esphome and especially esp32s3box3 I can give an address its new code is the following address ESP32-S3-Box3-Custom-ESPHome/s3b.yaml at b5c4a30ab1e9e406d1d72747b8446284dc26b784 · BigBobbas/ESP32-S3-Box3-Custom-ESPHome · GitHub but for the M5Stack Atom Echo this address wake-word-voice-assistants/m5stack-atom-echo/m5stack-atom-echo.yaml at 5a2aff4b9a85ffef728a65666cd40badc8791ef3 · esphome/wake-word-voice-assistants · GitHub

1 Like

Yes, If you are Using the dock for the Box 3, you habe two i2c Busses.

One is used by the mic & speaker and programmed Into the Firmware Itself - but without having a Bus ID.

That will cause the issue If you are adding the i2c config Intro your customized config (for the Radar and dht Sensor).

The Firmware should Cover this Case, but I did nothing Had the time to create an issue for this yet

1 Like

I ended up using Bob’s latest yaml (updated days ago) and this is giving me all the functionality I had plus much much more and with no error messages this time.

Happy with this resolution.

1 Like

Thanks for chiming in and for the links with updated codes. Will have a look at them and do some testing.

I managed to make my sd card reader work on my esp32s3box3 it displays the data well but in the esphome documentation it does not allow you to read a file is there a solution for example to read an audio file thank you

You have to assign your adc and dac node to the i2c interface with i2c_id: <your bus id>.
See for example: ES7210 — ESPHome

1 Like

anyone have any idea what i need to do here?

src/esphome/components/adf_pipeline/media_player/adf_media_player.cpp: In member function 'virtual void esphome::esp_adf::ADFMediaPlayer::control(const esphome::media_player::MediaPlayerCall&)':
src/esphome/components/adf_pipeline/media_player/adf_media_player.cpp:99:12: error: enumeration value 'MEDIA_PLAYER_COMMAND_ENQUEUE' not handled in switch [-Werror=switch]
     switch (call.get_command().value()) {
            ^
src/esphome/components/adf_pipeline/media_player/adf_media_player.cpp:99:12: error: enumeration value 'MEDIA_PLAYER_COMMAND_REPEAT_ONE' not handled in switch [-Werror=switch]
src/esphome/components/adf_pipeline/media_player/adf_media_player.cpp:99:12: error: enumeration value 'MEDIA_PLAYER_COMMAND_REPEAT_OFF' not handled in switch [-Werror=switch]
src/esphome/components/adf_pipeline/media_player/adf_media_player.cpp:99:12: error: enumeration value 'MEDIA_PLAYER_COMMAND_CLEAR_PLAYLIST' not handled in switch [-Werror=switch]
cc1plus: some warnings being treated as errors
*** [.pioenvs/esp32-s3-box-3-641324/src/esphome/components/adf_pipeline/media_player/adf_media_player.o] Error 1

Can you link to this latest yaml please?

thanks you!

Hi :slight_smile:

Has anyone tried to implement usb_host of the dock and what are GPIO?

Is this ok to use on a esp32-s3-box (non box 3) or I do risk bricking something?

EDIT: Ok I managed to make it run changing some GPIOs. Still missing the touchscreen tho.

1 Like

I’ve been merrily running my ESP32-S3-BOX-3s with ESPHome 2024.4.x for nearly a year, so decided today to try updating ESPHome and the esphome.voice-assistant script to the latest versions. As expected, I can’t get it to work. The whole chain seems to work until the box is meant to play the voice response, which fails. The error I’m seeing is exactly as described in this issue: Error mediaplayer no audio response after upgrading esp32-s3-box-3 with esphome 2025.2 · Issue #72 · esphome/wake-word-voice-assistants · GitHub

I cannot figure out what network settings need altering to get this to work with the latest versions of everything. I’m running HA, ESPHome, Piper and Whisper in docker containers (all “latest” tags). My “local network” IP in the HA GUI is correct (http://192.168.1.89:8123) and I can play the generated voice files (“Media URL” in the ESP32-S3-BOX-3’s logs) directly, but the assistant box cannot:

[12:19:24][D][esp-idf:000][ann_read]: E (1885756) esp-tls: [sock=61] select() timeout

[12:19:24][D][esp-idf:000][ann_read]: E (1885759) transport_base: Failed to open a new connection: 32774

[12:19:24][D][esp-idf:000][ann_read]: E (1885762) HTTP_CLIENT: Connection failed, sock < 0

[12:19:24][E][speaker_media_player.pipeline:112]: Media reader encountered an error: ESP_ERR_HTTP_CONNECT

My ESP config is:

substitutions:
  name: ha-voice-2
  friendly_name: HA Voice 2
  micro_wake_word_model: hey_jarvis

packages:
  esphome.voice-assistant: github://esphome/wake-word-voice-assistants/esp32-s3-box-3/esp32-s3-box-3.yaml@main

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

My HA config has the following (I doubt all of these are necessary):

http:
  use_x_forwarded_for: true
  trusted_proxies:
     - 127.0.0.1
       # Host IP:
     - 192.168.1.89
       # Home Assistant network gateway IP:
     - 172.19.0.1
       # Reverse proxy docker IP:
     - 172.27.1.2

I checked the logs of HA, Piper, Whsiper, and ESPHome and none of them show any issues when trying a command, although maybe they would if I enabled debug logging on each of them? It just annoys me so much how difficult this is. Is there any up-to-date documentation regarding this? Does port 32774 need to be open somewhere with these newer versions? My firewall logs show nothing being blocked during a voice command.

My unupdated device still works fine, so something must have changed in either ESPHome or the package that has caused this to break.