ESP32 Audio Output with I2S DMA and the MAX98357A Class D Amplifier

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
Music Playing... Hey Everyone, we’ve spent a couple of videos getting audio into the ESP32 We’re now going to switch it up a bit and get audio out of the ESP32! I’m going using the MAX98357A breakout board from Adafruit. This is a class D amplifier with an I2S interface. You need to wire up the LRC, BCLK and DIN lines. Be careful not to confuse the pin labelled SD with the Serial Data pin this pin is actually the Shutdown and channel select pin. Use the DIN pin for the serial data. The amplifier needs to connect directly to a speaker you cannot use this board as a pre-amp. The amount of power you can get out of the board depends on the impedance of the speaker and the voltage you supply to the board. The maximum output you can achieve is 3 watts with a 5V supply and 4ohm speaker but this does come at the price of some audio distortion. If you want to run at this power you will need a power supply that can deliver at least 1.25 Amps. You can control the amount of amplification the board provides by configuring the gain pin. In my tests I have found that leaving the pin floating seems to cause some random noise on the output so it may be worth experimenting in your own setup or tying the pin high or low with or without a resistor. In the video I had the gain pin pulled down with a 100K resistor for maximum gain. The SD pin is a bit more complicated to configure and is confusingly named a lot of other boards use SD to stand for Serial Data but in this case it’s the Shutdown and mode pin. If you are planning on playing mono audio then you can leave it floating and simply send data on both the left and right channels simultaneously. If you tie it to ground then the amplifier will shut down if you tie it to Vin then the amplifier will play the left channel. And to play the right channel you need to use a pull-up resistor. The value for this resistor is slightly complicated by the fact that the board already has an internal voltage divider on this pin. I’ve calculated an appropriate value for the resistor for you in this table of 39Kohm which should work for both 3.3V and 5V but you may want to use 47Kohm resistor if using a 5V supply to be safe and allow for resister tolerance. That’s the basic wiring of the board, but what actually is a class D amplifier? Class D amplifiers are also known as switching amplifiers. They output a modulated signal that switches between the positive and negative power rails. This signal is passed into a low pass filter or directly to the loudspeaker to recover the audio signal. This makes the amplifier very efficient as the transistors are only dissipating power when they are switching from high to low and low to high. This animation demonstrates this process - we have an input sine wave coming into the system. This input signal is then converted to the PWM signal and then we reconstruct the output by low pass filtering the PWM signal. In this animation I am using a very low frequency for the PWM signal. So our reconstructed signal is very noisy. This next animation shows how you can create a PWM signal. Once again we have an input sine wave. To generate the PWM signal we compare the input signal with a high-frequency triangle wave. Where the signal is higher we output high and when it is lower we output low. I’ve captured the output from the amplifier when it is being fed with a 10KHz sin wave. To simulate the speaker acting as a low pass filter I’ve added a simple LC filter to the output and captured the filtered signal. As you can see we can recover the 10KHz input sine wave from the amplifier’s PWM signal. One of the nice things about this board is that it has an I2S interface. This means that we can feed it a digital signal straight from the ESP32. Our entire audio path is digital up until the speaker output. Let's have a look at how the I2S interface is wired up. There are at least three required lines: We have a serial clock - this is used to clock data to or from the peripheral. We have a word select (also called the left-right clock or LRCLK) this selects the channel that you want to send or receive data for. And finally, we have the data line. When the Word Select is low data for the right channel is sent, and when it is high data for the left channel is sent I’ve captured these three lines from the ESP32 on my oscilloscope Here we see the left-right clock line going high and low for each channel. And here is the serial clock. I’m sending 16-bit data so we see 16 clock cycles for each left-right clock phase. And here is the serial signal carrying the audio data encoded as 16-bit words. That’s all the wiring up taken care of. Let’s have a look at the code. Here we have the I2S configuration We will be running in master mode and transmitting data We’ll take our sample rate from whatever is being used to generate our samples - either directly from a WAV file or from a generated signal. We’ll output 16 bits for each sample And we’ll be outputting both left and right channels - this lets us support both mono and stereo sources. The stereo source will be mixed by the amplifier board into mono. If you have two amplifier boards then you could configure one to be the left channel and one to be the right channel and connect them to the same I2S pins. Sending data is pretty straightforward We wait for the I2S peripheral to reach the end of one of its DMA buffers And then we pull some samples from our sample generator And then we write those samples out to the I2S peripheral We need some audio data to play - the simplest format for us to use are WAVE files. The header for a WAVE file contains all the information we need to understand the contents of the file. We’ll only try and support very basic WAVE files. We need the number of channels - we can support either mono or stereo files in our code. And we need the sample rate to configure the I2S peripheral. We also need to know the bit depth - in our code we can only support 16-bit samples but the code could be extended to support other bit depths. Here’s some very basic code for reading the WAVE file header. We can read directly into our C structure And pull out the details we are interested in. Here’s the basic code for reading samples from a WAVE file We seek past the header data which we know is 44 bytes And then read a sample from the file If we only have mono data then we copy across the left channel to the right channel Otherwise we read in the next sample from the file for the right channel All we need to do now is wire up the sample generator to the I2S output and we should get audio coming out of the speaker. We store our audio files on SPIFFS - to do this in platform.io you put them in the data folder. To upload the filesystem, click on the platform.io icon and then find the env section in the project tasks. Scroll down and you’ll find the upload file system command. So, that’s it for this video, I found the MAX 98357 very easy to use and a nice simple way to get audio data out of the ESP32. It’s a class D amplifier so it’s very efficient. The I2S interface means that we are pretty much digital all the way to the speaker output We’ve also seen that reading basic WAV files from the SPIFFS is pretty straightforward. Thanks for watching, all the source code is on GitHub - the link is in the description. If you found the video useful then please hit the subscribe - there’s more videos in the pipeline and I’m still working on my next big project which is getting pretty interesting! Thanks again and I’ll see you in the next video. Music Playing
Info
Channel: atomic14
Views: 63,169
Rating: undefined out of 5
Keywords: MAX98357A, MAX98357, MAX98357A esp32, MAX98357 esp32, esp32 audio output, esp32 I2S, esp32 DMA, esp32 audio, esp32 speaker, I2S, DMA, class-d amplifier, audio amplifier, max98357a volume control, esp32 wav player, esp32 audio player, esp32 i2s audio output, i2s protocol, i2s protocol explained, esp32, esp32 projects, esp32 projects 2020, esp32 i2s dma example, esp32 i2s dma, esp, class d
Id: At8PDQ3g7FQ
Channel Id: undefined
Length: 10min 5sec (605 seconds)
Published: Fri Sep 18 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.