No artigo anterior, “Reproduzindo Áudio WAV no ESP32”, exploramos o uso do ESP32 como plataforma de reprodução de áudio local, utilizando seu DAC interno para gerar sinal analógico diretamente a partir de dados digitais armazenados no próprio microcontrolador.
O passo seguinte nessa evolução é natural: se o ESP32 consegue reproduzir áudio localmente, por que não utilizá-lo também como receptor de áudio via Bluetooth?
É exatamente essa a proposta deste projeto.
Neste artigo será apresentado o desenvolvimento de um Monitor de Áudio Bluetooth programável, no qual o ESP32 se torna uma interface inteligente de mídia. A ideia central é transformar um simples receptor Bluetooth em uma plataforma aberta e totalmente programável, na qual o desenvolvedor possui controle sobre cada etapa do fluxo de áudio.
Módulos receptores Bluetooth dedicados são extremamente práticos para aplicações diretas — como transformar uma caixa ativa em Bluetooth. Nesses casos, essas soluções são suficientes.
Entretanto, o desenvolvedor não tem acesso ao protocolo, não controla os comandos de mídia e não pode interferir no processamento interno do áudio.
Ao utilizar o ESP32, a abordagem muda completamente. Torna-se possível implementar o perfil A2DP diretamente no firmware e também controlar o protocolo AVRCP, responsável pelos comandos de reprodução.
Para implementar a recepção de áudio Bluetooth via A2DP utilizaremos a biblioteca ESP32-A2DP, desenvolvida por Phil Schatzmann.
Essa biblioteca utiliza recursos da biblioteca AudioTools, também desenvolvida pelo mesmo autor.
Passo 1 – Baixar as bibliotecas
Acesse o repositório oficial da biblioteca ESP32-A2DP no GitHub
Acesse o repositório oficial da biblioteca AudioTools no GitHub
Em cada repositório, clique em Code → Download ZIP para baixar os arquivos.
Passo 2 – Instalar na Arduino IDE
Abra a Arduino IDE
Vá em Sketch → Incluir Biblioteca → Adicionar Biblioteca .ZIP
Selecione o arquivo ZIP baixado
Repita o processo para a segunda biblioteca
Passo 3 – Verificar o core do ESP32
A biblioteca depende do suporte oficial ao ESP32 na Arduino IDE.
Verifique em: Ferramentas → Placa → Gerenciador de Placas
Instale (ou atualize) o pacote oficial da Espressif para o ESP32.
Após esses passos, o ambiente estará pronto para compilar exemplos básicos de recepção A2DP.



O áudio Bluetooth no ESP32 utiliza o perfil A2DP (Advanced Audio Distribution Profile), responsável por transmitir áudio estéreo de alta qualidade entre dispositivos, como celular e receptor. A biblioteca ESP32-A2DP implementa esse protocolo de forma simplificada, permitindo que o microcontrolador atue como um receptor Bluetooth.
Após o recebimento e a decodificação do áudio via Bluetooth, o próximo passo é a conversão do sinal digital para analógico — etapa necessária para que o som possa ser amplificado e reproduzido em um alto-falante, essa conversão pode ser feita utilizando o DAC interno onboard ou enviando o áudio digital para um DAC externo via interface I²S.
A diferença entre as duas abordagens está principalmente na qualidade sonora e na arquitetura do projeto. O DAC interno oferece simplicidade, menos componentes e montagem mais direta. Já o DAC externo via I²S adiciona um módulo ao sistema, mas entrega menor nível de ruído, melhor resposta de frequência e maior fidelidade sonora.

Uma das maiores vantagens de usar o ESP32 como receptor Bluetooth é a possibilidade de criar uma interface física personalizada, utilizando a própria biblioteca para enviar comandos de controle de mídia ao dispositivo conectado (celular, tablet ou computador).
Isso significa que você pode construir seu próprio painel físico utilizando: Botões táteis, Chaves seletoras, Potenciômetros, Displays informativos, e muito mais!
Você pode começar com dois botões simples e evoluir para um painel completo com display, indicador de volume, nome da faixa e até integração com outros sistemas. O hardware se torna apenas a interface física — enquanto a biblioteca faz o trabalho pesado da comunicação Bluetooth.
A biblioteca ESP32-A2DP fornece um conjunto direto de métodos para inicialização do Bluetooth, controle de reprodução, ajuste de volume, monitoramento de conexão e configuração da interface I²S no ESP32.
Essas funções representam uma camada de abstração que encapsula a complexidade do protocolo Bluetooth A2DP e do controle AVRCP. Em vez de lidar diretamente com a implementação de baixo nível, o desenvolvedor interage com métodos objetivos e diretos, simplificando a lógica do sistema.
A tabela a seguir reúne os principais comandos utilizados na construção de um receptor A2DP, servindo como referência prática para implementação, personalização e expansão do projeto.

Diagrama DAC interno – áudio mono (pin25)

Diagrama interface física

#include "AudioTools.h"
#include "BluetoothA2DPSink.h"
// ======================================================
// =============== CONFIGURAÇÃO GERAL ===================
// ======================================================
// --------- Pinos de Controle ---------
const int BTN_PLAY = 32;
const int BTN_NEXT = 33;
const int POT_PIN = 35;
// --------- Parâmetros de Áudio ---------
#define SAMPLE_RATE 44100
#define BITS_PER_SAMPLE 16
// ===== ESCOLHA DO MODO DE SAÍDA =====
#define AUDIO_MONO // ← Descomente para MONO
//#define AUDIO_STEREO // ← Descomente para ESTÉREO
// ======================================================
// ================= OBJETOS ============================
// ======================================================
// DAC interno do ESP32 (GPIO25 ou GPIO26)
AnalogAudioStream analog_out;
BluetoothA2DPSink a2dp_sink(analog_out);
// ======================================================
// ================= CONTROLE ===========================
// ======================================================
bool isPlaying = true;
int lastVolume = -1;
unsigned long lastDebouncePlay = 0;
unsigned long lastDebounceNext = 0;
const unsigned long debounceDelay = 200;
// ======================================================
// ================= SETUP ==============================
// ======================================================
void setup() {
Serial.begin(115200);
pinMode(BTN_PLAY, INPUT_PULLUP);
pinMode(BTN_NEXT, INPUT_PULLUP);
// --------- Configuração do DAC Interno ---------
auto config = analog_out.defaultConfig();
config.sample_rate = SAMPLE_RATE;
config.bits_per_sample = BITS_PER_SAMPLE;
#ifdef AUDIO_MONO
config.channels = 1;
a2dp_sink.set_mono_downmix(true);
Serial.println("Modo MONO (DAC interno)");
#endif
#ifdef AUDIO_STEREO
config.channels = 2;
a2dp_sink.set_mono_downmix(false);
Serial.println("Modo ESTÉREO (DAC interno)");
#endif
analog_out.begin(config);
// --------- Configuração Bluetooth ---------
a2dp_sink.set_volume(80);
a2dp_sink.start("AudioMonitorBT_ESP32");
Serial.println("Monitor de Audio via DAC interno iniciado");
}
// ======================================================
// ================= LOOP ===============================
// ======================================================
void loop() {
// ===== BOTÃO PLAY / PAUSE =====
if (digitalRead(BTN_PLAY) == LOW) {
if (millis() - lastDebouncePlay > debounceDelay) {
if (isPlaying) {
a2dp_sink.pause();
Serial.println("Pause");
} else {
a2dp_sink.play();
Serial.println("Play");
}
isPlaying = !isPlaying;
lastDebouncePlay = millis();
}
}
// ===== BOTÃO NEXT =====
if (digitalRead(BTN_NEXT) == LOW) {
if (millis() - lastDebounceNext > debounceDelay) {
a2dp_sink.next();
Serial.println("Next track");
lastDebounceNext = millis();
}
}
// ===== POTENCIÔMETRO (VOLUME) =====
int potValue = analogRead(POT_PIN); // 0–4095
int volume = map(potValue, 0, 4095, 0, 127);
/* ===== DEBUG ADC =====
Serial.println(potValue);
*/
// ===== ATUALIZA VOLUME (evita ruído excessivo) =====
if (abs(volume - lastVolume) > 2) {
a2dp_sink.set_volume(volume);
lastVolume = volume;
Serial.print("Volume: ");
Serial.println(volume);
}
delay(10);
}#include "AudioTools.h"
#include "BluetoothA2DPSink.h"
// ======================================================
// ======== CONFIGURAÇÃO DE HARDWARE E ÁUDIO ===========
// ======================================================
// --------- Pinos I2S ---------
const int I2S_BCK = 26; // Bit Clock
const int I2S_WS = 27; // Word Select (LRCK)
const int I2S_DATA = 25; // Data Out
// --------- Controles ---------
const int btnPlay = 32;
const int btnNext = 33;
const int potPin = 35;
// --------- Configuração de Áudio ---------
#define SAMPLE_RATE 44100
#define BITS_PER_SAMPLE 16
// ===== ESCOLHA DO MODO DE SAÍDA =====
#define AUDIO_MONO // ← Descomente para MONO
//#define AUDIO_STEREO // ← Descomente para ESTÉREO
// ======================================================
// ================= OBJETOS ============================
// ======================================================
I2SStream i2s;
BluetoothA2DPSink a2dp_sink(i2s);
// ======================================================
// ================= CONTROLE ===========================
// ======================================================
bool isPlaying = true;
int lastVolume = -1;
unsigned long lastDebouncePlay = 0;
unsigned long lastDebounceNext = 0;
const unsigned long debounceDelay = 200;
// ======================================================
// ================= SETUP ==============================
// ======================================================
void setup() {
Serial.begin(115200);
pinMode(btnPlay, INPUT_PULLUP);
pinMode(btnNext, INPUT_PULLUP);
// --------- Configuração I2S ---------
auto config = i2s.defaultConfig(TX_MODE);
config.sample_rate = SAMPLE_RATE;
config.bits_per_sample = BITS_PER_SAMPLE;
#ifdef AUDIO_MONO
config.channels = 1;
a2dp_sink.set_mono_downmix(true);
Serial.println("Modo MONO ativado");
#endif
#ifdef AUDIO_STEREO
config.channels = 2;
a2dp_sink.set_mono_downmix(false);
Serial.println("Modo ESTÉREO ativado");
#endif
// --------- Pinos I2S explícitos ---------
config.pin_bck = I2S_BCK;
config.pin_ws = I2S_WS;
config.pin_data = I2S_DATA;
i2s.begin(config);
a2dp_sink.set_volume(80);
a2dp_sink.start("AudioMonitorBT_ESP32");
Serial.println("Monitor de Audio I2S iniciado");
}
// ======================================================
// ================= LOOP ===============================
// ======================================================
void loop() {
// ===== BOTÃO PLAY / PAUSE =====
if (digitalRead(btnPlay) == LOW) {
if (millis() - lastDebouncePlay > debounceDelay) {
if (isPlaying) {
a2dp_sink.pause();
Serial.println("Pause");
} else {
a2dp_sink.play();
Serial.println("Play");
}
isPlaying = !isPlaying;
lastDebouncePlay = millis();
}
}
// ===== BOTÃO NEXT =====
if (digitalRead(btnNext) == LOW) {
if (millis() - lastDebounceNext > debounceDelay) {
a2dp_sink.next();
Serial.println("Next track");
lastDebounceNext = millis();
}
}
// ===== POTENCIÔMETRO =====
int potValue = analogRead(potPin);
int volume = map(potValue, 0, 4095, 0, 127);
if (abs(volume - lastVolume) > 2) {
a2dp_sink.set_volume(volume);
lastVolume = volume;
Serial.print("Volume: ");
Serial.println(volume);
}
delay(10);
}Vídeo utilizando o ESP32 + Módulo amplificador LM386 + Interface de controle (com saída de áudio via DAC Interna do ESP32)
No vídeo seguinte, está sendo utilizado o ESP32 + módulo amplificador Max98357A (com saída de áudio I2S)
A proposta de utilizar o ESP32 como receptor Bluetooth demonstrou que é possível substituir módulos comerciais fechados por uma solução aberta, flexível e totalmente programável. Ao implementar diretamente os perfis A2DP e AVRCP, o projeto ultrapassa a simples reprodução de áudio e se consolida como uma plataforma de desenvolvimento para sistemas de mídia embarcados, oferecendo autonomia técnica e liberdade de personalização.
A análise das arquiteturas de saída de áudio evidenciou que a escolha entre o DAC interno e um conversor externo via I²S — como o MAX98357A — depende dos objetivos do projeto. Enquanto o DAC interno atende aplicações compactas e funcionais, a solução externa amplia significativamente a qualidade sonora e a robustez do sistema. Essa flexibilidade reforça o caráter modular do ESP32, permitindo equilibrar custo, complexidade e desempenho conforme a necessidade.
A utilização da biblioteca ESP32-A2DP, desenvolvida por Phil Schatzmann, demonstrou que a abstração de alto nível simplifica a implementação dos protocolos Bluetooth sem limitar a expansão do projeto. A possibilidade de integrar botões, potenciômetros e displays transforma o microcontrolador em uma interface física personalizada de mídia, consolidando o sistema como uma base escalável para futuras aplicações — desde monitores de áudio até controladores dedicados.
|
Erwin desenvolve projetos com microcontroladores voltados à geração sonora e aplicações musicais embarcadas. Atua com Arduino, ESP32 e programação em C/C++ e MicroPython, integrando conceitos de eletrônica, acústica e linguagem musical. Possui formação em Licenciatura em Música pela UFRJ e atualmente estuda Redes de Computadores, realizando projetos e laboratórios práticos em sistemas embarcados que unem música e tecnologia.
Tenha a Metodologia Eletrogate dentro da sua Escola! Conheça nosso Programa de Robótica nas Escolas!