In this tutorial you will learn how to build an 30 Watt Stereo Amplifier and an Internet, Bluetooth or MP3 radio with a TPA31110 XH-A232 amplifier, a PCM5102 DAC and an ESP32 microcontroller.
The ESP32 produces a digital audio signal, which is converted to an analog audio signal using the PCM5102 Digital-Analog-Converter, which is then amplified by the TPA31110 XH-A232.
While the PCM5102 can only drive high-impedance headphones and active speakers, the TPA31110 XH-A232 can drive passive speakers with up to 30 Watts. If you want to build a Internet, Bluetooth or MP3 radio with higher audio output then this tutorial is for you.
Required Parts
For this project we will need a PCM5102 DAC module, a TPA31110 XH-A232 Amplifier Board, an ESP32 and a pair of passive speakers. You can use other speakers than the ones I listed – just make sure that their power rating is around 30 watts.
Similarly, you can use a different ESP32 board. Most ESP32 boards will be fine but you should go for an ESP32-S3 board with PSRAM, if you plan to store and play music from memory.
To play MP3 files from an SD Card you will furthermore need an SD Card and an SD Card reader module.
Finally, a breadboard and some cables will be handy for a temporary build. Or you solder everything together.

TPA31110 XH-A232 Amplifier

PCM5102 DAC

2 x Speaker 4 Ohm 25 Watts

Micro SD Card Reader

Micro SD Card 8GB

ESP32 lite

USB Data Cable

Dupont Wire Set

Breadboard
Makerguides is a participant in affiliate advertising programs designed to provide a means for sites to earn advertising fees by linking to Amazon, AliExpress, Elecrow, and other sites. As an Affiliate we may earn from qualifying purchases.
Technical Features of the TPA31110 XH-A232
The TPA3110 XH-A232 is a compact stereo audio amplifier board built around the Texas Instruments TPA3110 Class-D audio amplifier chip. This module is designed as a complete amplification stage suitable for small to medium audio systems.
The board integrates the necessary input, power, and output circuitry onto a single printed circuit, letting it interface readily with microcontrollers like Arduino or ESP32 for audio playback and amplification tasks.
Amplifier Architecture and Power Handling
At the heart of the board is the TPA3110 Class-D amplifier core, a switching amplifier architecture that uses high-frequency PWM (pulse-width modulation) to achieve efficient audio power amplification with minimal heat generation. Unlike linear amplifiers, Class-D stages switch output transistors rapidly between on and off states, significantly reducing conduction losses and enabling higher overall system efficiency.
The TPA3110 on this board is configured to deliver up to approximately 30 W per channel into 4 Ω–8 Ω loads when powered from a sufficiently high DC supply voltage, preferably in the 12 V to 24 V range. The dual-channel configuration allows simultaneous left and right stereo outputs from a single amplifier board. The picture below shows the pinout of the TPA31110 XH-A232 board.

Under normal operation, the amplifier requires a DC supply capable of delivering around 3 A to support near-maximum audio output. The board includes decoupling and filtering components to stabilize these currents and reduce supply noise. Output impedance matching is typically suited for 4 Ω to 8 Ω speakers.
Signal Handling and Audio Performance
The TPA3110 XH-A232 board accepts line-level analog audio input, which is then amplified by the internal TPA3110. Input sensitivity is around 0.775 V. Frequency response is typically flat from roughly 20 Hz up to 20 kHz. Signal-to-noise ratio is around 100 dB, and total harmonic distortion is ≤ 0.1 % under normal conditions.
Protection Features
The board incorporates several protection mechanisms to improve reliability in practical use. Over-voltage protection guards against excessive supply voltage, while short-circuit and over-current protection help prevent damage if the speaker outputs are inadvertently shorted or overloaded. Thermal protection is also present, activating if the amplifier IC or board temperatures exceed safe limits. The module is designed to recover automatically once conditions return to safe levels.
Technical Specification
| Parameter | Specification |
|---|---|
| Module Model | XH-A232 |
| Amplifier IC | TPA3110 Class-D |
| Channels | 2.0 (stereo) |
| Nominal Output Power | 30 W + 30 W (into 4 Ω loads, dependent on supply and load) |
| Supply Voltage | DC ~8 V to 26 V (typical operation around 12 – 24 V) |
| Recommended Supply Current | ≥ 3 A |
| Input Sensitivity | ~0.775 V (line-level) |
| Input Impedance | ~20 kΩ |
| Speaker Load Impedance | 4 Ω – 8 Ω |
| Signal-to-Noise Ratio (SNR) | ~100 dB |
| Total Harmonic Distortion (THD) | ≤ 0.1 % |
| Frequency Response | ~20 Hz – 20 kHz |
| Protection Features | Over-voltage, over-current/short-circuit, thermal protection |
| Physical Dimensions | Approx. 53 × 45 × 14 – 15 mm |
| Approximate Weight | ~20 – 25 g |
Connecting the TPA31110 XH-A232 with PCM5102 and ESP32
In this section we are connecting the TPA31110 XH-A232 Amplifier to the PCM5102 DAC and the ESP32 microcontroller. The picture below shows the complete wiring diagram:

We start by connecting the ESP32 to the PCM5102 via the I2S interface. You could configure different pins (see the code in later sections) but here I am using LCK=32, BCK=25 and DIN=33. The following table shows the complete connections between the ESP32 and the PCM5102 :
| PCM5102A | ESP32 |
|---|---|
| VIN | 3V3 |
| GND | G |
| LRCK | 32 |
| BCK | 25 |
| DIN | 33 |
| SCK | G |
If you have soldered the SCK bridge on the PCM5102 you actually won’t need the SCK to ground connection but it doesn’t do any harm. I strongly recommend that you read the Playing Audio with ESP32 and PCM5102A tutorial, if you haven’t configured or used the PCM5102 before. There are other bridges that need to be soldered to ensure that the PCM5102 works!
Next we connect the TPA31110 XH-A232 Amplifier via line out to the PCM5102. The following table shows the connections you need to make:
| TPA31110 XH-A232 | PCM5102 |
|---|---|
| L | LROUT |
| bJ | AGND |
| R | ROUT |
Note that the labelling of the pins of the TPA31110 XH-A232 and the PCM5102 is confusing. The left channel output on the PCM5102 should be labelled “ROUT” but actually reads “LROUT”. The middle pin for the line input reads as “bJ” but should be labelled “G” for ground.
Also note that you will need a separate power supply for the TPA31110 XH-A232 that can deliver between 12V up to 24V and 3A .
Polarity of Speakers
The right and left loudspeakers are connected to the R+, R-, L+ and L- pins of the TPA31110 XH-A232. Make sure that you match the polarity of the output pins with the polarity of the speaker pins. Typically the speaker pins are marked with “+” and “-” signs or have differently shaped pins (thinner for minus).

If there are no markings, you can connect a 1.5V AA battery and if the membrane moves outwards, the plus pole of the battery indicates the plus pole of the speaker. Loudspeaker polarity is defined so that a positive voltage produces forward cone motion.
Connecting SD Card Reader
If you want to play MP3 files you need to connect an SD Card reader that stores the audio files on an SD Card. The wiring diagram below shows you how to connect an additional SD Card reader:

The SD Card Reader communicates via SPI and the default SPI pins of the ESP32 for SPI are CS=5, MOSI=23, CLK=18 and MISO=19. The table below summarizes the connections you need to make between the SD Card Reader and the ESP32:
| SD Card Reader | ESP32 |
|---|---|
| 3V3 | 3V |
| GND | G |
| CS/SS | 5 |
| MOSI | 23 |
| CLK/SCK | 18 |
| MISO | 19 |
If you are not sure which pins are the default SPI pins of your ESP32 have a look at the Find I2C and SPI default pins tutorial.
The following photo shows my wiring of the TPA31110 XH-A232 and PCM5102A with an SD Card Reader, an ESP32 and two speaker for testing:

Installing Libraries
We are going to use arduino-audio-tools library by Phil Schatzmann to build our Internet, Bluetooth and MP3 player. To install this library go to the arduino-audio-tools repo, click on the green “<> Code” button and then “Download ZIP” to download the library as a ZIP file as shown below:

Then open a Sketch, go to Sketch -> Include Library -> Add .ZIP Library … to install the downloaded ZIP library (arduino-audio-tools-main.zip):

For some of the code examples we need two more libraries by Phil Schatzmann; namely the arduino-libhelix library and the ESP32-A2DP library. You can install them in the same way. Click on the link to go to the github repo, click on the green “<> Code” button to download the libraries (arduino-libhelix-main.zip, ESP32-A2DP-main.zip) and then install them.
Finally, if this is the first time you program an ESP32 board from your Arduino IDE, you will need to install the ESP32 core as well. For details see the Install ESP32 core in Arduino IDE tutorial.
In the next three sections I will show you the code to build a Bluetooth Player, an Internet Radio and an MP3 Player using the arduino-tools-library.
Code for a Bluetooth Player
This first code example configures an ESP32 to operate as a Bluetooth A2DP audio sink that receives stereo audio streams from a paired device such as a smartphone and outputs the digital audio data via the I2S peripheral.
/*
www.makerguides.com
Libraries:
- ESP32 Core 3.3.6
- [arduino-audio-tools](https://github.com/pschatzmann/arduino-audio-tools)
Version: 1.2.2
- [arduino-libhelix](https://github.com/pschatzmann/arduino-libhelix)
Version: 0.9.2
- [ESP32-A2DP](https://github.com/pschatzmann/ESP32-A2DP)
Version: 1.8.8
*/
#include "AudioTools.h"
#include "BluetoothA2DPSink.h"
#define DIN_PIN 33 // serial data
#define LRCK_PIN 32 // word select
#define BCLK_PIN 25 // serial clock
I2SStream i2s;
BluetoothA2DPSink a2dp_sink(i2s);
void setup() {
auto config = i2s.defaultConfig();
config.pin_bck = BCLK_PIN;
config.pin_ws = LRCK_PIN;
config.pin_data = DIN_PIN;
i2s.begin(config);
a2dp_sink.start("MyMusic");
}
void loop() { }
The code initializes an I2SStream interface with the assigned bit clock, word select, and serial data pins, which are connected to a PCM5102 digital-to-analog converter. The PCM5102 converts the incoming I2S digital audio signal into an analog stereo signal, which is then amplified by the TPA3110-based XH-A232 amplifier module to drive two connected speakers.
During setup, the ESP32 initializes the I2S driver with the specified pin configuration and starts the Bluetooth A2DP sink with the device name “MyMusic”, making the ESP32 discoverable as a Bluetooth audio receiver.
Once paired and connected, audio streamed over Bluetooth is routed directly through the I2S interface to the DAC and subsequently amplified for playback. The main loop remains empty because audio handling and Bluetooth communication are managed internally by the underlying libraries and run asynchronously in the background.
Code for an Internet Radio
This code example uses an ESP32 as a Wi-Fi internet radio receiver that streams an online MP3 audio feed, decodes it in real time, and again outputs the audio signal via I2S to the PCM5102A DAC. The analog signal generated by the DAC is then amplified by the TPA31110 XH-A232 to drive the connected speakers.
/*
www.makerguides.com
Libraries:
- ESP32 Core 3.3.6
- [arduino-audio-tools](https://github.com/pschatzmann/arduino-audio-tools)
Version: 1.2.2
- [arduino-libhelix](https://github.com/pschatzmann/arduino-libhelix)
Version: 0.9.2
*/
#include <Arduino.h>
#include <WiFi.h>
#include <Wire.h>
#include "AudioTools.h"
#include "AudioTools/AudioCodecs/CodecMP3Helix.h"
#include "AudioTools/Communication/HTTP/ICYStream.h"
// PCM5102A
#define DIN_PIN 33 // serial data
#define LRCK_PIN 32 // word select
#define BCLK_PIN 25 // serial clock
#define VOLUME 0.3 // Volume
const char* ssid = "ssid";
const char* password = "pwd";
const char* url = "https://jazz.stream.laut.fm/jazz";
ICYStream icystream;
I2SStream i2s;
VolumeStream volume(i2s);
EncodedAudioStream mp3decode(&volume, new MP3DecoderHelix());
StreamCopy copier(mp3decode, icystream);
void callbackMetadata(MetaDataType type, const char* str, int len) {
Serial.printf("%s: %s\n", toStr(type), str);
}
void setup() {
Serial.begin(115200);
AudioLogger::instance().begin(Serial, AudioLogger::Warning);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
auto config = i2s.defaultConfig(TX_MODE);
config.pin_bck = BCLK_PIN;
config.pin_ws = LRCK_PIN;
config.pin_data = DIN_PIN;
i2s.begin(config);
volume.begin(config);
volume.setVolume(VOLUME);
mp3decode.begin();
icystream.begin(url);
icystream.setMetadataCallback(callbackMetadata);
}
void loop() {
copier.copy();
}
During setup, the ESP32 connects to a specified Wi-Fi network using the provided SSID and password. You will need to replace the strings “ssid” and “pwd” with the credentials of your Wi-Fi network.
Once the wireless connection is established, the code initializes the I2S peripheral in transmit mode and assigns the bit clock, word select, and serial data pins to match the PCM5102A hardware interface. A VolumeStream object is layered on top of the I2S stream to apply digital volume scaling before the audio data is sent to the DAC.
The program opens an HTTP connection to the specified streaming URL using an ICYStream, which supports ICY metadata commonly used by internet radio stations. The incoming MP3-encoded audio data is passed to an EncodedAudioStream configured with the Helix MP3 decoder, which performs real-time decoding of the compressed audio frames into raw PCM samples. These decoded samples are then forwarded through the volume control stage and ultimately transmitted over I2S to the DAC.
A metadata callback function is registered to receive and print stream metadata such as the current track title to the serial monitor. In the main loop, the StreamCopy object continuously transfers data from the network stream through the decoder and audio processing chain, ensuring uninterrupted playback as long as the stream remains available.
In the following a list of URLs for some other internet radio stations you can try out:
"https://jazz.stream.laut.fm/jazz" "http://vis.media-ice.musicradio.com/CapitalMP3"; "http://stream.srg-ssr.ch/m/rsj/mp3_128" "http://stream.live.vc.bbcmedia.co.uk/bbc_world_service" "http://icecast.omroep.nl/radio1-bb-mp3" "http://stream-02-eu.relaxingjazz.com/stream/1/"
Code for an MP3 Player
This last program uses the ESP32 as a standalone MP3 audio player that reads audio files from an SD card, decodes them in real time, and outputs the resulting PCM signal via the I2S interface to the PCM5102A DAC. The analog output of the DAC is then amplified by the TPA31110 XH-A232 and send to the speakers.
/*
www.makerguides.com
Libraries:
- ESP32 Core 3.3.6
- [arduino-audio-tools](https://github.com/pschatzmann/arduino-audio-tools)
Version: 1.2.2
- [arduino-libhelix](https://github.com/pschatzmann/arduino-libhelix)
Version: 0.9.2
*/
#include "AudioTools.h"
#include "AudioTools/Disk/AudioSourceSD.h"
#include "AudioTools/AudioCodecs/CodecMP3Helix.h"
// PCM5102A
#define DIN_PIN 33 // serial data
#define LRCK_PIN 32 // word select
#define BCLK_PIN 25 // serial clock
#define VOLUME 0.5 // Volume
#define PATH "/"
#define EXT "mp3"
AudioSourceSD source(PATH, EXT);
I2SStream i2s;
MP3DecoderHelix decoder;
AudioPlayer player(source, i2s, decoder);
void printMetaData(MetaDataType type, const char* str, int len){
Serial.printf("%s: %s\n", toStr(type), str);
}
void setup() {
Serial.begin(115200);
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Warning);
auto config = i2s.defaultConfig(TX_MODE);
config.pin_bck = BCLK_PIN;
config.pin_ws = LRCK_PIN;
config.pin_data = DIN_PIN;
i2s.begin(config);
player.setMetadataCallback(printMetaData);
player.setVolume(VOLUME);
player.begin();
}
void loop() {
player.copy();
}
An AudioSourceSD object is initialized to access MP3 files stored on the SD card in the root directory. The source is configured to select files with the “mp3” extension, allowing the system to iterate through compatible audio files available on the card. The AudioPlayer object combines the SD card source, an I2S output stream, and the Helix MP3 decoder into a single playback pipeline.
During setup, the ESP32 initializes serial communication for debugging and configures the I2S peripheral in transmit mode with explicitly assigned bit clock, word select, and serial data pins connected to the PCM5102A. The audio player is configured with a metadata callback function to print information such as track title or artist to the serial monitor when available. A digital volume level is also set before playback begins.
In the main loop, the player.copy() function continuously processes the audio stream. The player reads MP3 data from the SD card, decodes it using the Helix decoder into raw PCM samples, and sends the processed audio through the I2S interface to the DAC for playback. This loop-driven streaming mechanism ensures continuous audio output as long as valid MP3 files are available on the SD card.
Conclusions
In this project, you learned how to play audio using the ESP32 and the TPA31110 XH-A232 amplifier in conjunction with a PCM5102 DAC. We explored the technical details of the TPA31110 XH-A232 and how to wire it to the ESP32. You also learned how to stream internet radio, play MP3 files from an SD Card and play audio via Bluetooth. For more code examples see the examples folder of the arduino-tools-library.
This tutorial is based on the PCM5102 DAC. For more information on the PCM5102 see the Playing Audio with ESP32 and PCM5102A tutorial. Similarly, if you need more background on the SD Card Reader module used here, have a look at the SD Card Module with ESP32 tutorial.
Finally, if you don’t need 30 Watts of stereo output and want a simpler solution read our Playing Audio with ESP32 and MAX98357 tutorial. The MAX98357A is a DAC with a built-in amplifier that can drive small 3 Watt speakers. It won’t be as load as with the TPA31110 XH-A232 amplifier but the circuit is simpler and you can use smaller and cheaper speakers.
Feel free to leave any further questions in the comment section.
Happy Tinkering ; )
Stefan is a professional software developer and researcher. He has worked in robotics, bioinformatics, image/audio processing and education at Siemens, IBM and Google. He specializes in AI and machine learning and has a keen interest in DIY projects involving Arduino and 3D printing.

