【实践原创】 esp32打造蓝牙音箱
·
开发工具:
-
Arduino IDE
| MAX98357A 引脚 | ESP32 引脚 | 说明 |
|---|---|---|
| VCC | 3.3V | 模块电源(⚠️不要接 5V,否则可能烧芯片) |
| GND | GND | 公共地线 |
| DIN | GPIO25 | I2S 数据线(音频数据输出) |
| BCLK | GPIO27 | I2S 位时钟(Bit Clock) |
| LRCK / WS | GPIO26 | I2S 采样帧同步(左右声道选择) |
| GAIN (可选) | 接地或悬空 | 增益控制:GND=9dB,悬空=15dB,接VCC=6dB |
| SD (或 SD_MODE) (可选) | 可接 ESP32 GPIO 控制 | 使能/关闭功放:高电平=启用,低电平=静音 |
源代码
#include <Arduino.h>
#include <BluetoothA2DPSink.h>
#include <driver/i2s.h>
#define I2S_DATA_PIN 25
#define I2S_CLOCK_PIN 27
#define I2S_WS_PIN 26
BluetoothA2DPSink a2dp_sink;
bool is_connected = false; // 标志位,表示蓝牙是否连接
void setup() {
Serial.begin(115200);
Serial.println("ESP32 A2DP Receiver with MAX98357A Playback");
// I2S 配置
i2s_config_t i2s_config = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX),
.sample_rate = 44100, // 可尝试 48000 或 32000
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
.communication_format = I2S_COMM_FORMAT_I2S_MSB,
.intr_alloc_flags = 0,
.dma_buf_count = 32,
.dma_buf_len = 32,
};
i2s_pin_config_t pin_config = {
.bck_io_num = I2S_CLOCK_PIN,
.ws_io_num = I2S_WS_PIN,
.data_out_num = I2S_DATA_PIN,
.data_in_num = I2S_PIN_NO_CHANGE
};
// 初始化 I2S
esp_err_t err = i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
if (err != ESP_OK) {
Serial.printf("I2S driver install failed: %d\n", err);
while (true);
}
err = i2s_set_pin(I2S_NUM_0, &pin_config);
if (err != ESP_OK) {
Serial.printf("I2S set pin failed: %d\n", err);
while (true);
}
// 设置 I2S 时钟
err = i2s_set_clk(I2S_NUM_0, 44100, I2S_BITS_PER_SAMPLE_16BIT, I2S_CHANNEL_STEREO);
if (err != ESP_OK) {
Serial.printf("I2S set clock failed: %d\n", err);
}
// 配置蓝牙 A2DP 直接输出到 I2S,降低音量以减少噪声
a2dp_sink.set_stream_reader([](const uint8_t *data, uint32_t len) {
static uint32_t last_time = 0;
uint32_t now = millis();
Serial.printf("Received audio data: %d bytes, time since last: %d ms\n", len, now - last_time);
last_time = now;
// 软件降低音量(模拟 GAIN 控制)
int16_t *samples = (int16_t *)data;
for (uint32_t i = 0; i < len / 2; i++) {
samples[i] = samples[i] * 0.5; // 降低 50% 音量
}
if (is_connected) {
size_t bytes_written;
esp_err_t err = i2s_write(I2S_NUM_0, data, len, &bytes_written, portMAX_DELAY);
if (err != ESP_OK) {
Serial.printf("I2S write error: %d\n", err);
} else if (bytes_written != len) {
Serial.printf("I2S wrote %d bytes, expected %d\n", bytes_written, len);
}
}
}, false);
// 蓝牙连接状态回调
a2dp_sink.set_on_connection_state_changed([](esp_a2d_connection_state_t state, void*) {
Serial.printf("Connection state: %d\n", state);
if (state == ESP_A2D_CONNECTION_STATE_CONNECTED) {
Serial.println("Bluetooth connected!");
is_connected = true;
} else if (state == ESP_A2D_CONNECTION_STATE_DISCONNECTED) {
Serial.println("Bluetooth disconnected!");
is_connected = false;
// 清空I2S缓冲区
i2s_zero_dma_buffer(I2S_NUM_0);
}
});
// 启动蓝牙
a2dp_sink.start("ESP32 Audio Sink");
Serial.println("Connecting to Bluetooth...");
}
void loop() {
if (!is_connected) {
Serial.println("Bluetooth not connected, playing test tone...");
int16_t samples[64];
for (int i = 0; i < 64; i++) {
samples[i] = sin(2 * PI * 440 * i / 44100) * 1000; // 降低测试音音量
}
size_t bytes_written;
esp_err_t err = i2s_write(I2S_NUM_0, samples, sizeof(samples), &bytes_written, portMAX_DELAY);
if (err != ESP_OK) {
Serial.printf("I2S tone write error: %d\n", err);
} else {
Serial.printf("Wrote %d bytes for tone\n", bytes_written);
}
}
delay(200);
}
成品效果
用 esp32 蓝牙播放器
更多推荐



所有评论(0)