基于 ESP32-S3 + VB6824 的四博三模联网 AI 智能音箱方案设计
1. 项目背景
传统智能音箱通常以"Wi-Fi 联网 + 云端语音对话"为核心,但在实际产品化过程中,会遇到几个典型问题:
1. 只能在 Wi-Fi 环境下使用,移动场景受限;
2. 配网流程复杂,用户首次使用门槛高;
3. 高噪环境下唤醒不稳定;
4. 播放 TTS 时无法稳定打断;
5. 二次开发接口不统一;
6. 批量生产时缺少完整产测逻辑。
四博 AI 智能音箱方案基于 ESP32-S3 原生架构 ,结合 VB6824 语音前端、Wi-Fi / BLE / 4G 三模联网、远距离拾音、高噪唤醒、云端大模型、四博小助手小程序、MCP 工具调用和 OTA 升级,更适合作为 B 端客户批量集成的 AI 音箱底座。
整体目标可以概括为:
ESP32-S3 主控
+ VB6824 语音前端
+ Wi-Fi / BLE / 4G 三模联网
+ 云端大模型
+ 小程序配置
+ MCP 工具调用
+ OTA / 产测 / 二次开发接口
2. 系统总体架构
系统建议拆分为以下几个模块:
app_main
├── net_manager_task // Wi-Fi / 4G / BLE 配网管理
├── vb6824_task // 唤醒、打断、录音事件
├── ai_client_task // WebSocket / MQTT / HTTPS AI通信
├── audio_task // 录音、播放、音量、TTS
├── mcp_task // AI工具调用
├── ota_task // 固件和素材升级
├── config_task // NVS配置管理
└── factory_task // 工厂产测
系统框图:
┌──────────────────────────────────────┐
│ 四博 AI 智能音箱 │
├──────────────────────────────────────┤
│ ESP32-S3 主控 │
│ ├── Wi-Fi 联网 │
│ ├── BLE / BluFi 配网 │
│ ├── 4G 模组 AT / PPP 控制 │
│ ├── AI WebSocket / MQTT / HTTPS │
│ ├── OTA / NVS / 配置管理 │
│ ├── MCP 工具调用 │
│ └── 二次开发接口 │
│ │
│ VB6824 语音前端 │
│ ├── 远距离拾音 │
│ ├── 离线唤醒 │
│ ├── AEC 回声消除 │
│ ├── 高噪降噪 │
│ └── 实时打断 │
│ │
│ 网络侧 │
│ ├── Wi-Fi │
│ ├── BLE │
│ └── 4G │
└──────────────────────────────────────┘
3. 三模联网设计
三模联网并不是让 Wi-Fi、BLE、4G 同时承载 AI 数据,而是分工明确:
Wi-Fi:主联网通道,用于家庭、办公室、教室等固定场景;
BLE:近场配置通道,用于小程序配网、绑定、参数下发;
4G:移动联网通道,用于户外、车载、展会、无 Wi-Fi 场景。
3.1 网络状态定义
typedef enum {
NET_MODE_NONE = 0,
NET_MODE_WIFI,
NET_MODE_4G,
NET_MODE_BLE_CONFIG,
} net_mode_t;
typedef enum {
NET_STATE_IDLE = 0,
NET_STATE_CONNECTING,
NET_STATE_CONNECTED,
NET_STATE_FAIL,
NET_STATE_SWITCHING,
} net_state_t;
typedef struct {
net_mode_t mode;
net_state_t state;
int wifi_rssi;
int cellular_rssi;
bool ai_online;
} net_context_t;
static net_context_t g_net_ctx = {
.mode = NET_MODE_NONE,
.state = NET_STATE_IDLE,
};
3.2 网络管理任务
推荐策略:
优先连接 Wi-Fi;
Wi-Fi 不可用时尝试 4G;
Wi-Fi 和 4G 均不可用时进入 BLE 配网;
网络切换成功后自动重连 AI 服务。
static void net_manager_task(void *arg)
{
while (1) {
switch (g_net_ctx.mode) {
case NET_MODE_NONE:
ESP_LOGI("NET", "尝试连接 Wi-Fi");
if (wifi_connect_saved()) {
g_net_ctx.mode = NET_MODE_WIFI;
g_net_ctx.state = NET_STATE_CONNECTED;
ai_client_reconnect();
break;
}
ESP_LOGW("NET", "Wi-Fi 连接失败,尝试 4G");
if (cellular_connect()) {
g_net_ctx.mode = NET_MODE_4G;
g_net_ctx.state = NET_STATE_CONNECTED;
ai_client_reconnect();
break;
}
ESP_LOGW("NET", "Wi-Fi / 4G 均不可用,进入 BLE 配网");
g_net_ctx.mode = NET_MODE_BLE_CONFIG;
g_net_ctx.state = NET_STATE_CONNECTING;
blufi_start_config();
break;
case NET_MODE_WIFI:
if (!wifi_is_connected()) {
ESP_LOGW("NET", "Wi-Fi 断开,切换到 4G");
g_net_ctx.state = NET_STATE_SWITCHING;
if (cellular_connect()) {
g_net_ctx.mode = NET_MODE_4G;
g_net_ctx.state = NET_STATE_CONNECTED;
ai_client_reconnect();
} else {
g_net_ctx.mode = NET_MODE_BLE_CONFIG;
blufi_start_config();
}
}
break;
case NET_MODE_4G:
if (!cellular_is_ready()) {
ESP_LOGW("NET", "4G 不可用,尝试恢复 Wi-Fi");
g_net_ctx.state = NET_STATE_SWITCHING;
if (wifi_connect_saved()) {
g_net_ctx.mode = NET_MODE_WIFI;
g_net_ctx.state = NET_STATE_CONNECTED;
ai_client_reconnect();
} else {
g_net_ctx.mode = NET_MODE_BLE_CONFIG;
blufi_start_config();
}
}
break;
case NET_MODE_BLE_CONFIG:
// 等待小程序下发 Wi-Fi 配置
break;
default:
break;
}
vTaskDelay(pdMS_TO_TICKS(3000));
}
}
4. 4G 模组 AT 控制
如果 4G 模组采用 UART AT 方式接入,ESP32-S3 只需要完成 AT 指令收发、SIM 检查、信号检测、网络注册判断即可。
4.1 UART 初始化
#define MODEM_UART_NUM UART_NUM_2
#define MODEM_TX_GPIO 21
#define MODEM_RX_GPIO 20
#define MODEM_BAUD 115200
void modem_uart_init(void)
{
uart_config_t cfg = {
.baud_rate = MODEM_BAUD,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
};
ESP_ERROR_CHECK(uart_driver_install(MODEM_UART_NUM, 4096, 4096, 0, NULL, 0));
ESP_ERROR_CHECK(uart_param_config(MODEM_UART_NUM, &cfg));
ESP_ERROR_CHECK(uart_set_pin(MODEM_UART_NUM,
MODEM_TX_GPIO,
MODEM_RX_GPIO,
UART_PIN_NO_CHANGE,
UART_PIN_NO_CHANGE));
}
4.2 AT 指令发送函数
static esp_err_t modem_send_at(const char *cmd,
const char *expect,
int timeout_ms)
{
char rx[512] = {0};
uart_flush(MODEM_UART_NUM);
uart_write_bytes(MODEM_UART_NUM, cmd, strlen(cmd));
uart_write_bytes(MODEM_UART_NUM, "\r\n", 2);
int len = uart_read_bytes(MODEM_UART_NUM,
(uint8_t *)rx,
sizeof(rx) - 1,
pdMS_TO_TICKS(timeout_ms));
if (len > 0) {
rx[len] = 0;
ESP_LOGI("MODEM", "AT: %s => %s", cmd, rx);
if (strstr(rx, expect)) {
return ESP_OK;
}
}
return ESP_FAIL;
}
4.3 SIM、信号和注册检测
bool cellular_check_sim(void)
{
return modem_send_at("AT+CPIN?", "READY", 1000) == ESP_OK;
}
bool cellular_check_signal(void)
{
return modem_send_at("AT+CSQ", "OK", 1000) == ESP_OK;
}
bool cellular_check_register(void)
{
if (modem_send_at("AT+CREG?", "+CREG: 0,1", 1000) == ESP_OK) {
return true;
}
if (modem_send_at("AT+CREG?", "+CREG: 0,5", 1000) == ESP_OK) {
return true;
}
return false;
}
bool cellular_connect(void)
{
ESP_LOGI("MODEM", "初始化 4G 模组");
if (modem_send_at("AT", "OK", 1000) != ESP_OK) {
return false;
}
if (!cellular_check_sim()) {
ESP_LOGE("MODEM", "SIM 卡未就绪");
return false;
}
cellular_check_signal();
for (int i = 0; i < 10; i++) {
if (cellular_check_register()) {
ESP_LOGI("MODEM", "4G 网络注册成功");
return true;
}
vTaskDelay(pdMS_TO_TICKS(1000));
}
ESP_LOGE("MODEM", "4G 网络注册失败");
return false;
}
5. VB6824 语音前端接入
VB6824 主要负责:
1. 离线唤醒;
2. AEC 回声消除;
3. 高噪环境降噪;
4. 实时语音打断;
5. 语音事件上报;
6. 自定义唤醒词。
推荐事件协议:
0xA5 0x01 0x00 0x5A 唤醒成功
0xA5 0x02 0x00 0x5A 用户打断
0xA5 0x03 0x00 0x5A 开始录音
0xA5 0x04 0x00 0x5A 停止录音
5.1 VB6824 UART 初始化与解析
#define VB_UART_NUM UART_NUM_1
#define VB_UART_TX 17
#define VB_UART_RX 18
#define VB_UART_BAUD 115200
#define VB_HEAD 0xA5
#define VB_TAIL 0x5A
#define VB_CMD_WAKEUP 0x01
#define VB_CMD_INTERRUPT 0x02
#define VB_CMD_REC_START 0x03
#define VB_CMD_REC_STOP 0x04
static void vb6824_parse_frame(uint8_t *buf, int len)
{
if (len < 4) {
return;
}
if (buf[0] != VB_HEAD || buf[3] != VB_TAIL) {
return;
}
switch (buf[1]) {
case VB_CMD_WAKEUP:
ESP_LOGI("VB6824", "唤醒成功");
app_post_event(APP_EVT_WAKE_WORD, 0, 0, NULL);
break;
case VB_CMD_INTERRUPT:
ESP_LOGI("VB6824", "用户打断");
app_post_event(APP_EVT_VOICE_INTERRUPT, 0, 0, NULL);
break;
case VB_CMD_REC_START:
ESP_LOGI("VB6824", "开始录音");
app_post_event(APP_EVT_RECORD_START, 0, 0, NULL);
break;
case VB_CMD_REC_STOP:
ESP_LOGI("VB6824", "停止录音");
app_post_event(APP_EVT_RECORD_STOP, 0, 0, NULL);
break;
default:
ESP_LOGW("VB6824", "未知命令: 0x%02X", buf[1]);
break;
}
}
static void vb6824_uart_task(void *arg)
{
uint8_t rx[64];
while (1) {
int len = uart_read_bytes(VB_UART_NUM,
rx,
sizeof(rx),
pdMS_TO_TICKS(100));
if (len > 0) {
vb6824_parse_frame(rx, len);
}
}
}
6. AI 状态机设计
AI 音箱不建议把所有逻辑写在回调函数里,而是应该通过状态机管理。
typedef enum {
AI_STATE_BOOT = 0,
AI_STATE_IDLE,
AI_STATE_WAKEUP,
AI_STATE_LISTENING,
AI_STATE_THINKING,
AI_STATE_SPEAKING,
AI_STATE_BT_SPEAKER,
AI_STATE_4G_CONNECTING,
AI_STATE_WIFI_CONFIG,
AI_STATE_NET_ERROR,
AI_STATE_LOW_BATTERY,
AI_STATE_OTA,
} ai_state_t;
static ai_state_t g_ai_state = AI_STATE_BOOT;
状态切换:
void ai_set_state(ai_state_t state)
{
g_ai_state = state;
switch (state) {
case AI_STATE_BOOT:
audio_play_prompt("boot.wav");
break;
case AI_STATE_IDLE:
ESP_LOGI("AI", "待机状态");
break;
case AI_STATE_WAKEUP:
haptic_double();
audio_play_prompt("ding.wav");
break;
case AI_STATE_LISTENING:
audio_start_record();
break;
case AI_STATE_THINKING:
ESP_LOGI("AI", "AI 正在思考");
break;
case AI_STATE_SPEAKING:
ESP_LOGI("AI", "TTS 播放中");
break;
case AI_STATE_BT_SPEAKER:
audio_play_prompt("bt_mode.wav");
break;
case AI_STATE_4G_CONNECTING:
audio_play_prompt("cellular_connecting.wav");
break;
case AI_STATE_WIFI_CONFIG:
audio_play_prompt("config_mode.wav");
break;
case AI_STATE_NET_ERROR:
haptic_long();
audio_play_prompt("network_error.wav");
break;
case AI_STATE_LOW_BATTERY:
haptic_long();
audio_play_prompt("low_battery.wav");
break;
case AI_STATE_OTA:
audio_play_prompt("ota_start.wav");
break;
default:
break;
}
}
7. 云端 AI 消息解析
推荐云端返回结构化 JSON,而不是只返回自然语言文本。
{
"type": "tts",
"state": "start",
"emotion": "happy",
"text": "你好,我在。",
"session_id": "abc123"
}
设备侧解析:
static void ai_handle_json(const char *json)
{
cJSON *root = cJSON_Parse(json);
if (!root) {
return;
}
cJSON *type = cJSON_GetObjectItem(root, "type");
cJSON *state = cJSON_GetObjectItem(root, "state");
cJSON *emotion = cJSON_GetObjectItem(root, "emotion");
if (cJSON_IsString(type)) {
if (strcmp(type->valuestring, "stt") == 0) {
ai_set_state(AI_STATE_THINKING);
}
if (strcmp(type->valuestring, "llm") == 0) {
ai_set_state(AI_STATE_THINKING);
}
if (strcmp(type->valuestring, "tts") == 0) {
if (state && cJSON_IsString(state)) {
if (strcmp(state->valuestring, "start") == 0) {
ai_set_state(AI_STATE_SPEAKING);
} else if (strcmp(state->valuestring, "stop") == 0) {
ai_set_state(AI_STATE_IDLE);
}
}
}
if (strcmp(type->valuestring, "error") == 0) {
ai_set_state(AI_STATE_NET_ERROR);
}
}
if (cJSON_IsString(emotion)) {
ESP_LOGI("AI", "情绪字段: %s", emotion->valuestring);
}
cJSON_Delete(root);
}
8. MCP 工具调用
MCP 的价值在于让 AI 能直接控制设备能力,比如切换联网模式、设置音量、进入配网模式、停止播放等。
8.1 联网模式工具
{
"name": "self.network.set_mode",
"description": "切换设备联网模式",
"parameters": {
"type": "object",
"properties": {
"mode": {
"type": "string",
"enum": ["wifi", "4g", "auto"]
}
},
"required": ["mode"]
}
}
设备侧实现:
void mcp_set_network_mode(const char *mode)
{
if (strcmp(mode, "wifi") == 0) {
g_net_ctx.mode = NET_MODE_WIFI;
wifi_connect_saved();
ai_set_state(AI_STATE_IDLE);
} else if (strcmp(mode, "4g") == 0) {
g_net_ctx.mode = NET_MODE_4G;
ai_set_state(AI_STATE_4G_CONNECTING);
cellular_connect();
} else {
g_net_ctx.mode = NET_MODE_NONE;
net_manager_start();
}
}
8.2 音量工具
{
"name": "self.audio.set_volume",
"description": "设置音箱音量",
"parameters": {
"type": "object",
"properties": {
"volume": {
"type": "integer",
"minimum": 0,
"maximum": 100
}
},
"required": ["volume"]
}
}
void mcp_set_volume(int volume)
{
if (volume < 0) volume = 0;
if (volume > 100) volume = 100;
audio_set_volume(volume);
config_set_int("volume", volume);
haptic_short();
}
8.3 MCP 工具分发
void mcp_dispatch_tool(const char *tool_name, cJSON *args)
{
if (strcmp(tool_name, "self.network.set_mode") == 0) {
cJSON *mode = cJSON_GetObjectItem(args, "mode");
if (cJSON_IsString(mode)) {
mcp_set_network_mode(mode->valuestring);
}
return;
}
if (strcmp(tool_name, "self.audio.set_volume") == 0) {
cJSON *volume = cJSON_GetObjectItem(args, "volume");
if (cJSON_IsNumber(volume)) {
mcp_set_volume(volume->valueint);
}
return;
}
if (strcmp(tool_name, "self.device.enter_config") == 0) {
enter_config_mode();
return;
}
if (strcmp(tool_name, "self.audio.stop") == 0) {
audio_stop_tts();
ai_set_state(AI_STATE_IDLE);
return;
}
}
9. 小程序配置与 NVS 保存
四博小助手小程序可以作为设备配置入口,用于配网、4G 模式切换、声音克隆、知识库、MCP 工具和 OTA 管理。
typedef struct {
char device_id[32];
char user_id[32];
char wifi_ssid[32];
char ai_agent_id[64];
char voice_id[64];
char kb_id[64];
int volume;
int wake_sensitivity;
int network_mode; // 0:auto, 1:wifi, 2:4g
int noise_level;
bool child_mode;
bool quiet_mode;
bool bt_speaker_enabled;
} device_config_t;
static device_config_t g_device_config;
保存到 NVS:
#define NVS_NAMESPACE "dev_cfg"
#define NVS_KEY "config"
esp_err_t device_config_save(void)
{
nvs_handle_t nvs;
esp_err_t ret = nvs_open(NVS_NAMESPACE, NVS_READWRITE, &nvs);
if (ret != ESP_OK) {
return ret;
}
ret = nvs_set_blob(nvs,
NVS_KEY,
&g_device_config,
sizeof(g_device_config));
if (ret == ESP_OK) {
ret = nvs_commit(nvs);
}
nvs_close(nvs);
return ret;
}
10. OTA 和分区设计
推荐分区:
# Name, Type, SubType, Offset, Size
nvs, data, nvs, 0x9000, 0x6000
otadata, data, ota, 0xf000, 0x2000
phy_init, data, phy, 0x11000, 0x1000
factory, app, factory, 0x20000, 2M
ota_0, app, ota_0, 0x220000, 2M
ota_1, app, ota_1, 0x420000, 2M
assets, data, spiffs, 0x620000, 4M
storage, data, fat, 0xA20000, 4M
OTA 清单:
{
"device": "sibo_ai_speaker_s3",
"hw_version": "V1.0",
"fw_version": "1.0.8",
"asset_version": "2026.04.01",
"firmware": {
"url": "https://server.com/fw/sibo_ai_speaker_1.0.8.bin",
"sha256": "xxxx"
},
"assets": {
"url": "https://server.com/assets/prompt_20260401.bin",
"sha256": "yyyy"
},
"force": false
}
11. 产测设计
量产建议准备 factory 固件,覆盖:
Wi-Fi:RSSI、连接、重连
BLE:广播、配网连接
4G:SIM、CSQ、CREG、联网
麦克风:录音电平、底噪
VB6824:唤醒、打断、降噪
喇叭:提示音、最大音量
功放:失真、噪声
按键:短按、长按、双击
Flash:NVS、OTA、分区
电源:电池电压、充电状态
OTA:升级、回滚
产测代码示例:
void factory_reply(const char *item, const char *result)
{
printf("{\"item\":\"%s\",\"result\":\"%s\"}\n", item, result);
}
void factory_test_wifi(void)
{
int rssi = wifi_get_rssi();
if (rssi > -70) {
printf("{\"item\":\"wifi\",\"result\":\"ok\",\"rssi\":%d}\n", rssi);
} else {
printf("{\"item\":\"wifi\",\"result\":\"fail\",\"rssi\":%d}\n", rssi);
}
}
void factory_test_4g(void)
{
if (!cellular_check_sim()) {
factory_reply("4g", "sim_fail");
return;
}
if (!cellular_check_register()) {
factory_reply("4g", "register_fail");
return;
}
factory_reply("4g", "ok");
}
void factory_test_speaker(void)
{
audio_play_prompt("factory_test.wav");
factory_reply("speaker", "ok");
}
12. 二次开发接口
为了方便 B 端客户集成,建议开放 UART、HTTP 和 WebSocket 接口。
UART 控制协议
55 AA 03 01 01 AA 55 进入配网
55 AA 03 02 01 AA 55 切换 Wi-Fi
55 AA 03 03 01 AA 55 切换 4G
55 AA 03 04 32 AA 55 设置音量 50
55 AA 03 05 01 AA 55 开启蓝牙音箱
HTTP 本地调试接口
POST /api/device/config
{
"volume": 70,
"network_mode": "auto",
"wake_sensitivity": 5
}
WebSocket 事件上报
{
"event": "network_changed",
"mode": "4g",
"rssi": -65,
"timestamp": 123456789
}
13. 总结
四博 ESP32-S3 三模联网 AI 智能音箱方案,本质上是一套适合量产和二次开发的 AI 硬件底座。
它的技术特点是:
ESP32-S3 原生架构,开发生态成熟;
Wi-Fi / BLE / 4G 三模联网,适合固定和移动场景;
VB6824 负责远场唤醒、降噪、AEC 和打断;
支持四博小助手小程序,方便配网、配置和运营;
支持 MCP 工具调用,让 AI 可以直接控制硬件;
支持 OTA、产测和开放接口,适合 B 端批量集成。
一句话总结:
四博 AI 智能音箱 =
ESP32-S3 主控
+ VB6824 远场语音前端
+ Wi-Fi / BLE / 4G 三模联网
+ 云端大模型
+ 四博小助手
+ 声音克隆 / 知识库 / MCP
+ OTA / 产测 / 二次开发接口
这套方案不仅可以做家用 AI 音箱,也可以做儿童陪伴机、智能家居入口、移动 AI 终端、教育问答设备、品牌客服终端和 B 端行业定制设备。