Build a fully functional wireless speaker system using the ESP32's built-in Bluetooth capabilities. By pairing it with a high-fidelity I2S DAC, you can stream CD-quality audio from your phone or laptop to your own custom-built speaker enclosure.
The ESP32 is one of the few microcontrollers that supports the A2DP (Advanced Audio Distribution Profile). This allows it to act as a Bluetooth audio sink. While the ESP32 has internal DACs, they are only 8-bit. In this project, we use an external 24-bit PCM5102 I2S DAC to achieve professional audio quality.
I2S (Inter-IC Sound) is a specialized serial bus for digital audio. It transmits raw audio data without noise or interference, which is then converted to a crisp analog signal by the dedicated DAC module.
| Part Name | Qty |
|---|---|
| ESP32 DevKit V1 | 1 |
| PCM5102 I2S DAC Module | 1 |
| PAM8403 Audio Amplifier | 1 |
| 3W 4Ω Speaker | 2 |
We use the ESP32's standard I2S pins to communicate with the PCM5102. The DAC output then goes to the amplifier.
| Peripheral | Device Pin | ESP32 Pin | Notes |
|---|---|---|---|
| I2S DAC | BCK (Bit Clock) | GPIO 26 | Serial clock |
| I2S DAC | DIN (Data In) | GPIO 22 | Raw audio data |
| I2S DAC | LCK (Word Select) | GPIO 25 | Left/Right channel |
| Power | VCC / GND | 3.3V / GND | Shared with ESP32 |
#include "BluetoothA2DPSink.h"
BluetoothA2DPSink a2dp_sink;
void setup() {
static const i2s_config_t i2s_config = {
.mode = (i2s_mode_t) (I2S_MODE_MASTER | I2S_MODE_TX),
.sample_rate = 44100,
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
.intr_alloc_flags = 0, // default interrupt priority
.dma_buf_count = 8,
.dma_buf_len = 64,
.use_apll = false
};
static const i2s_pin_config_t pin_config = {
.bck_io_num = 26,
.ws_io_num = 25,
.data_out_num = 22,
.data_in_num = I2S_PIN_NO_CHANGE
};
a2dp_sink.set_i2s_config(i2s_config);
a2dp_sink.set_pin_config(pin_config);
a2dp_sink.start("MakersDeck_Speaker");
}
void loop() {
// Bluetooth stack handles audio in background
}