ESP32 – Intro to I2S Part 1

This is the first in a series of videos and articles explaining I2S and how to use with the ESP32. This opening episode keeps it very simple just using the included standard Espressiv libraries. In the video there is a full explanation of how I2S is implemented followed by a run through of the demo software – which has been kept very simple. Click below to watch the video, which has everything you need to know in it. Read further for supporting code and a write up of the video.

Watch the video in YouTube

Introduction
In recent articles we’ve looked at how to use I2S to play MP3’s and Web radio. But those examples used extra libraries consisting of hundreds if not thousands of lines of code. It wasn’t easy to understand exactly what was going on. So I started this series, in this opening episode we’re going to look at how I2S works and how to generate a simple digital tone, we’ll then build on that to make more complex examples, eventually ending with the update and release of a new version of my DACAudio library that supports I2S audio. The video is essential viewing- especially for the explanation of digital sound and how I2S functions.

The Circuit
Below is the circuit I’ll be using, I’m using MAX98357A I2S decoders as they have a handy in-built class D amplifier and can drive up to 4Ohm speakers directly. Other decoders are available but I won’t be covering the wiring for them. This is going to be a very simple example to illustrate I2S.

Circuit implementation


Here’s the parts list for what you are seeing, along with affiliate links for these items.

ESP32 : https://amzn.to/3kb02n8
ESP32 – Pack of three : https://amzn.to/2XfIRqH
I2S Decoder : MAX98357A : https://amzn.to/3fkHEnU
3W Speaker : https://amzn.to/2XeRP7i
Breadboards : https://amzn.to/30fWibZ
Wires : https://amzn.to/3k4PKoC
Pins and sockets : https://amzn.to/39O7a3K (I2S board doesn’t some with them)

First off the data and control lines. These can be any pins you specify (more or less) but stick with those shown then the examples I’m going to show you will work. The serial data connects to pin 25 of the ESP32 and goes to the DIN line of MAX98357A. You can see we connect it to both decoder boards. One of these boards is set to decode the left channel ignoring the right channel data and the other is set to decode the right channel data and ignore the left, thus giving stereo sound. I’ll show you how to set this at the end of this wiring part. Pin 27 is the bit clock and goes to BCLK connection of the boards. Pin 26 is the Left/Right clock and goes to the pin labelled LRCLK. That’s all the connections as far as I2S is concerned, we now turn our attention to the connections unique to this decoder board.

The Gain is how much this hardware will amplify the audio by default, my website explains this more fully but I’ve found for this setup connecting this to Vcc gives a good gain, too much is as bad as too little. The SD with a line over it – pronounced NOT SD, should be left unconnected as it used used by the design of this board to select the left or right channel or even if we mix the stereo sound down to mono. More on that part later. If you were to ground it it would shut down the device, effectivly acting like a mute. However to unmute it must be left unconnected or you may inadvertantly select the wrong channel unless you know what your doing.

Gnd – ground goes to ground. The 2.5-5.5v Vcc connection, however, I recommend connecting to the Voltage in from your supply (as long as it’s not more than 5.5V) and not the regulated 3.3v output from the ESP32. This is because these devices when driving low impedence speakers can cause current spikes that will cause problems for your ESP32. Here you can see I’ve connected to the VIN pin available on this particular style of board. Not all boards have this, so if you want to build this project then ensure you get one that has this or have some other way of accessing your power source. And of course you need to connect a speaker, 4 or 8 ohm ones are fine, ensure at least 3W unless you want to damage the speaker.

The Code from the video

STEREO SELECTION
The MAX98357A’s shown support mixing stereo down to mono or individual ones can be set to the right or left channels, therefore to have stereo you need to have tow of them. The video covers how to do this, look in the description for time-codes to jump right to the part you want if required.

In the next article and video in this series we’ll look at how to play back digitised sounds through the I2S interface using WAV files.

All for now. 🙂

17 Comments

  1. Hi Xtronical, I hope you are well. Big fan of the work you do, love the tutorials and videos. I appreciate you are open source and I contacted you a while back and you were kind enough to allow me to convert your brilliant Space invaders tutorial into an Arduboy format to use for students learning about programming. I want the reference to Xtronical to remain within the pdf tutorial document so the original source is always preserved, hence people will always know that the original source code comes from Xtronical and of course preserve a link to your website. To do this I recommend adding a BSD 3 – Clause to it meaning that it can be shared but the original author – Xtronical must be preserved and no financial gain can be made and that of course, it’s open-source, sharing my additions (arduboy code). Would you be happy for me to include this in the tutorial pdf? Arduboy get a huge following so it might be kind of cool to even share it with the Aruboy community. What do you think?

    • Thank you for your kind comments. Keeping the references to myself is fine and appreciated but I do not mind if any financial gain is made from using or extending the work that I do, so apart from that, great 🙂

      • Thanks for your quick response. I’ll keep the link to your work, add the appropriate license requiring the recognition of your input and website but use a license allowing commercial use as well. Thanks for all your support with this you are very kind with your time.

    • Sorry for late reply, real life work has been very busy and I missed this comment. driver/i2s comes already with the default install of the ESP32 software. If you don’t have it then try installing your esp32 environment in the arduino IDE again.

  2. XTronical is it possible to phase invert I2S audio?
    I was looking at this app note from invensence https://invensense.tdk.com/wp-content/uploads/2015/02/Low-Noise-Directional-Studio-Microphone-Reference-Design1.pdf

    Was wondering could we do that digitally where one channel goes into a ‘mic distance’ ring buffer and then the other channel is phase inverted and then mixed at equal volume.
    I am not sure how that creates a directional mic but the invernsense engineers seems to think so and wondered if I could tempt you to give it a go?
    Ignore the array but thinking could use L/R of the I2S and mix 2x 16bit 16000hz mics?

  3. Hi XTronical,
    Thank you for the library and thank you for the tutorials. I have limited pins on my esp32 to use and not able to use 3 pins for the build in i2s or external i2s dac.
    Instead i would like to try to use MCP4725 with i2c together with your library. Is it possible to use the library with MCP4725? I hope you can shed some light on how to make the library work with the MCP4725.
    Thank you in advance.

    Cheers,
    TS

    • Sorry , for whatever reason this post was marked as SPAM but I can’t see why that would be. Anyhow… I:m writing a new library, I’ll look in to 4725 and see if I can support it

  4. Sorry for asking this here, but comments are not approved on your DAC Audio pages. I am using your DACAudio library and want to include lots of small samples in my project. But now I am running beyond the 520k SRAM limit of the ESP32. Do you have a solution for that? I want to use DAC and not I2S 8bit sounds are plenty for me. Is there a way to store the WAV files in SPIFFS and read them from there without declaring them as variables in the code?

    • Yes, sorry. Because it’s hard for me to ensure nothing inappropriate is posted I moderate them but sometimes find that I don’t always have enough time to do it quickly (as you can tell as this is quite a late reply). Although I did think you could post the comment. Anyways…
      You should be storing your files in program memory not SRAM, that will give you more space. One of the tutorials takes you through that. Or is that actually what you mean?

      • Yes, I did define them in PROGMEM, but you still reach a limit sooner than later which is way less than the memory limit of the ESP. Give it a try, define a few different sound files (I used one in each header file), you also define the Xtronic variable as a global variable and your code will not compile:
        section .dram0.bss' will not fit in region dram0_0_seg’
        DRAM segment data does not fit.
        region `dram0_0_seg’ overflowed by 19224 bytes

  5. Has anyone tried storing MP3 in SPIFFS?

    I want to store MP3 files in SPIFS and adjust volume in code as required before playback. I am using VS.CODE and ESP.IDF for code development.

    Thanks

    • I’m supporting SPIFFS in my I2SAudio library, this will replace my DACAudio library. Initial release around 2 months (but might not have SPIFFS support at that point)

      • I also noticed that audio cuts out if your ESP is also doing a lot of extra work. In my project, I had OLED display, Wifi enabled and when I was using it, the audio was not continues. On the ESP32 I moved the DAC code to a different thread on core 1 and the issue was resolved. You can mention that as well, at least that is an option you have on an ESP32.

  6. Hi XTronical,
    Thanks for your tutorials.
    I’m getting a problem to work with the second i2s: I2S_NUM_1 channel. Code crashes. I tried both internal adc and dac. The same code works fine with the first i2s channel: I2S_NUM_0.
    Could you advise anything?
    P.S. I use M5Stack board. Could it be that some internal components (like display driver) use it?

    • I’ve no experience with that dev board, however I quick look at the specs says 1 x I2S, so it would suggest that one I2S channel is being use by something. However the display is a ILI9341 which is SPI, so don’t think that.

Comments are closed.