-
-
Notifications
You must be signed in to change notification settings - Fork 1
Getting Started
walinsky edited this page Nov 12, 2025
·
3 revisions
Quick start guide for the a2dpSinkHfpClient component.
The a2dpSinkHfpClient component turns your ESP32 into a Bluetooth speaker and hands-free kit with support for:
- 🎵 Music streaming (A2DP)
- 📞 Phone calls (HFP)
- 🎛️ Music control (AVRC)
- 📇 Contact sync (PBAP)
- ESP32 module
- I2S DAC (e.g., PCM5102, MAX98357A)
- I2S Microphone (e.g., INMP441) - optional, needed for calls
- Speakers or headphones
idf.py add-dependency "a2dpSinkHfpClient"cd your_project/components
git clone https://github.com/yourusername/a2dpSinkHfpClient.gitRun idf.py menuconfig and enable:
Component config → Bluetooth → Bluedroid Options
[*] A2DP
[*] Hands Free Profile
[*] Audio (SCO) data path in controller → HCI
[*] Use external codec for mSBC
[*] Phone Book Access Profile
[*] AVRCP
Create main/main.c:
#include "a2dpSinkHfpHf.h"
#include "nvs_flash.h"
void app_main(void) {
// Initialize NVS
nvs_flash_init();
// Configure pins and device name
a2dpSinkHfpHf_config_t config = {
.device_name = "ESP32-Speaker",
.i2s_tx_bck = 26, // Speaker I2S pins
.i2s_tx_ws = 25,
.i2s_tx_dout = 22,
.i2s_rx_bck = 32, // Microphone I2S pins
.i2s_rx_ws = 33,
.i2s_rx_din = 34
};
// Initialize component
a2dpSinkHfpHf_init(&config);
}idf.py build flash monitorYour ESP32 is now discoverable as "ESP32-Speaker" and ready to pair!
#include "a2dpSinkHfpHf.h"
#include "nvs_flash.h"
#include "esp_log.h"
#define TAG "MAIN"
void app_main(void) {
nvs_flash_init();
a2dpSinkHfpHf_config_t config = {
.device_name = "ESP32-HFP",
.i2s_tx_bck = 26,
.i2s_tx_ws = 25,
.i2s_tx_dout = 22,
.i2s_rx_bck = 32,
.i2s_rx_ws = 33,
.i2s_rx_din = 34
};
a2dpSinkHfpHf_init(&config);
ESP_LOGI(TAG, "Waiting for connection...");
// Example: Answer call after 5 seconds (for testing)
vTaskDelay(pdMS_TO_TICKS(5000));
a2dpSinkHfpHf_answer_call();
}#include "a2dpSinkHfpHf.h"
#include "nvs_flash.h"
void metadata_callback(const bt_avrc_metadata_t *metadata) {
if (metadata && metadata->valid) {
printf("Now Playing: %s - %s\n",
metadata->artist, metadata->title);
}
}
void app_main(void) {
nvs_flash_init();
a2dpSinkHfpHf_config_t config = {
.device_name = "ESP32-Music",
.i2s_tx_bck = 26,
.i2s_tx_ws = 25,
.i2s_tx_dout = 22,
.i2s_rx_bck = -1, // No mic needed for music only
.i2s_rx_ws = -1,
.i2s_rx_din = -1
};
// Register metadata callback
a2dpSinkHfpHf_register_avrc_metadata_callback(metadata_callback);
a2dpSinkHfpHf_init(&config);
// Control playback
vTaskDelay(pdMS_TO_TICKS(2000));
a2dpSinkHfpHf_avrc_play();
}| Signal | ESP32 Pin | DAC Pin |
|---|---|---|
| BCK | 26 | BCK |
| WS | 25 | LCK |
| DOUT | 22 | DIN |
| Signal | ESP32 Pin | Mic Pin |
|---|---|---|
| BCK | 32 | SCK |
| WS | 33 | WS |
| DIN | 34 | SD |
Note: You can use any available GPIO pins. The pins shown are examples.
// Set PIN before initialization
a2dpSinkHfpHf_set_pin("5678", 4);
a2dpSinkHfpHf_init(&config);- Add SPIFFS partition to
partitions.csv:
# Name, Type, SubType, Offset, Size
nvs, data, nvs, 0x9000, 0x6000
phy_init, data, phy, 0xf000, 0x1000
factory, app, factory, 0x10000, 1536K
storage, data, spiffs, , 1M
- Set country code in your app:
a2dpSinkHfpHf_set_country_code("1"); // USA
a2dpSinkHfpHf_init(&config);- API Reference - Complete function documentation
- Examples - More code examples
- HFP Control - Phone call control guide
- AVRC Control - Music control guide
- Configuration - Advanced configuration
- Troubleshooting - Common issues
a2dpSinkHfpHf_answer_call(); // Answer call
a2dpSinkHfpHf_reject_call(); // Reject call
a2dpSinkHfpHf_hangup_call(); // Hang up
a2dpSinkHfpHf_dial_number("5551234"); // Dial number
a2dpSinkHfpHf_redial(); // Redial
a2dpSinkHfpHf_start_voice_recognition(); // Start Siri/Assistanta2dpSinkHfpHf_avrc_play(); // Play
a2dpSinkHfpHf_avrc_pause(); // Pause
a2dpSinkHfpHf_avrc_next(); // Next track
a2dpSinkHfpHf_avrc_prev(); // Previous trackbool connected = a2dpSinkHfpHf_is_connected();
bool avrc_connected = a2dpSinkHfpHf_is_avrc_connected();
const bt_avrc_metadata_t *meta = a2dpSinkHfpHf_get_avrc_metadata();