Arduino and ESP32 I2S

Hello,

I'm trying to get my ESP32 to output an 8-bit 16-kHz sound file that is stored in PROGMEM as uint8_t via I2S, through an Adafruit I2S mono amp.

The problem is, now that I've got everything (apparently correctly) wired up, I have no idea what to do. I tried using the commands provided in the Arduino reference here on this web page, but they just don't seem to work with the ESP32 and the code doesn't compile. Also, apparently the ESP32 core has a built-in I2S header file, but when I try including it in my sketch, I only get errors.

How do I output my sound sample on a speaker through I2S? And why is there so little documentation on I2C functionality?

nobody? :frowning:

You haven't posted any code, error messages, or connections. How is anybody supposed to know what the problem is?

Pieter

The problem is that I haven't found any example code that could show me how exactly I can play sounds with the ESP32 using an external I2S amp.

I have no code to post here because I simply don't know where to start.

ok so I've actually found some example code which I've taken from here: Demo 26: How to use Arduino ESP32 I2S (external DAC and built-in DAC) to play wav music file from sdcard and which I've tried to adapt for my purposes:

#include "driver/i2s.h"
#include "freertos/queue.h"
#include <pgmspace.h>

#include "soundsample.h"


//i2s configuration
int i2s_num = 0; // i2s port number
i2s_config_t i2s_config = {
  .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX),
  .sample_rate = 16000,
  .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
  .channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT,
  .communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S),
  .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, // high interrupt priority
  .dma_buf_count = 8,
  .dma_buf_len = 64   //Interrupt level 1
};

i2s_pin_config_t pin_config = {
  .bck_io_num = 26, //this is BCK pin
  .ws_io_num = 25, // this is LRCK pin
  .data_out_num = 22, // this is DATA output pin
  .data_in_num = -1   //Not used
};


int i2s_write_sample_nb(uint32_t sample) {
  return i2s_write_bytes((i2s_port_t)i2s_num, (const char *)&sample, sizeof(uint32_t), 100);
}

//Main function to play samples from PROGMEM
void playPROGMEMsample(const uint32_t* audioSample) {

  uint32_t sampleSize = sizeof(audioSample) * 4;

  uint32_t counter = 0;
  //initialize i2s with configurations above
  i2s_driver_install((i2s_port_t)i2s_num, &i2s_config, 0, NULL);
  i2s_set_pin((i2s_port_t)i2s_num, &pin_config);
  //set sample rates of i2s to sample rate of wav file
  i2s_set_sample_rates((i2s_port_t)i2s_num, 16000);


  uint32_t readData;

  while (audioSample)  {
    readData = pgm_read_dword(&audioSample[counter++]);
    if (readData == NULL) break;
    i2s_write_sample_nb(readData);
  }

  i2s_driver_uninstall((i2s_port_t)i2s_num); //stop & destroy i2s driver
}

void setup() {

  Serial.begin(115200);
  Serial.println("Serial connection OK");
  playPROGMEMsample(sample1);
}

void loop() {


}

At this point, I'm actually not yet fully grasping what I am really doing here. This code compiles, but all I get on my speaker that is connected to the amp is noise.

I'm using a 16kHz 16-bit wav sample that I've put into PROGMEM (see attached zip file for sketch and .h file) as an array of double word hex values. Within my project, I want to play all sound samples that it will contain from PROGMEM. Maybe I would make my life easier by just putting them on an SD card, but that is not the goal. The finished product must contain them in flash memory.

My pinout:

[ESP32] ----------- [Adafruit 98357A]
GPIO22 ----------- DIN
GPIO25 ----------- LRC
GPIO26 ----------- BCLK

The Adafruit amp with the speaker is connected to an external 3V3 supply.

I have loosely tried to make sense of the i2s.h file within the ESP32 core, but I'm really not quite sure how I can get my setup to work.

Any help is appreciated.

  • carguy

esp32_audio__.zip (472 KB)

EDIT: The sound sample in my last post was crap, it was in the wrong byte order so it wouldn't have worked either way.

I've attached the sample again. Together with an updated version of my code, but which is sadly still not working and only producing noise on my speaker.

---esp32_audio.zip (473 KB)

I'm not really familiar with the ESP32 Arduino Core. You might have more luck if you use ESP-IDF with freeRTOS directly, without the Arduino Core on top.

The ESP-IDF contains an I²S example (https://github.com/espressif/esp-idf/blob/master/examples/peripherals/i2s/main/i2s_example_main.c) and extensive documentation (Inter-IC Sound (I2S) - ESP32 - — ESP-IDF Programming Guide latest documentation).
The I²S hardware documentation can be found in chapter 12 of the [ESP32 Technical Reference](https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf#12 I2S).

If you do plan on using it in the Arduino IDE, keep in mind that it's C code, not C++.

I see... well, I've also asked on the Espressif ESP32 forum, an answer is still pending.

Do you have any way of testing my sound sample to see if it's in the correct format? So that I'd at least be able to eliminate that as a potential source of my problems?

  • carguy

carguy:
Do you have any way of testing my sound sample to see if it's in the correct format?

I'd say that it depends on the firmware you're running, not on the I²S functions/hardware itself.
I'm not sure what format you need.

From the example code I found, apparently it has to be at least 16-bit, but the sampling freq can be anything from 8000 to 48000 Hz. It can also be either mono or stereo.

The example code from iotsharing.com is for a stereo amp, so I guess somehow I would have to change the settings so that it's for a mono amp, which is what I have here with my setup. But I'm not sure how to do that.

I don't know if this helps:

Interfacing an audio codec with ESP32 – Part 1 and 2
http://iot-bits.com/interfacing-an-audio-codec-with-esp32/
http://iot-bits.com/interfacing-audio-codec-esp32/

hii guys, i solved this problem with modify variable sample1 data type from soundSample.h from uint32_t to uint8_t. this is the last modify of code above...

esp32_audio.zip (523 KB)

Hi @Tobil,

Ran your code, getting

"exit status 1
narrowing conversion of '100980833' from 'int' to 'uint8_t {aka unsigned char}' inside { } [-Wnarrowing]
"

on compilation. Console is getting flooded with messages like these.

Sparkfun has a good guide on how to do this using the Arduino core for ESP32: I2S Audio Breakout Hookup Guide - SparkFun Learn