Skip to main content
Raspberry Pi HATs

Building a Class D Audio Amplifier HAT

Overview

This tutorial walks through a Raspberry Pi HAT that turns the Pi's PWM audio outputs into a small stereo speaker amplifier. The design uses a PAM8403 Class D amplifier, two volume controls, screw-terminal style speaker headers, input filtering, and local power decoupling.

The PAM8403 is a filterless Class D amplifier that can drive two small speakers from a 5V rail. It is commonly used for compact 3W-per-channel projects. The speaker outputs are bridge-tied load outputs, so the L- and R- terminals must not be connected to ground.

Circuit Requirements

The HAT should include:

  • PAM8403 stereo Class D amplifier powered from the Pi 5V rail
  • Two low-pass filters for Raspberry Pi PWM audio on GPIO18 and GPIO19
  • Two volume controls, one per channel
  • Pull-ups for shutdown and mute so the amplifier starts enabled
  • Decoupling close to the amplifier power pins
  • Left and right two-pin speaker terminals

How the Class D Output Works

The PAM8403 switches each speaker output at a high frequency and uses the speaker coil as part of the output filtering. Each channel is a bridge-tied load: both speaker terminals move, and neither terminal is ground. This doubles the available voltage swing compared with a single-ended output, which is how the small 5V amplifier can deliver useful speaker power.

Use 4 ohm or 8 ohm speakers rated for the power you expect to use. Keep speaker leads short, route the OUTL and OUTR pairs together, and avoid running the speaker traces beside the sensitive input traces.

Building the Circuit Step by Step

Step 1: Start with the HAT board

The RaspberryPiHatBoard component provides the 40-pin header and the normal HAT outline.

import { RaspberryPiHatBoard } from "@tscircuit/common"

export default () => (
<RaspberryPiHatBoard name="HAT1">
{/* Amplifier circuit goes here */}
</RaspberryPiHatBoard>
)

Step 2: Add the PAM8403 amplifier

The amplifier is represented as a 16-pin chip. The pin labels make the traces read like the datasheet signals instead of raw package pin numbers.

<chip
name="U1"
footprint="soic16"
manufacturerPartNumber="PAM8403"
pinLabels={{
pin1: ["INL"],
pin2: ["INR"],
pin5: ["OUTL_P"],
pin7: ["OUTL_N"],
pin9: ["OUTR_N"],
pin11: ["OUTR_P"],
pin12: ["SD"],
pin13: ["MUTE"],
pin14: ["VDD"],
}}
/>

Step 3: Filter the Raspberry Pi audio pins

Raspberry Pi PWM audio can be output on GPIO18 and GPIO19. A simple RC filter turns the PWM waveform into an analog-ish signal before the volume controls. The example uses 270 ohm and 33nF, a small starting point that can be adjusted for your noise and bandwidth targets.

<resistor name="R1" resistance="270" footprint="0402" />
<capacitor name="C1" capacitance="33nF" footprint="0402" />
<trace from=".HAT1_chip .GPIO_18" to=".R1 > .pin1" />
<trace from=".R1 > .pin2" to=".C1 > .pin1" />
<trace from=".C1 > .pin2" to="net.GND" />

Step 4: Add volume controls

Use one 10k potentiometer for the left channel and one for the right channel. For a real product, choose a dual-gang audio-taper potentiometer so both channels track together from one knob.

<potentiometer name="RVL" maxResistance="10k" footprint="pinrow3" />
<potentiometer name="RVR" maxResistance="10k" footprint="pinrow3" />
<trace from=".RVL > .pin2" to=".U1 .INL" />
<trace from=".RVR > .pin2" to=".U1 .INR" />

Step 5: Keep the amplifier enabled

The SD and MUTE pins are pulled to 5V through 10k resistors. If you want software-controlled mute later, route those pins to spare GPIO pins instead.

<resistor name="R3" resistance="10k" footprint="0402" />
<resistor name="R4" resistance="10k" footprint="0402" />
<trace from=".R3 > .pin1" to="net.V5" />
<trace from=".R3 > .pin2" to=".U1 .SD" />
<trace from=".R4 > .pin1" to="net.V5" />
<trace from=".R4 > .pin2" to=".U1 .MUTE" />

Step 6: Add speaker terminals

Each channel uses a two-pin terminal. Keep the polarity labels visible on the silkscreen, but remember that L- and R- are amplifier outputs, not ground.

<pinheader
name="J2"
pinCount={2}
gender="female"
pitch="3.5mm"
footprint="pinrow2"
pinLabels={["L+", "L-"]}
showSilkscreenPinLabels
/>
<trace from=".U1 .OUTL_P" to=".J2 > .pin1" />
<trace from=".U1 .OUTL_N" to=".J2 > .pin2" />

PCB Layout

Place the PAM8403 near the speaker terminals so the high-current speaker traces are short. Put the 100nF decoupling capacitor as close as possible to the power pins, with the 10uF bulk capacitor nearby. Keep the input filters and potentiometer traces on the other side of the amplifier from the speaker output pairs.

import { RaspberryPiHatBoard } from "@tscircuit/common"

export default () => (
<RaspberryPiHatBoard name="HAT1">
<chip name="U1" footprint="soic16" manufacturerPartNumber="PAM8403" pcbX={0} pcbY={0} />
<resistor name="R1" resistance="270" footprint="0402" pcbX={-20} pcbY={8} />
<resistor name="R2" resistance="270" footprint="0402" pcbX={-20} pcbY={-8} />
<capacitor name="C1" capacitance="33nF" footprint="0402" pcbX={-14} pcbY={8} />
<capacitor name="C2" capacitance="33nF" footprint="0402" pcbX={-14} pcbY={-8} />
<potentiometer name="RVL" maxResistance="10k" footprint="pinrow3" pcbX={-8} pcbY={10} />
<potentiometer name="RVR" maxResistance="10k" footprint="pinrow3" pcbX={-8} pcbY={-10} />
<capacitor name="C3" capacitance="100nF" footprint="0402" pcbX={12} pcbY={4} />
<capacitor name="C4" capacitance="10uF" footprint="0603" pcbX={12} pcbY={-4} />
<pinheader name="J2" pinCount={2} gender="female" pitch="3.5mm" footprint="pinrow2" pcbX={22} pcbY={8} />
<pinheader name="J3" pinCount={2} gender="female" pitch="3.5mm" footprint="pinrow2" pcbX={22} pcbY={-8} />
</RaspberryPiHatBoard>
)
PCB Circuit Preview

Bill of Materials

RefPartNotes
U1PAM8403 stereo Class D amplifier5V, filterless BTL output
RVL, RVR10k potentiometerUse a dual-gang audio-taper part for one knob
R1, R2270 ohm resistorPWM low-pass filter series resistor
C1, C233nF capacitorPWM low-pass filter shunt capacitor
R3, R410k resistorPull SD and MUTE high
C3100nF capacitorHigh-frequency decoupling
C410uF capacitorLocal bulk supply capacitance
C51uF capacitorBypass/reference capacitor
J2, J32-pin speaker terminalOne terminal block per channel

Raspberry Pi Audio Configuration

Enable PWM audio by adding the audio overlay to /boot/firmware/config.txt on newer Raspberry Pi OS images:

dtparam=audio=on
dtoverlay=audremap,pins_18_19

After rebooting, select the analog/PWM output in your audio settings or with raspi-config. Start testing at a low volume:

speaker-test -t sine -f 440 -c 2

For a quick Python check, play a short WAV file through ALSA or use any normal Linux audio player. The HAT does not need a driver when it is fed from the Pi's PWM audio pins.

Testing Procedure

  1. With the HAT unpowered, check continuity from each speaker terminal to the expected PAM8403 output pin.
  2. Confirm neither speaker terminal is shorted to ground.
  3. Power the Pi with no speakers connected and confirm 5V is present at the PAM8403 power pins.
  4. Connect one speaker, keep volume low, and play a sine wave.
  5. Repeat with the second speaker and verify left/right channel assignment.

Next Steps

  • Add a GPIO-controlled mute input
  • Replace the two separate potentiometers with a dual-gang audio potentiometer
  • Add an EEPROM for full Raspberry Pi HAT identification
  • Add ferrite beads or extra LC filtering if your speaker wiring is long