I found some cheap AI Thinker ESP32 Audio Kit V2.2 on AliExpress and because I was tired of all the wires I had to connect to implement my different scenarios that are possible with my Arduino Audio Tools Library, I thought it to be a good idea to buy this board.

Audio Kit

I am aware that this board, like the corresponding LyraT alternatives from Espressif are mainly used with the IDF/ADF framework, but I wanted to use it with Arduino, and that’s where the problems started: First I was so naive to just deploy one of my Bluetooth A2DP Audio sketches. It was running somehow – but there was no sound! Next I tried out the SD drive – and here again – the SD drive was not available.

I am documenting here the solutions to make things work for my V2.2 3478 Board:

The SD Card

The AI board like the LyraT boards are using some unusual pin assignments and you need to initialize SPI by indicating the correct pins.
In addition you need to make sure that the DATA3 and CMD on-board switches are in the on position:

#define PIN_AUDIO_KIT_SD_CARD_CS 13
#define PIN_AUDIO_KIT_SD_CARD_MISO 2
#define PIN_AUDIO_KIT_SD_CARD_MOSI 15
#define PIN_AUDIO_KIT_SD_CARD_CLK  14

SPI.begin(PIN_AUDIO_KIT_SD_CARD_CLK, PIN_AUDIO_KIT_SD_CARD_MISO, PIN_AUDIO_KIT_SD_CARD_MOSI, PIN_AUDIO_KIT_SD_CARD_CS);

Then when you set up the SD library you need to indicate the PIN_AUDIO_KIT_SD_CARD_CS as CS pin. That was the easy one – no let’s move to the major challenge:

Output to the Speakers

The board uses a ES8388 audio chip that is connected via I2S, so we need to use the correct I2S pin assignments. Note that these are different from the LyraT ones!

#define PIN_I2S_AUDIO_KIT_MCLK 0
#define PIN_I2S_AUDIO_KIT_BCK 27
#define PIN_I2S_AUDIO_KIT_WS 25
#define PIN_I2S_AUDIO_KIT_DATA_OUT 26
#define PIN_I2S_AUDIO_KIT_DATA_IN 35

The audio chip is responsible for routing the output or input to the correct final device and controlling the volume. The ES8388 must be programmed via I2C! In order to do this I found this solution from thaaraak which inspired me to try to convert the original ADF driver from Espressif, so that it can be used in Arduino.
Here is the necessary information for the I2C connection:

#define I2C_MASTER_NUM I2C_NUM_0 /*!< I2C port number for master dev */
#define I2C_MASTER_SCL_IO 32     
#define I2C_MASTER_SDA_IO 33    
#define ES8388_ADDR 0x10

Finally, here is a link to the ES8388 user guide.

Headphone Detection

I was testing the headphone detection with the following logic:

#define HEADPHONE_DETECT 39 

bool headphoneStatus() {
  return !gpio_get_level((gpio_num_t)HEADPHONE_DETECT);
}

If no headphone is connected the gpio_get_level() returns 1 – with a headphone the output changes to 0 – so I confirm that on this board we need to use GPIO 39.

Please note that the pin must be set up to be pulled high.

Enable Power Amplifier

The power activate pin for the speakers is identical to the LyraT boards:

#define PA_ENABLE_GPIO 21

We can use this pin together with the headphone detection pin to activate/deactivate the speaker

  void processKeys() {
    LOGI(LOG_METHOD);
    static unsigned long keys_timeout = 0;
    if (keys_timeout < millis()) {
      if (cfg.is_headphone_detection) {
        LOGI("process headphone detection");
        bool isConnected = headphoneStatus();
        bool powerActive = !isConnected;
        if (powerActive != actualPower) {
          LOGW("Headphone jack has been %s",
                   isConnected ? "inserted" : "removed");
          setPAPower(powerActive);
        }
      }
      keys_timeout = millis() + KEY_RESPONSE_TIME_MS;
    }
  }

Conclusions

I have the solution working now and I can share my Audio Player Sketch that I used for my tests. It is based on my arduino-audio-tools project:

The Arduino Audio Player Sketch

#define USE_SDFAT
#define USE_HELIX
#include "AudioTools.h"
#include "AudioLibs/AudioKit.h"

const char *startFilePath="/";
const char* ext="mp3";
AudioSourceSdFat source(startFilePath, ext, PIN_AUDIO_KIT_SD_CARD_CS);
AudioKitStream kit;
MP3DecoderHelix decoder;
AudioPlayer player(source, kit, decoder);


void setup() {
  Serial.begin(115200);
  AudioLogger::instance().begin(Serial, AudioLogger::Info);

  // setup output
  auto cfg = kit.defaultConfig(TX_MODE);
  kit.begin(cfg);

  // setup player
  player.begin();
}

void loop() {
  player.copy();
  kit.processActions();
}

Yes – I just needed to replace the I2SStream with the AudioKitStream and that’s pretty cool!
If you add the kit.processActions() in the loop you get the automatic headphone detection and volume control working.

Unfortunately the output is quite distored mainly for the loud parts. We can take care of this by reducing the signal strength (volume) that we send to the kit by adjusting the volume of the player with player.setVolume(0.7);

The full example can be found on Github

Dependencies

Disclaimer

Please note that the sketches that I am posting on this site are working at the point of time of the posting. It might be that things have changed when you read this. So please use the corresponding updated example in the Audio Tools Project if you want to try it out yourself.


16 Comments

darz82 · 6. March 2024 at 7:52

Hello, I’ve recently purchased a ESP32-A1S board and I want to be able to play audio through ceiling speakers, with an ultimate goal being multiroom audio, now I think I’ll need to add an external amplifier to do this, can someone explain to me how you go about connecting an external amplifier to this board and driving higher wattage speakers.? Cheers

    pschatzmann · 6. March 2024 at 8:24

    Just connect the AUX out with the input of your amplifier: You might need an adapter cable.

Facu · 4. July 2023 at 23:02

I would like to ask about something very little, it’s about the LED’s D4 and D5. Could you know what GPIO’s are related to them? Many thanks in advance. Your work it’s phenomenal!
Cheers!

Clint Davis · 27. March 2023 at 19:04

Hello Phil, I thank you very much for your hard work!

I’ve been trying to use the Audiokit to flash two of these boards, unfortunately my boards just say Version 2.2 A237.

I would really like to create an AAC webserver for my network, and then another board to stream it.

When I flash the Webserver, it will join my network, and I can go to the page and start a stream, it takes a second, but unfortunately there is no Audio… I have confirmed the input.

I have verified that DIP switch 2 and 3 are on with the others off and I have also tried the other two settings for the board in your file, but the first AI thinker is the only one that starts a server.

Have you possibly got any ideas what could be wrong, or where to start?

Thank you for any help!

Clint

    pschatzmann · 27. March 2023 at 19:15

    The dip switches have no impact in this scenario.
    I would start with the WAV and move to a more complex encoder only after this is working.
    Don’t forget to define the input device cfg.input_device = AUDIO_HAL_ADC_INPUT_LINE2;

      Clint Davis · 1. April 2023 at 13:33

      Thank you for your reply. I’ve tried several different things, your example sketch streams-audiokit-webserver_aac.ino seems to define LINE2 but I still have no sound. The WAV Streamer example tries to save a file as soon as I go to the webpage. I cannot find anything at all that will play it or anything I can download to go stream it. I’m kind of at a loss. I’ll try to host a streaming service on a computer and see if I can play it with one of these examples.

Alwin · 2. January 2023 at 19:08

Board in picture uses AC101 chip instead of 8388….Hence the A1S in the name…

T. H. · 8. March 2022 at 22:25

I tried this with AudioKit 2.2. with ES8388, but
a) only headphone jack insertion is detected, not removal
and
b) volume is very low for headphone and speaker. I coud fix this, but only for speaker, by changing some lines in es8388.c es8388_set_voice_volume, as depicted here: https://github.com/AI-Thinker-Open/ESP32-A1S-AudioKit/issues/26

Do you have any idea how to fix headphone jack detection and headphone volume?
I read somewhere that several AudioKit variants with ES8388 exist, using different pins for I2C/I2S, did you take this into account in your code?

    pschatzmann · 9. March 2022 at 9:05

    I am not aware that different pin variants exist for the AudioKit with ES8388. However there is a variant with the AC101 which is totally different not only with the pins. As you can see in the readme of the AudioKit project, I am supporting both – but please note that depending on the functionality you want to use you might run into different pin conflicts: e.g. on the AC101 you can’t use the headphone detection if you use the SD.
    I did not hear any issues with a low volume – on the contrary for me it was too loud. But please notice that the AudiKitStream class provides it’s own methods for managing the volume: The initial value is set to 40, but you can change this by calling the setVolume() method.

    I could reproduce your issue with the headphone detection which was introduced when I extended the button handling logic.

    For further discussions please use the issues or discussions on Github.

Vladimir Kozlov · 6. January 2022 at 13:57

Hello Phil, I just tried your library for Audio Kit and it works great! By the way, do you have any information regarding on-board microphones, i.e. sensitivity, noise level, etc.? I’m thinking about measuring sound level pressure using this board, but to calculate dB values I need some data about microphones, and there are no any info for this nor in Ai-Thinker docs, nor in Google…

    pschatzmann · 10. January 2022 at 18:52

    I haven’t used the built in microphone so far.
    Please note that the driver provides the method es8388_set_mic_gain(es_mic_gain_t gain) to control the gain.

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *