ESP32-A1S Audio Kit Media Player

I recently picked up a couple of ESP32-A1S Audio Kits from Amazon and have been playing with them for a bit. I figure it might be helpful if someone condensed some of the information about this board.

Amazon Link, AliExpress Link

If you have a 3D Printer, here’s a pretty good case for you to print/modify: EdwardKrayer’s github
I am using these speakers: 8 ohm 1W speakers with JST connectors
I also picked up this battery: 3.7V 3700mAh Battery – I’m still waiting on this to arrive.

My hope is that this can be supported in ESPHome like the RaspiMuse Proto or the M5Stack Speaker Kit or at least this might be helpful for someone who wants to play with this board a bit. Hopefully this isn’t too redundant.

The A1S Audio Kit boards I have are marked V2.2 with A210 on one board and 3895 on the other. On both the A1S module has B238 printed on the back. From what I can tell, there are older boards that use a different codec and older revisions have different GPIO assignments, but this appears to be the current version and matches up with AI Thinker’s (current) spec sheets and documentation.

The ESP32-A1S Audio kit can function as a media player in ESPhome, but only using the internal speakers. Headphone jacks don’t seem to output audio. If you’ve got some little speakers to attach to the JST connectors, this config will work (Thanks to @egwent @ra.jeevan and @hareeshmu for the help with this):

esphome:
  name: esp32-audio-kit
 
esp32:
  board: esp-wrover-kit
  framework:
    type: arduino
 
logger:
api:

ota:
 

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

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "ssid"
    password: "pass"
 
captive_portal:
i2c:
  sda: GPIO33
  scl: GPIO32
 
external_components:
  - source: github://pr#3552
    components: [es8388]
    refresh: 0s
 
es8388:
media_player:
  - platform: i2s_audio
    name: "ESP32 Audio Kit"
    i2s_lrclk_pin: GPIO25
    i2s_dout_pin: GPIO26
    i2s_bclk_pin: GPIO27
    dac_type: external
    mode: stereo

 
switch:
  - platform: gpio
    pin: GPIO21
    name: "AMP Switch"
    restore_mode: ALWAYS_ON

    
binary_sensor:
  - platform: gpio
    pin:
      number: GPIO39
      inverted: true
      mode:
        input: true
    name: "Jack Status"

  - platform: gpio
    pin:
      number: GPIO036
      inverted: true
    name: "Key 1"
    filters:
      - delayed_off: 10ms

  - platform: gpio
    pin:
      number: GPIO013
      inverted: true
    name: "Key 2"
    filters:
      - delayed_off: 10ms

  - platform: gpio
    pin:
      number: GPIO019
      inverted: true
    name: "Key 3"
    filters:
      - delayed_off: 10ms
      
  - platform: gpio
    pin:
      number: GPIO023
      inverted: true
      mode:
        input: true
        pullup: true
    name: "Key 4"
    filters:
      - delayed_off: 10ms
      
  - platform: gpio
    pin:
      number: GPIO018
      inverted: true
      mode:
        input: true
        pullup: true
    name: "Key 5"
    filters:
      - delayed_off: 10ms
      
  - platform: gpio
    pin:
      number: GPIO005
      inverted: true
      mode:
        input: true
        pullup: true
    name: "Key 6"
    filters:
      - delayed_off: 10ms

light:
  - platform: binary
    name: "Test LED 1"
    output: light_output_1
  - platform: binary
    name: "Test LED 2"
    output: light_output_2
 
output:
  - id: light_output_1
    platform: gpio
    pin: GPIO22
    inverted: true
  - id: light_output_2
    platform: gpio
    pin: GPIO19
    inverted: true

The other way to get this to work in HomeAssistant is via Squeezelite-ESP32. To do that, go here:

  1. sle118’s Squeezelite-ESP32 Installer

  2. Then set up the wifi on the Squeezelite box and reboot

  3. Go to “Hardware” and under “Known Board Name” select “ESP32A1S V2.2+ Variant 1 (ES8388)”, Save, Apply, Reboot.

  4. Go to “Credits” then “Show NVS Editor” and go to the “NVS Editor” under actlrs_config: type buttons

  5. Scroll to the bottom. in the “new key” box type buttons and under “new value” type:

[{"gpio": 18,"type": "BUTTON_LOW","pull": true,"long_press": 600,"debounce": 0,"normal": {"pressed": "BCTRLS_PS5"},"longpress":{"pressed":"BCTRLS_UP"}},{"gpio": 5,"type": "BUTTON_LOW","pull": true,"long_press": 600,"debounce": 0,"normal": {"pressed": "BCTRLS_PS6"},"longpress":{"pressed":"BCTRLS_DOWN"}},{"gpio": 36,"type": "BUTTON_LOW","pull": true,"long_press": 600,"debounce": 0,"normal": {"pressed": "BCTRLS_PS1"},"longpress":{"pressed":"BCTRLS_LEFT"}},{"gpio": 13,"type": "BUTTON_LOW","pull": true,"long_press": 600,"debounce": 0,"normal": {"pressed": "BCTRLS_PS2"},"longpress":{"pressed":"BCTRLS_RIGHT"}},{"gpio": 19,"type": "BUTTON_LOW","pull": true,"long_press": 600,"debounce": 0,"normal": {"pressed": "BCTRLS_PS3"},"longpress":{"pressed":"KNOB_LEFT"}},{"gpio": 23,"type": "BUTTON_LOW","pull": true,"long_press": 600,"debounce": 0,"normal": {"pressed": "BCTRLS_PS4"},"longpress":{"pressed":"KNOB_RIGHT"}}]

You can put different assignments to these as you’d like. I did it like this so every short press and every long press sends a different event to Home Assistant.

  1. At the bottom of the screen press “Commit” then press “Exit Recovery” and reboot your board.

  2. Then go to Home Assistant and add the “SlimProto Player” addon. Give it some time and then it will automagically detect and treat the board like a media_player.

  3. Key presses are passed to Home Assistant as a slimproto_event. You can use this to set up automations for key presses like so:

alias: Button 1 Short Press
description: ""
trigger:
  - platform: event
    event_type: slimproto_event
    event_data:
      args:
        - button
        - preset_1.single
      entity_id: media_player.squeezelite_00000
condition: []
action:
  - service: media_player.volume_down
    data: {}
    target:
      device_id: 00000000000000
mode: single

The Squeezelite player is pretty freaking cool and I’ve had no issues. I wish that I didn’t have to rely on service calls, but that’s a very minor gripe. Sound outputs to the speakers and to the headphone jack just fine.

If you’re having issues with keypresses, try setting your dip switches to: ON - OFF - OFF - OFF - ON.

Anyway, I hope this was helpful to someone. At the very least I hope it can encourage someone to give these cheap little boards a try.

5 Likes

Cool. Have you tried it as a Squeezebox client?

I currently have mine set up as a squeezebox client using my second set of instructions.

The slimproto player integration is essentially emulating a Logitech Media Server. I use my media sources in Home Assistant to play to the boxes as though it was connected to LMS.

I did try the LMS integration in HACS, so it definitely can work as a pure squeezebox, but after playing for awhile I realized Music Assistant has the same capabilities so I’m sticking with that.

Thanks for posting the configuration. It was pretty timely for me as I was working on getting a ESP32-S3-Korvo-1 setup. It has a es8311 chipset so I’ll keep that external component PR in mind.

Do the head phones work with the esphome configuration if the GPIO21 switch is turned off. The Korvo had some hardware logic to keep audio only headphone or only speaker.

On ESPHome the GPIO21 switch doesn’t seem to do anything but mute/unmute the internal speakers. Output to the headphone jacks is extremely quiet (inaudible) no matter what I do with that switch.

The only thing I can see that’s different between the squeezelite and ESPHome config is that squeezelite assigns data in and the I2C bus. (di=35, i2c=16)

4ohm 3 watt speakers are what the board was designed for.
8ohm 1 watt will work, just not as loud.
However, if you crank up the volume on a 4ohm 3watt you do get a bit of distortion.
Not so much on a 8 ohm 1 watt speaker.

Good guide/reference.

1 Like

Many thanks for the manual! Did you also use the line-in and expose it to HA?

1 Like

Hi All,
I know this thread is quite old already, but, I have to ask, I read everything and managed to have the ESP32-A1S working completely with mics, jack and and wake word… but, it’s worthless when trying to ask the assistant to play music because the TTS takes over while answering keeping the assistant from successfully playing the music, and… no automation can be made because there is no way to distinguish between the TTS and actual music since all the attributes remains the same (even music details). Any thoughts?

P.S I meant when using the jack (connected to speakers)

i got error when i reuse this example code :

Component media_player.i2s_audio requires component i2s_audio.

Look here