I2S on the ESP32 with ADC sampling

Given I always forget how to do this. Here is to read values of an ADC from a DMA. A good resource for this is this project though the layers of abstractions makes it hard to get the important details out. So here are those.

Step number 1 : Choose the pin

Look at the pinout of the ESP 32, and decide on a PIN, look at which ADC and channel it corresponds to.

Example : - Pin 33, corresponds to the ADC 1 and the Channel 5 of that ADC. - Pin 14, ADC 2, Channel 6.

Step number 2 : Configure the Hardware

You first need to configure the driver. There are a few things you would need to modify depending on your application.

// i2s config for reading from both channels of I2S
i2s_config_t i2sConfigChannel = {
    .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN),
    .sample_rate = 44100,
    .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
    .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,//I2S_CHANNEL_FMT_RIGHT_LEFT,
    .communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_I2S),
    .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
    .dma_buf_count = 4,
    .dma_buf_len = 64,
    .use_apll = false,
    .tx_desc_auto_clear = false,
    .fixed_mclk = 0
};

Now, you also need to install that driver :

i2s_driver_install(I2S_NUM_0, &i2sConfigChannel, 0, NULL);

Avoiding using queues makes it more straight forward to program.

Step number 3 : Configure the ADC channel

Configure the ESP 32 using these numbers.

i2s_set_adc_mode(ADC_UNIT_1, ADC1_CHANNEL_5);
i2s_adc_enable(I2S_NUM_0);

Step number 4 : Read data

In the loop, now read the data.

int16_t buffer[64];
size_t bytes_read;
i2s_read(I2S_NUM_0, &buffer, sizeof(buffer), &bytes_read, 0);

If you are reading sound data, the IC is usually biased, so you should find the center of the bias, the fastest way is to sample and average the data, and take that figure then substract it from the data. For example :

for (int i = 0; i < number_of_samples; i++)
    buffer[i] = buffer[i] - 24824;

Now your buffer is full of audio. Good job.