Lesson13: PDM Microphone Input and Volume Analysis¶
1. Objectives¶
In this lesson, you will use the ESP32-S3's I2S PDM RX mode to record one second of audio from the onboard microphone and calculate the peak and RMS values of the recording. No audio is played; the microphone input level is monitored only through the serial port.
2. Prerequisites¶
- Complete the ESP32-S3 environment setup in Lesson01.
- This lesson uses the built-in
ESP_I2Slibrary included with Arduino-ESP32. No additional third-party libraries are required.
How to add the library files:
- No additional third-party libraries are required. Use the ESP_I2S library included with the ESP32 3.3.3 board package.
- Library download link:
3. Arduino IDE Instructions¶
-
Confirm that the board settings match those used in Lesson01.

-
Click Upload to flash the sketch, then open the Serial Monitor and set the baud rate to
115200.
4. Hardware Instructions¶
- Connect the development board to the computer using a USB data cable, then open the Serial Monitor.
-
Keep the environment quiet and first observe the baseline microphone peak and rms values.
-
Speak into the microphone or clap softly, and observe whether the peak and rms values increase.
-
This lesson only tests the microphone input and the serial analysis results.
5. Key Code Explanation¶
microphone.setPinsPdmRx(kMicrophoneClockPin, kMicrophoneDataPin);
microphone.begin(I2S_MODE_PDM_RX, kSampleRate, I2S_DATA_BIT_WIDTH_16BIT,
I2S_SLOT_MODE_MONO, I2S_STD_SLOT_LEFT);
A PDM microphone requires a clock line and a data line. setPinsPdmRx() assigns GPIO12 and GPIO11, while begin() configures I2S to operate in PDM receive mode. The sample rate is 16 kHz, and the sample bit depth is 16 bits, which is suitable for basic sound intensity analysis.
size_t wavBytes = 0;
uint8_t* wavData = microphone.recordWAV(kRecordSeconds, &wavBytes);
if (wavData == nullptr || wavBytes <= kWavHeaderBytes) {
Serial.println("ERROR: Microphone recording failed");
free(wavData);
return;
}
recordWAV() returns a block of WAV-formatted data in memory. The first 44 bytes are the WAV file header, followed by the PCM samples. If it returns a null pointer or the total length is not large enough to contain a WAV header, the recording has failed. free() is also called on failure to ensure consistent memory-release logic.
const int16_t* samples = reinterpret_cast<const int16_t*>(wavData + kWavHeaderBytes);
const size_t sampleCount = (wavBytes - kWavHeaderBytes) / sizeof(int16_t);
These two lines skip the WAV header and point directly to the PCM sample area. Because the sample format uses 16-bit signed integers, the data is read using an int16_t*, and the number of samples is calculated by dividing the remaining number of bytes by 2.


