Adding audio input to a Raspberry Pi seems trivial until you move past plug-and-play USB webcams and try to integrate a low-profile, high-fidelity I2S MEMS microphone. Unlike USB audio class devices, a raw I2S microphone like the SPH0645LM4H requires precise GPIO clock mapping, kernel device tree overlays, and ALSA (Advanced Linux Sound Architecture) configuration to function. If you skip a step, you will be greeted with deafening white noise or silent dropouts.
This guide walks through wiring the Adafruit I2S MEMS breakout, configuring the I2S bus on Raspberry Pi OS (Bookworm), and provides a robust Python recording script with explicit error handling for the most common ALSA and PortAudio failures.
Hardware Spec Sheet & Pin Mapping
Parts List
- Microcontroller: Raspberry Pi 4 Model B (or Pi 5)
- Microphone Module: Adafruit I2S MEMS Microphone Breakout - SPH0645LM4H (Product ID: 3421, ~$7.95)
- Wiring: 5x female-to-female jumper wires (silicone, 28 AWG)
- Storage: MicroSD card (32GB minimum, Class 10)
Pin Mapping Table
The SPH0645LM4H operates as an I2S slave device. It requires a Bit Clock (BCLK), a Left/Right Word Select clock (LRCLK), and a serial data line (DOUT). We map these to the Pi's hardware PCM/I2S pins.
| Mic Breakout Pin | Raspberry Pi GPIO (BCM) | Physical Pin (Header) | Function / Signal |
|---|---|---|---|
| VIN | N/A (3.3V Power) | Pin 1 | 3.3V Power Supply |
| GND | N/A (Ground) | Pin 6 | Common Ground |
| BCLK | GPIO 18 | Pin 12 | PCM_CLK (Bit Clock) |
| LRCLK | GPIO 19 | Pin 35 | PCM_FS (Frame Sync / Word Select) |
| DOUT | GPIO 20 | Pin 38 | PCM_DIN (Serial Data Input to Pi) |
Wiring and ALSA Configuration Steps
Before writing code, the Linux kernel must be told to route the I2S peripheral to the correct GPIO pins and load the appropriate audio driver. In Raspberry Pi OS Bookworm, the boot partition is mounted at /boot/firmware/, not /boot/ as in older Bullseye releases.
- Wire the Breakout: Connect the 5 pins exactly as specified in the table above. Double-check that VIN is on 3.3V (Pin 1). Never connect VIN to 5V; the SPH0645LM4H absolute maximum rating is 3.6V, and 5V will instantly destroy the MEMS element.
- Disable Default Audio: Open a terminal and edit the config file:
sudo nano /boot/firmware/config.txt
Find the linedtparam=audio=onand change it todtparam=audio=off. This disables the onboard PWM audio, which conflicts with I2S. - Enable the I2S Overlay: Add the following line to the bottom of
config.txt:
dtoverlay=googlevoicehat-soundcard
Why this overlay? The SPH0645LM4H has a known hardware quirk where the MSB (Most Significant Bit) is delayed by one clock cycle. Thegooglevoicehatoverlay configures the I2S controller in DSP Mode A, which correctly aligns the bit-shift and prevents the recording from sounding like loud white noise. - Reboot and Verify: Save the file (Ctrl+O, Enter, Ctrl+X) and reboot:
sudo reboot
After rebooting, verify the sound card is recognized:
arecord -l
You should seecard 1: sndgooglevoicehat(or similar) listed as a capture device. - Install Python Dependencies: We use
sounddevice(a modern wrapper around PortAudio) andnumpyfor buffer manipulation.
sudo apt update && sudo apt install libportaudio2 python3-pip
pip3 install sounddevice numpy wave
Python Recording Script with Error Handling
This script targets the Raspberry Pi 4/5 ALSA environment. It records 5 seconds of audio from the I2S MEMS microphone and saves it as a 16-bit WAV file. It includes explicit try/except blocks to catch the exact PortAudio and OS errors that plague Pi audio setups.
import sounddevice as sd
import numpy as np
import wave
import sys
import time
# Hardware mapping reference (handled by ALSA overlay, not Python directly):
# BCLK -> GPIO 18 (Pin 12)
# LRCLK -> GPIO 19 (Pin 35)
# DOUT -> GPIO 20 (Pin 38)
# Recording Parameters
SAMPLE_RATE = 44100 # SPH0645 supports up to 48kHz; 44.1kHz is standard for WAV
CHANNELS = 1 # Mono (Single MEMS mic)
DURATION = 5 # Seconds
FILENAME = 'i2s_mems_capture.wav'
def record_i2s_audio():
print(f'Starting {DURATION}-second capture via I2S MEMS...')
# Calculate total frames
num_frames = int(SAMPLE_RATE * DURATION)
try:
# Open the audio stream using the default ALSA input device
# blocksize=1024 prevents buffer underruns on the Pi's I2S DMA
with sd.InputStream(samplerate=SAMPLE_RATE, channels=CHANNELS,
dtype='int16', blocksize=1024) as stream:
# Pre-allocate numpy array for the audio data
audio_data = np.zeros((num_frames, CHANNELS), dtype=np.int16)
# Record in chunks to allow for keyboard interrupts
frames_recorded = 0
while frames_recorded < num_frames:
chunk_size = min(1024, num_frames - frames_recorded)
data, overflowed = stream.read(chunk_size)
if overflowed:
print('Warning: Audio buffer overflowed. Pi CPU may be throttling.')
audio_data[frames_recorded:frames_recorded + chunk_size] = data
frames_recorded += chunk_size
print('Capture complete. Writing to disk...')
# Save to WAV file
with wave.open(FILENAME, 'wb') as wf:
wf.setnchannels(CHANNELS)
wf.setsampwidth(2) # 2 bytes = 16-bit
wf.setframerate(SAMPLE_RATE)
wf.writeframes(audio_data.tobytes())
print(f'Successfully saved to {FILENAME}')
except OSError as e:
# Catches: 'OSError: No default input device'
print(f'\n[CRITICAL OS ERROR] {e}')
print('Fix: ALSA does not see the I2S overlay. Run "arecord -l" to verify.')
sys.exit(1)
except sd.PortAudioError as e:
# Catches low-level PortAudio/ALSA communication failures
print(f'\n[PORTAUDIO ERROR] {e}')
print('Fix: PulseAudio/PipeWire might be hogging the I2S bus.')
sys.exit(1)
except KeyboardInterrupt:
print('\nRecording aborted by user.')
sys.exit(0)
if __name__ == '__main__':
record_i2s_audio()
Debugging: ALSA Failures & PortAudio Errors
When working with I2S audio on Linux, things will break. Here are the exact error strings you will encounter, ranked by frequency, and how to fix them.
1. "OSError: No default input device"
Rank: #1 Most Common
Cause: PortAudio queries ALSA for a default capture device, but ALSA returns nothing. This happens if the kernel overlay failed to load, or if dtparam=audio=off was omitted, leaving the system with no valid capture routing.
Fix: Run dmesg | grep i2s. If you see no output, your dtoverlay line in config.txt has a typo. Run sudo raspi-config, go to Interface Options, and ensure I2C/I2S interfaces are enabled, then reboot.
2. "ALSA lib pcm_dmix.c:1075:(snd_pcm_dmix_open) unable to open slave"
Rank: #2 Most Common
Cause: Another audio daemon (PipeWire or PulseAudio, which are default in Bookworm desktop environments) has locked the ALSA device in exclusive mode, or the sample rate requested by Python (44100Hz) doesn't match the hardware's fixed I2S clock divider.
Fix: Stop the audio daemon temporarily to test: systemctl --user stop pipewire. Alternatively, force ALSA to use the hardware device directly by modifying the Python script to use device='hw:1,0' inside the sd.InputStream() arguments instead of relying on the default PulseAudio routing.
3. Recording is 100% Loud White Noise (No Error Thrown)
Rank: #3 Most Common (The Silent Killer)
Cause: You used a generic overlay like dtoverlay=hifiberry-dac or i2s-mmap instead of googlevoicehat-soundcard. The SPH0645 chip shifts data on the falling edge of the clock, while standard I2S expects the rising edge. The data is read bit-shifted by one, resulting in maximum-amplitude random noise.
Fix: Change the overlay in /boot/firmware/config.txt to dtoverlay=googlevoicehat-soundcard, reboot, and re-record.
- Kernel Load: Run
cat /proc/asound/cards. If the I2S card isn't listed, the issue is inconfig.txt, not your Python code. - ALSA Visibility: Run
arecord -l. If the card is listed but Python fails, the issue is PortAudio/PipeWire blocking the device. - Physical Continuity: Use a multimeter in continuity mode to check the BCLK (Pin 12) and LRCLK (Pin 35) traces. I2S requires clean clock edges; a loose dupont wire will cause the Pi's I2S peripheral to hang or output garbage.
Extending and Simplifying the Build
How to Simplify: If you do not strictly need the low-profile form factor or the high SNR (Signal-to-Noise Ratio) of a MEMS I2S mic, buy a $10 USB mini microphone. USB audio class devices require zero kernel overlays, zero GPIO wiring, and work instantly with sounddevice out of the box. I2S is only worth the headache if you are building a custom PCB, need a flush-mounted enclosure, or are doing precise acoustic beamforming.
How to Extend:
- Stereo Array: The SPH0645 breakout has an L/R pad. By soldering the pad to ground on one mic and leaving it open on a second mic, you can wire both DOUT pins to the same GPIO 20 line. The Pi will read them as Left and Right channels on the same I2S bus.
- Local Voice Recognition: Pipe the raw PCM stream directly into whisper.cpp running on the Pi's CPU for offline, low-latency voice command processing without relying on cloud APIs.
Raspberry Pi Microphone FAQ
Why is my raspberry pi microphone recording static or a high-pitch whine?
Beyond the SPH0645 bit-shift issue mentioned above, a high-pitch whine (usually around 1kHz to 3kHz) is almost always caused by the Raspberry Pi's onboard switching DC-DC voltage regulators. The 3.3V rail on the Pi is notoriously noisy. Because the MEMS microphone has a high Power Supply Rejection Ratio (PSRR) but is physically millimeters away from the Pi's power inductors, it picks up magnetic and conducted noise. To fix this, add a 10µF ceramic capacitor and a 100nF capacitor directly across the VIN and GND pins on the microphone breakout board to filter high-frequency switching noise.
Can I use a raspberry pi microphone for real-time voice recognition without latency?
Yes, but you must tune the ALSA buffer sizes. By default, PortAudio requests large buffers (e.g., 4096 frames) to prevent dropouts, which introduces 80ms+ of latency. In the Python script above, we set blocksize=1024. For true real-time keyword spotting, drop the blocksize to 256 or 512. Ensure your Pi is actively cooled; if the CPU thermally throttles during inference, the I2S DMA interrupts will be delayed, causing audio buffer underruns and stuttering.
Do I need an external power supply or BMS for a raspberry pi microphone?
No. The SPH0645LM4H draws less than 1.2mA of current during active operation. The Raspberry Pi's 3.3V rail can easily supply hundreds of milliamps. You do not need an external regulator or a Battery Management System (BMS) specifically for the microphone, even if you are running the Pi off a LiFePO4 or 18650 battery pack via a buck converter. Just ensure your main Pi power delivery is stable.
How do I test the raspberry pi microphone without writing Python code?
Use the native ALSA command-line tools. Run arecord -D hw:1,0 -f S16_LE -r 44100 -c 1 test.wav to record a 5-second clip (press Ctrl+C to stop), then play it back with aplay test.wav. If this works but your Python script fails, the issue is strictly within your Python environment or PortAudio installation, not the hardware or kernel.






