If you need to capture high-fidelity audio or train voice recognition models, use a digital PDM or I2S microphone (like the onboard MP34DT01 on the Nano 33 BLE Sense or an external INMP441). If you only need to detect loud noises, claps, or basic audio envelopes, use an analog module like the MAX9814. The single biggest mistake makers make is trying to run Fast Fourier Transforms (FFTs) or machine learning inference on cheap analog envelope detectors, which physically cannot output the raw waveform data required.

This guide breaks down the hardware differences, provides a direct wiring comparison, and delivers complete, compilable code for capturing raw 16kHz audio using the Arduino Nano 33 BLE Sense.

Choosing the Right Microphone Module for Arduino

Not all 'microphone modules' output the same data. Analog modules output a varying voltage (0-5V) that represents either the raw audio wave or just the volume envelope. Digital modules output a stream of 1s and 0s that must be decoded by the microcontroller's I2S or PDM hardware peripherals.

Table 1: Arduino Microphone Module Comparison
Module / IC Type & Interface SNR (dB) Sensitivity Approx. Price Best Use Case
MAX9814 Analog / ADC 60 dB -44 dBV $8 - $10 Clap detection, basic threshold triggering
MAX4466 Analog / ADC 66 dB -44 dBV $5 - $7 Audio envelope, VU meters
INMP441 Digital / I2S 61 dB -26 dBFS $3 - $5 High-quality audio recording (requires ESP32/Due)
MP34DT01 (Onboard Nano 33 BLE) Digital / PDM 66 dB -26 dBFS $22 (Whole board) Edge AI, TinyML voice recognition, FFT analysis
Warning on Analog AGC: The MAX9814 features an Automatic Gain Control (AGC) circuit. While great for keeping volume levels consistent for human ears, AGC actively compresses and distorts the raw waveform. If you feed MAX9814 audio into a machine learning model (like Edge Impulse), the model will fail to generalize because the AGC alters the harmonic signatures of the sound.

Hardware Setup and Pin Mapping

For the primary code build in this guide, we are targeting the Arduino Nano 33 BLE Sense (Rev2) [Part# ABX00069]. This board has the STMicroelectronics MP34DT01 PDM microphone soldered directly to the PCB, eliminating wiring noise and impedance mismatches.

However, if you are building a simplified threshold-trigger project on a standard Arduino Uno, you will wire an external analog module. Below is the pin mapping for the MAX9814 breakout to an Arduino Uno/Nano.

Pin Mapping: MAX9814 to Arduino Uno (Simplified Build)

MAX9814 Pin Arduino Uno Pin Notes
VCC 5V Requires clean 5V; noisy USB power will introduce a 60Hz hum.
GND GND Connect to a common ground plane.
OUT A0 Analog output. Biased at VCC/2 (approx 2.5V) when silent.
AR (Attack/Release) Leave Floating or GND Tying to GND sets fastest AGC response. Tying to VCC sets slowest.

Parts List for Primary PDM Build

  • Microcontroller: Arduino Nano 33 BLE Sense Rev2 (ABX00069)
  • Cable: High-quality USB-C data cable (must support data transfer, not just charge)
  • Software: Arduino IDE 2.x with 'Arduino Mbed OS Nano Boards' package installed via Boards Manager

Complete PDM Audio Capture Code

The following code targets the Arduino Nano 33 BLE Sense (Rev1 or Rev2). It initializes the hardware PDM peripheral, sets up a double-buffer interrupt callback, and calculates the Root Mean Square (RMS) audio level in the main loop. This prevents the serial monitor from being flooded with raw 16-bit samples while still giving you accurate, real-time volume data.

#include 

// Target Board: Arduino Nano 33 BLE Sense (Rev1 or Rev2)
// Library: PDM.h (Included in Arduino Mbed OS Nano Boards package)

// Buffer to read samples into. Each sample is 16-bits (2 bytes).
// 512 samples at 16kHz = 32ms of audio per buffer read.
short sampleBuffer[512];

// Flag and counter for the interrupt callback
volatile int samplesRead = 0;

void setup() {
  Serial.begin(115200);
  
  // Wait for serial monitor to open (optional, but good for debugging)
  while (!Serial) {
    delay(10);
  }

  // Configure the data receive callback
  PDM.onReceive(onPDMdata);

  // Set the hardware gain. Defaults to 20.
  // Range is typically 0 to 80. Adjust if your audio is clipping.
  PDM.setGain(30);

  // Initialize PDM with:
  // - 1 channel (mono mode)
  // - 16000 Hz sample rate (Standard for voice/TinyML)
  if (!PDM.begin(1, 16000)) {
    Serial.println("FATAL: Failed to start PDM peripheral!");
    Serial.println("Check board selection and Mbed OS package version.");
    while (1) {
      // Halt execution on hardware failure
      delay(1000);
    }
  }
  
  Serial.println("PDM Microphone initialized successfully. Listening...");
}

void loop() {
  // Wait until the callback has filled the buffer
  if (samplesRead > 0) {
    
    // Calculate RMS (Root Mean Square) for audio level metering
    float sumOfSquares = 0;
    for (int i = 0; i < samplesRead; i++) {
      float sample = (float)sampleBuffer[i];
      sumOfSquares += (sample * sample);
    }
    
    float rms = sqrt(sumOfSquares / samplesRead);
    
    // Print the RMS value. Silence is usually around 10-50 depending on gain.
    // Normal speech is 500-2000. Loud claps can hit 10000+.
    Serial.print("Audio RMS: ");
    Serial.println(rms, 2);

    // Clear the read count so the callback can fill it again
    samplesRead = 0;
  }
}

void onPDMdata() {
  // Query the number of bytes available to read
  int bytesAvailable = PDM.available();

  // Read into the sample buffer. 
  // PDM.read() blocks until data is ready if not called from interrupt,
  // but inside the callback, it copies the DMA buffer immediately.
  PDM.read(sampleBuffer, bytesAvailable);

  // 16-bit samples, 2 bytes per sample
  samplesRead = bytesAvailable / 2;
}
Bench Tip: If your RMS values are stuck at exactly 0.00 or fluctuating wildly between 0 and 32767, your USB cable is likely a 'charge-only' cable lacking the D+/D- data lines. The board is brownouting and resetting the PDM peripheral mid-read. Swap to a verified data cable.

Debugging: When the Mic Fails to Read

Audio peripherals on microcontrollers are notoriously fragile because they rely on strict timing and DMA (Direct Memory Access) buffers. If your build fails, check these exact error strings and hardware states.

Exact Error Strings in the IDE

Error 1: #error "This library only supports boards with an nRF52840 processor."

  • Cause: You have the wrong board selected in the Arduino IDE Tools menu, or you are trying to compile this code for an Arduino Uno/Mega.
  • Fix: Go to Tools > Board > Arduino Mbed OS Nano Boards > select Arduino Nano 33 BLE Sense.

Error 2: fatal error: PDM.h: No such file or directory

  • Cause: The core board package is missing or outdated. The PDM.h library is not a standard Arduino library you download from the Library Manager; it is bundled inside the Mbed OS core.
  • Fix: Open Boards Manager, search for Arduino Mbed OS Nano Boards, and install/update to the latest version (ensure it is > 3.0.0).

The First Three Things to Check When Runtime Fails

If the code compiles and uploads, but the Serial Monitor shows Audio RMS: 0.00 continuously, run this diagnostic path:

  1. Check the Hardware Revision (Rev1 vs Rev2): The Nano 33 BLE Sense Rev2 changed the internal power routing. If you are using an older version of the Mbed OS core (pre-2.6.0), the I2C and PDM power rails may not be initialized correctly on a Rev2 board. Update your board package.
  2. Check for I2C/BLE Bus Contention: The MP34DT01 shares internal routing with the I2C bus and the IMU sensors. If your sketch also initializes Wire.begin() or the ArduinoBLE library in the setup() block before PDM.begin(), the PDM peripheral can fail to claim the DMA clock. Always initialize PDM.begin() first.
  3. Check the Physical Environment: The small silver square on the Nano 33 BLE Sense is the acoustic port. If you have placed the board flat against a solid surface, or if conformal coating/solder flux has seeped into the port, the diaphragm is physically dampened. Elevate the board and ensure the port is clear.

Extending and Simplifying the Build

Depending on your end goal, you will either need to scale this project up for machine learning or scale it down for simple hardware triggers.

How to Extend: Edge Impulse and TinyML

Raw RMS values are useless for distinguishing between a dog barking and a glass breaking. To extend this build into voice recognition or acoustic anomaly detection:

  1. Create a free account at Edge Impulse.
  2. Install the Edge Impulse Arduino CLI tools.
  3. Use the Nano 33 BLE Sense to capture raw 16kHz PDM data directly to your browser via WebSerial.
  4. Train an MFCC (Mel-frequency cepstral coefficients) neural network on their cloud platform.
  5. Export the trained model as an Arduino C++ library and drop it into the loop() above, passing the sampleBuffer array directly into the inference engine.

How to Simplify: The Analog Envelope Fallback

If you do not need machine learning and just want an LED to light up when someone claps, abandon the Nano 33 BLE Sense and the PDM code entirely. Switch to an Arduino Uno and a MAX4466 or MAX9814 analog module.

Wire the OUT pin to A0, and use this simplified logic:

void loop() {
  int micValue = analogRead(A0);
  // The analog mic is biased at 512 (2.5V). 
  // We look for deviations from the center point.
  int deviation = abs(micValue - 512);
  
  if (deviation > 150) {
    digitalWrite(LED_BUILTIN, HIGH);
    delay(50); // Debounce
  } else {
    digitalWrite(LED_BUILTIN, LOW);
  }
}

This approach requires no external libraries, no DMA buffers, and compiles on literally any AVR-based Arduino board. It sacrifices audio fidelity for absolute simplicity, proving that the 'best' microphone module is entirely dependent on the data pipeline you intend to build.