Skip to content

Using a Digital-to-Analog Converter (DAC)

Welcome to the DAC Lab

Monty waving welcome Your Pico speaks in digital numbers — ones and zeros. But speakers need a smooth, changing voltage to make sound. A DAC is the translator that turns digital numbers into smooth audio signals. Let's build something amazing!

What Is a DAC?

A Digital-to-Analog Converter (DAC) takes a stream of digital numbers and turns them into a smoothly changing voltage. That smooth voltage is what you feed into a speaker or amplifier to produce sound.

Without a DAC: - The Pico can only output a square wave (buzzer-style tones) - Audio quality is harsh and robotic

With a DAC: - The Pico outputs real audio waveforms - You can play music, speech, and sound effects at CD quality

Key Idea

Monty thinking Think of the DAC like a very fast water faucet. The Pico tells it a number (say, 127 out of 255), and the DAC opens the faucet to exactly halfway. Change the number thousands of times per second, and you get smooth audio.

Types of DAC Connections

There are two common ways to add a DAC to a MicroPython project:

1. I2S DAC Modules

The most popular approach. The Pico sends audio data over the I2S bus to a DAC chip that converts it to an analog signal.

Popular I2S DAC modules:

Module Max Power Notes
MAX98357A 3 W mono Has a built-in amplifier — connect speaker directly
PCM5102A — (headphone level) High quality stereo, no amplifier
UDA1334A — (headphone level) Stereo with I2S and optical input

The MAX98357A is the best choice for beginners because it combines the DAC and a speaker amplifier in one board — no extra amplifier needed.

2. PWM as a Rough DAC

The Pico does not have a true analog output pin, but you can use PWM with a low-pass filter (a resistor and capacitor) to create a rough approximation of analog audio. This works for speech playback and simple sound effects but is not suitable for music.

Wiring a MAX98357A to the Pico

MAX98357A Pin Pico Pin Signal
VIN 3V3 (pin 36) 3.3 V power
GND GND Ground
BCLK GP10 I2S bit clock (SCK)
LRC GP11 I2S word select (WS)
DIN GP9 I2S serial data (SD)
+ (speaker) Speaker + Speaker positive terminal
− (speaker) Speaker − Speaker negative terminal

Connect a small 4 Ω or 8 Ω speaker (0.5 W to 3 W) to the + and − output terminals on the MAX98357A module.

Watch Out!

Monty warning Never connect a speaker directly to a GPIO pin. The GPIO pin can only supply about 3 mA — not nearly enough to drive a speaker. Always use an amplifier like the MAX98357A between the Pico and the speaker.

Sample Program: Play a Sine Wave

This program generates a 440 Hz sine wave (the note A4) and plays it through a MAX98357A:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
from machine import I2S, Pin
import math

# I2S pins for the MAX98357A
SCK_PIN = 10
WS_PIN  = 11
SD_PIN  = 9

# Set up the I2S transmitter
audio_out = I2S(
    0,
    sck=Pin(SCK_PIN),
    ws=Pin(WS_PIN),
    sd=Pin(SD_PIN),
    mode=I2S.TX,
    bits=16,
    format=I2S.MONO,
    rate=22050,         # 22.05 kHz sample rate
    ibuf=10000
)

SAMPLE_RATE = 22050
FREQUENCY   = 440       # Hz — the note A4
DURATION    = 3         # seconds
AMPLITUDE   = 30000     # volume (max 32767 for 16-bit)

# Generate one full cycle of a sine wave
samples_per_cycle = SAMPLE_RATE // FREQUENCY
one_cycle = bytearray(samples_per_cycle * 2)  # 2 bytes per 16-bit sample

for i in range(samples_per_cycle):
    sample = int(AMPLITUDE * math.sin(2 * math.pi * i / samples_per_cycle))
    # Pack the 16-bit sample as little-endian bytes
    one_cycle[i * 2]     = sample & 0xFF
    one_cycle[i * 2 + 1] = (sample >> 8) & 0xFF

# Play for DURATION seconds
total_bytes = SAMPLE_RATE * DURATION * 2   # 2 bytes per sample
bytes_written = 0
while bytes_written < total_bytes:
    audio_out.write(one_cycle)
    bytes_written += len(one_cycle)

audio_out.deinit()

What Each Line Does

Line Purpose
I2S(0, mode=I2S.TX, ...) Sets up I2S transmitter on peripheral 0
bits=16 16-bit audio samples (standard CD quality)
format=I2S.MONO Single audio channel
rate=22050 22 050 samples per second
math.sin(...) Calculates the sine wave value at each sample point
audio_out.write(one_cycle) Sends the audio data to the DAC over I2S

Monty's Tip

Monty giving a tip Change FREQUENCY = 440 to other values to play different musical notes. For example, 262 Hz is Middle C, 494 Hz is B4, and 523 Hz is C5.

Great Work!

Monty celebrating You have connected a real DAC and generated an audio signal from scratch! Next, try playing a WAV file from the Pico's flash storage using the Playing Audio Files lab.

References

  1. MAX98357A Datasheet (Maxim)
  2. MicroPython I2S Documentation
  3. I2S Standard Overview