Audio transmission and reception using ESP32 and MAX98357A

The I2S protocol, short for Inter-IC Sound , is primarily used for transmitting or receiving audio data in a synchronous serial port between two devices. Many digital devices require audio communication, such as adding a microphone or speaker output to play audio.

There are several audio protocols available for electronic devices that use audio codecs, DACs, or ADCs. One of the simplest and perhaps best methods is to use the I2S protocol, which uses a simple pin configuration to communicate between two digital audio devices. Designed by Philips Semiconductors (now NXP Semiconductors), the I2S protocol is widely used in various microcontrollers, codecs, audio modules, and microphones that use this protocol for data communication.

Next, let’s explore the key features of I2S and how this protocol works in microcontrollers.

I2S connection

The I2S protocol uses three wires for communication. The connection between the transmitter and receiver is shown below.

Audio  transmission and reception  using ESP32 and MAX98357A

Word Selection (WS) or Frame Selection (FS) lines:

Because the I2S protocol uses stereo operation, the WS pin can be used to select the left or right channel. Generally, if the WP pin is low, channel 1 or the left channel is selected; conversely, if the WS pin is high, the right channel is used.

If we disregard the channel selection pins mentioned above, the I2 protocol uses two pins that are most commonly found in any serial interface.

Serial data pin or SD:

The second line of the I2S communication protocol is the SD pin, which transmits serial data or data signals. Data is transmitted via this line using two’s complement notation.

In I2S data transmission, the most significant bit (MSB) is transmitted first, and the reason for this is obvious. In I2S, data can be transmitted from the transmitter to the receiver in different word lengths.

Therefore, if the MSB is sent first, the transmitter and receiver will not have any correlation in knowing how many bits are transmitted or received.

This raises a new problem: because the receiver and transmitter don’t know the word length, matching data becomes difficult, as data may be lost during transmission due to noise and other factors. This can be solved using the WS pin. If the receiver’s WS is greater than the transmitter’s WS, the word is truncated, and the least significant data bit is set to 0. If the receiver’s WS is less than the transmitter’s WS, the bits after the LSB are ignored.

Bit clock line or BCLK:

The last and most important pin in I2S communication is the Serial Clock (SCK), also known as the Bit Clock Line (BCLK). As the name suggests, it is a clock pin and is crucial in serial data communication protocols.

It is used to capture all components in the same loop. The BCLK line frequency depends on the sampling rate, the number of bits per channel, and the number of channels it uses.

I2S Timing Diagram

The timing diagram below shows the sequence of events:

Audio  transmission and reception  using ESP32 and MAX98357A

The timing diagram above shows three lines: BCLK, WS, and SD. BCLK provides the required clock cycles for the I2S line. WS changes its state from the right channel to the left channel.

Data is transmitted via I2S and sent in each clock cycle. Before the MSB transmission begins in one clock cycle of the I2S data line, the WS pin changes its state from one channel to another. This is because the receiver needs time to store the previously transmitted word and clear its registers.

I2S controller function in ESP32

The ESP32 is a popular, low-cost 32-bit microcontroller unit that supports WiFi and Bluetooth and I2S functionality.

Below is a complete list of the I2S controller functions of the ESP32.

  • ● The I2S controller driver can run as a system master or slave.
  • ● It can also act as a transmitter or receiver in the I2S bus.
  • ● The ESP32 has a dedicated DMA controller that can stream sample data without relying on the CPU to copy and inspect each data sample.
  • ● I2S peripherals also support LCDs. In this mode, I2S data begins to communicate via a parallel bus. This is required in some LCD and camera modules.

Nokia I2S Tone Generator

Let’s connect a speaker in the I2S protocol and use the ESP32 I2S to generate a Nokia tune.

However, since the speaker is an analog device and we need to drive it, we need an amplifier that supports I2S; we chose to use the MAX98357A module, an I2S-based mono amplifier.

The following diagram shows the pin arrangement of the module.

Audio  transmission and reception  using ESP32 and MAX98357A

The module’s three important pins are BCLK, DIN, and LRC. DIN is the data input pin, the same as SD, and LRC is the left/right channel selection pin, the same as WS.

The circuit connection diagram is as follows:

Audio  transmission and reception  using ESP32 and MAX98357A

ESP32 I2S sample code

To run the code, the sampleaac.h header file contains an AAC file converted to Nokia tunes in HEX format.

The header file format is as follows:

const unsigned char sampleaac[] PROGMEM = { 0xFF, 0xF9, 0x5C, 0x80, 0x2E, …………. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xF2
};

First, include all header files.

#include "AudioGeneratorAAC.h"
#include "AudioOutputI2S.h"
#include "AudioFileSourcePROGMEM.h"
#include "sampleaac.h"

We use the AAC audio generator library, which generates audio using the I2S protocol. This can be found on GitHub at: https://github.com/earlephilhower/ESP8266Audio

Next, configure the pins according to the previously provided pin diagram.

#define Bit_Clock_BCLK 27
#define Word_Select_WS 26
#define Serial_Data_SD 25

Then, in the setup function, set the I2S device pins.

  in = new AudioFileSourcePROGMEM(sampleaac, sizeof(sampleaac));
  aac = new AudioGeneratorAAC();
  out = new AudioOutputI2S();
  out -> SetGain(GAIN);
  out -> SetPinout(Bit_Clock_BCLK,Word_Select_WS,Serial_Data_SD);
  aac->begin(in, out);
}

The loop() function continuously plays the audio from the example AAC file in a loop.

void loop(){
  if (aac->isRunning()) {
            aac->loop();
  } else {
            aac -> stop();
            Serial.printf("Sound Generator\n");
            delay(1000);
  }
}

Playing Nokia tunes on an ESP32 using I2S communication

Now that we know how I2S communication works on the ESP32, we can establish a connection, upload the code, and play test audio. In this article, we’ll use Nokia Tunes as an example. Everything is connected correctly and ready for testing.

Audio  transmission and reception  using ESP32 and MAX98357A

Original post

error: Content is protected !!
Scroll to Top