I2S ESP32 Stereo output two MAX98357A

Hi there, I’m trying to get two MAX98357A boards to work in stereo mode using latest ESPHome on ESP32 (devkit1). However regardless of using stereo mode argument in the code, sound from both speakers work in mono regime.

status_led:
  pin:
    number: GPIO2
    inverted: true

i2s_audio:
  - id: i2s_out
    i2s_lrclk_pin: GPIO14
    i2s_bclk_pin: GPIO27
  - id: i2s_in
    i2s_lrclk_pin: GPIO13
    i2s_bclk_pin: GPIO12

media_player:
  - platform: i2s_audio
    name: ESPHome I2S Media Player
    dac_type: external
    i2s_audio_id: i2s_out
    i2s_dout_pin: GPIO25
    mode: stereo

    
# Example configuration entry
microphone:
  - platform: i2s_audio
    i2s_audio_id: i2s_in
    i2s_din_pin: GPIO26
    adc_type: external
    id: mic_i2s
    pdm: false

voice_assistant:
  microphone: mic_i2s

I have used the following diagram to hook DAC modules (mine hooked to different pins):

Can someone holp to sort this out?

1 Like

I don’t know much if anything about these boards so I could be very wrong. :slight_smile:

But the wiring diagram shows both amp boards wired to exactly the same signal. Do you not have to toggle a pin on the board for left or right channel?

there is no such a code in ESPHome to separate left and right channels with external DAC unfortunatelly. Stereo signal carry signal separation so LRCLK can understand which channel it should decode and play.
As far as I understood, the problem might be with ESPHome itself. I might be wrong.

UPDATE: Figured out stereo output. Problem was in MAX98357A configuration. By default it is configured to mix outputs using 1M resistor (to VDD) so to configure it to left and right channels, SD needs to be pulled-up to VDD with jumper (0 Ohms) that is going to be LEFT channel and with 370-470K resistor to VDD to output Right channel.
All perfect now.
By the way I get really nice sound quality despite this is only class D amplifier.

and here is my little project printed for stereo WiFi player ))

and here is my code:

captive_portal:

status_led:
  pin:
    number: GPIO2
    inverted: true

i2s_audio:
  - id: i2s_out
    i2s_lrclk_pin: GPIO14 
    i2s_bclk_pin: GPIO27
  - id: i2s_in
    i2s_lrclk_pin: GPIO32 #ws
    i2s_bclk_pin: GPIO33 #sck

# LR to be grounded

media_player:
  - platform: i2s_audio
    name: ESPHome I2S Media Player
    dac_type: external
    i2s_audio_id: i2s_out
    i2s_dout_pin: GPIO25
    mode: stereo

    
# Example configuration entry
microphone:
  - platform: i2s_audio
    i2s_audio_id: i2s_in
    i2s_din_pin: GPIO26 #sd
    adc_type: external
    id: mic_i2s
    pdm: false

voice_assistant:
  microphone: mic_i2s
7 Likes

Would you be kind enough to share the connection diagram of the components of your I2S ESP Stereo… Thank you!

@elik745i those speakers look massive… Is the amp able to drive them nicely?
What are the specs of the speakers?

1 Like

I am also curious about those speakers.
Can you post ohms and watts?

Those were for testing purpose only! For sure to drive those you would need AMP

Great work! Would you be kind enough to share the connection diagram of the components of your I2S ESP Stereo… Thank you!

Are you using the board mentioned here. I am trying to implement something similar with esp.

The connection between DAC and esp32 chip is as given below. Please refer to my other post where I have used different DAC but the result is same. I am getting the stereo quality output.

esp32 --------- UDA1334A
VIN ------------- VIN
GND ----------- GND
GPIO25 ------- DIN
GPIO26 ------- WSEL
GPIO27 ------- BCLK

1 Like

Thank you!

Did you find a way to set the volume via I2S (i.e., via software or config)?

1 Like

Nice Details , can you share hardware wiring photos, if you do good for me, Thank you.

For Voice Assistant to work with the device, as ESP32 chip is not that powerful, it gets laggy, to mitigate it, we need to stop media player before we communicate to it. I came up with this code so far:

esphome:
  name: stereo-notifier
  friendly_name: Stereo_Notifier
  on_boot:
    priority: 600  # Ensure this runs after other setup steps
    then:
      - media_player.volume_set:
          id: media_player_speaker
          volume: 0.2
      - logger.log: "System initialized, I2S audio ready."

esp32:
  board: esp32dev
  framework:
    type: arduino

# Enable logging
logger:

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

ota:
- platform: esphome
  password: "your pass"

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

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Stereo-Notifier Fallback Hotspot"
    password: "your passwd"

captive_portal:

status_led:
  pin:
    number: GPIO2
    inverted: true

i2s_audio:
  - id: i2s_out
    i2s_lrclk_pin: GPIO14
    i2s_bclk_pin: GPIO27
  - id: i2s_in
    i2s_lrclk_pin: GPIO32
    i2s_bclk_pin: GPIO33

# I2S media player configuration (stereo mode)
media_player:
  - platform: i2s_audio
    name: ESPHome I2S Media Player
    id: media_player_speaker
    dac_type: external
    i2s_audio_id: i2s_out
    i2s_dout_pin: GPIO25
    mode: stereo

# I2S microphone configuration
microphone:
  - platform: i2s_audio
    adc_type: external
    pdm: false
    id: mic_i2s
    channel: right
    bits_per_sample: 16bit
    i2s_audio_id: i2s_in
    i2s_din_pin: GPIO26

sensor:
  - platform: internal_temperature
    name: "Internal Temperature"

voice_assistant:
  microphone: mic_i2s
  id: va
  noise_suppression_level: 2
  auto_gain: 31dBFS
  volume_multiplier: 4.0
  use_wake_word: false
  media_player: media_player_speaker

switch:
  - platform: restart
    name: "Stereo Speaker Restart"

  - platform: template
    name: Use wake word
    id: use_wake_word
    optimistic: true
    restore_mode: RESTORE_DEFAULT_ON
    entity_category: config
    on_turn_on:
      - lambda: id(va).set_use_wake_word(true);
      - if:
          condition:
            not:
              - voice_assistant.is_running
          then:
            - voice_assistant.start_continuous
    on_turn_off:
      - voice_assistant.stop
      - lambda: id(va).set_use_wake_word(false);

binary_sensor:
  - platform: status
    name: API Connection
    id: api_connection
    filters:
      - delayed_on: 1s
    on_press:
      - if:
          condition:
            switch.is_on: use_wake_word
          then:
            - voice_assistant.start_continuous:
    on_release:
      - if:
          condition:
            switch.is_on: use_wake_word
          then:
            - voice_assistant.stop:

# Automation to pause and resume voice assistant based on media playback
interval:
  - interval: 10s
    then:
      - if:
          condition:
            - media_player.is_playing:
                id: media_player_speaker
          then:
            - if:
                condition:
                  - switch.is_on: use_wake_word
                then:
                  - logger.log: "Pausing voice assistant due to media playback."
                  - voice_assistant.stop
          else:
            - if:
                condition:
                  - not:
                      media_player.is_playing:
                        id: media_player_speaker
                then:
                  - if:
                      condition:
                        - switch.is_on: use_wake_word
                      then:
                        - logger.log: "Resuming voice assistant after media playback."
                        - voice_assistant.start_continuous



1 Like

Did you check the datasheet?

Check page 17 Table 5 SD_Mode Control, use one as Left other as Right it will work, unless your audio is mono (both have same data)