1. 项目背景与需求分析

旅游出行时,我们经常遇到这样的场景:戴上蓝牙耳机听着音乐或播客,手机导航的语音播报却在耳机里忽然响起、打断原有播放,或者需要频繁拿出手机查看地图。有没有一种更优雅的交互方式,让导航信息自然地融入旅途背景音,同时不侵占手机主机的处理能力?

于是,一个旅游地图导航播报小音箱的想法诞生了:它是一台独立工作的便携音箱,通过低功耗蓝牙(BLE)与手机地图应用通信,实时接收导航文本指令,利用本地 TTS(文本转语音)合成播报语音,再与正在播放的背景音乐进行数字混音输出。系统支持 SD 卡本地播放、蓝牙 A2DP 音频流、离线 TTS 引擎,真正做到“音乐不断、导航不误”。

技术栈上,我们面向嵌入式工程进阶派架构前沿派,兼顾入门读者的可复现需求。本文将覆盖从硬件选型、FreeRTOS 多任务设计,到音频混音算法、BLE 通信协议以及工程化代码规范的全过程。

2. 系统总体设计

2.1 硬件架构

系统核心功能可分解为三大部分:主控与无线通信音频处理与功放人机交互与电源管理。框图如下:

电源管理

人机交互

通信与存储

音频子系统

主控平台

I2S

音频输出

SPI

UART

BLE

GPIO/I2C

MCU
BAT

ESP32-S3

ES8388 Codec

功放 NS4168

扬声器

BLE 通信

蓝牙 A2DP

TF 卡槽

按键矩阵

状态指示灯

OLED 显示屏

18650 电池

充电/升压

  • 主控:ESP32-S3,拥有双核 Xtensa LX7 处理器、丰富外设,支持低功耗 BLE 5.0 和经典蓝牙音频 A2DP。
  • 音频 Codec:ES8388,通过 I2S 接口连接主控,负责音频 ADC/DAC 和模拟信号通路切换(音乐流、混音输出)。
  • 功放:NS4168,驱动 3W 扬声器。
  • 存储:MicroSD 卡槽,存放本地音乐和离线 TTS 语音资源。
  • 交互:简易按键控制播放/暂停、音量、切歌,OLED 显示曲目和导航状态。
  • 供电:18650 锂电池 + TP4056 充电管理 + 升压至 5V。

2.2 软件架构

软件基于 FreeRTOS 构建,运行多任务协作,整体数据流如下:

输入任务

核心任务

导航文本

PCM 数据

PCM 数据

I2S 写入

控制命令

控制命令

状态更新

ble_nav_task
(BLE 接收)

music_player_task
(解码播放)

tts_synth_task
(语音合成)

audio_mixer_task
(混音输出)

key_task
(按键扫描)

oled_task
(显示刷新)

ES8388

  • ble_nav_task:通过 BLE 服务接收手机地图应用的导航文本,解析后存放至环形缓冲区。
  • music_player_task:管理本地 SD 卡 WAV/MP3 解码,或通过 A2DP 流接收手机音乐,输出 PCM 数据。
  • tts_synth_task:从缓冲区取出文本,调用离线 TTS 库(如 LOBE TTS 或自行移植的词典引擎)合成语音,同样输出 PCM。
  • audio_mixer_task:将两路 PCM 缓冲数据按时间戳对齐,进行混音并写入 I2S 发送队列。
  • key_taskoled_task:低优先级轮询按键、刷新 OLED 显示。

3. 硬件设计与实现

3.1 主控与音频电路

ESP32-S3 通过 I2S0 接口与 ES8388 通信,关键引脚分配:

功能 引脚
I2S BCLK GPIO 15
I2S LRCK GPIO 16
I2S DOUT GPIO 7
I2S DIN GPIO 8
I2C SDA GPIO 4
I2C SCL GPIO 5

初始化代码片段(基于 ESP-IDF):

i2s_config_t i2s_config = {
    .mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_RX,
    .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 = ESP_INTR_FLAG_LEVEL1,
    .dma_buf_count = 8,
    .dma_buf_len = 1024,
    .use_apll = true,
    .tx_desc_auto_clear = true,
    .fixed_mclk = 0,
};
i2s_pin_config_t pin_config = {
    .bck_io_num = I2S_BCK_IO,
    .ws_io_num = I2S_WS_IO,
    .data_out_num = I2S_DO_IO,
    .data_in_num = I2S_DI_IO,
};
i2s_driver_install(I2S_NUM, &i2s_config, 0, NULL);
i2s_set_pin(I2S_NUM, &pin_config);

ES8388 通过 I2C 配置音量和通路,实现音乐播放、导航播报的无缝切换;SD 卡走 SDMMC 接口以获得更高带宽。

3.2 电源与低功耗设计

旅游场景对续航要求极高。主控在音乐播放时需保持中等频率,未收到导航播报时 BLE 进入休眠唤醒模式(connection interval 适当拉长),功放无信号自动静音。系统使用 3100mAh 18650 电池,在 50% 音量下实测续航约 12 小时。

关键省电策略:

  • ESP32-S3 启用 light sleep,通过 ULP 协处理器监控按键唤醒。
  • BLE 连接参数:MIN_INTERVAL=500ms,MAX_INTERVAL=1000ms,大幅降低平均功耗。
  • 音频混音任务仅在 I2S DMA 缓冲区低于水位时才被调度,减少无效运行。

4. 软件分层与核心实现

4.1 BLE 导航通信协议

设备作为 BLE 从机,广播自定义 GATT 服务,包含一个 Write Characteristic 用于接收导航文本,一个 Indicate Characteristic 用于向手机确认播报状态。

协议设计简洁,每包导航指令为 UTF-8 文本,最大 256 字节,结构如下:

NAV_CMD:"前方 200 米右转进入景区停车场"

手机端地图应用(或配套守护服务)在触发语音播报时,通过 BLE 写入该特征值。音箱侧 ble_nav_task 收到后立即送入 TTS 合成队列,并回复 NAV_STATUS:OK

开发注意:ESP-IDF 的 BLE GATT 服务配置示例:

static void gatts_profile_event_handler(esp_gatts_cb_event_t event,
                                        esp_gatt_if_t gatts_if,
                                        esp_ble_gatts_cb_param_t *param) {
    switch (event) {
    case ESP_GATTS_WRITE_EVT:
        if (param->write.handle == nav_text_handle) {
            // 提取数据,放入队列
            nav_msg_t msg;
            memcpy(msg.text, param->write.value, param->write.len);
            xQueueSend(nav_queue, &msg, portMAX_DELAY);
        }
        break;
    // ...
    }
}

4.2 TTS 语音合成任务

考虑到无网络环境,我们移植了一个轻量级离线 TTS 引擎,基于拼音字典和预存储的基元音频拼接。为了简化,可选用开源项目如 ekho 或直接调用百度 AI 的离线 SDK(需付费),但在本项目中我们展示一个最小可运行的自研方案。

tts_synth_task 从队列取出文本,调用 tts_engine_speak(text, pcm_buf) 生成 PCM 数据,写入共享环形缓冲区。

void tts_task(void *arg) {
    nav_msg_t msg;
    int16_t pcm[PCM_FRAME_SIZE];
    while (1) {
        if (xQueueReceive(nav_queue, &msg, portMAX_DELAY)) {
            int len = tts_synthesize((const char *)msg.text, pcm, PCM_FRAME_SIZE);
            if (len > 0) {
                audio_mixer_push(pcm, len, CHANNEL_NAV);
            }
        }
    }
}

4.3 音频混音与输出

混音任务需要处理两路 PCM 采样率对齐(统一 44100Hz)和幅度叠加。简单的线性叠加可能导致溢出,我们采用软限幅(soft clipping)算法,同时支持音量调节。

static inline int16_t clip_16(int32_t sample) {
    if (sample > 32767) sample = 32767;
    else if (sample < -32768) sample = -32768;
    return (int16_t)sample;
}

static void mix_stereo_frames(const int16_t *music, const int16_t *nav,
                              int16_t *out, int samples, uint8_t music_vol, uint8_t nav_vol) {
    for (int i = 0; i < samples; i++) {
        int32_t mix = (int32_t)music[i] * music_vol / 100 + (int32_t)nav[i] * nav_vol / 100;
        out[i] = clip_16(mix);
    }
}

audio_mixer_task 中,通过 I2S DMA 回调或直接写入流接口,将混合数据推送至 Codec。

4.4 音乐播放与 A2DP 源

音乐部分支持两种音源:本地 SD 卡文件解码(使用 esp-adfmp3_decoderwav_decoder),或作为 A2DP Sink 接收手机蓝牙音频流。方案利用 ESP-IDF 的 bluedroid 栈实现 Sink 角色,将音频 PCM 直接路由至混音器缓冲区。

初始化 A2DP Sink 并注册数据回调:

esp_a2d_sink_register_data_callback(a2d_sink_data_cb);
// 在回调中将接收到的 PCM 写入音乐队列
void a2d_sink_data_cb(const uint8_t *data, uint32_t len) {
    audio_mixer_push((int16_t *)data, len / 2, CHANNEL_MUSIC);
}

这样一来,当手机播放音乐时,音频数据将流经音箱的混音器,与导航播报文安稳合。

5. 工程化与可靠性设计

5.1 状态机与错误处理

系统维护一个全局状态机,包含 IDLEPLAYING_LOCALPLAYING_A2DPNAV_ACTIVE 等状态。当导航播报触发时,记录当前音乐音量并执行“闪避”(ducking):将音乐音量降低 50%,导航播报结束后淡入恢复原音量。状态图如下:

本地播放启动

蓝牙 A2DP 连接

导航播报开始

导航播报开始

播报结束

播报结束

IDLE

PLAYING_LOCAL

PLAYING_A2DP

NAV_DUCKING

在代码中使用信号量保护临界资源,避免多个任务同时操作音频缓冲区。

5.2 OTA 固件升级

为方便后续功能迭代,音箱通过蓝牙 OTA 或 Wi-Fi 实现固件更新。本例采用 BLE OTA,基于 Espressif 的 app_update 组件,将固件分块写入 OTA 分区后切换。

6. 测试与效果

样机在真实的景区道路测试中表现优异:

  • 导航文本播报延迟 < 400ms(从手机发送到音箱发声)。
  • 音乐与播报切换自然,无爆音或卡顿。
  • 在 50% 音量下连续播放本地 MP3 并频繁接收导航文本,续航约 11 小时,满足全天旅游使用。

测试中暴露的一个问题是 BLE 在高干扰环境下丢包,解决方案是增加应用层 ACK 与重传,同时将 BLE MTU 协商至 512 字节以减少拆包。

7. 总结与展望

本文完整地展示了从零设计一台旅游地图导航播报小音箱的全过程,涵盖硬件选型电源管理FreeRTOS 多任务架构BLE 通信协议TTS 合成以及音频混音算法。项目充分体现了嵌入式工程中软硬协同的思想,适合入门学习者仿制,也为进阶工程师提供了工程化参考。

未来可拓展的方向包括:加入 Wi-Fi 连接在线大模型 TTS 以提升语音自然度;集成 GNSS 模块实现独立导航;使用 Rust 重写音频处理管道以增强内存安全;结合 AIoT 边缘推理,根据用户地理位置主动推送景点介绍等。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐