四博 AI 智能音箱 4G S3 版本技术方案

news2026/4/27 12:56:31
下面这版更偏技术方案 原型开发说明 可落地代码骨架适合放到方案书、技术推广文档、客户交流材料中。代码以ESP-IDF / ESP32-S3风格写重点突出四博方案的工程结构、联网切换、远场拾音、实时打断、MCP 扩展、屏幕异显和客户系统接入。四博 AI 智能音箱 4G S3 版本技术方案1. 方案概述四博 AI 智能音箱 4G S3 版本是基于ESP32-S3 主控平台 远场语音前端 Wi-Fi / 蓝牙 / 4G 三模联网 屏幕显示 AI 大模型云端服务 MCP 扩展协议构建的一套 AI 语音硬件方案。该方案面向 AI 音箱、AI 学习机、AI 故事机、AI 桌宠、AI 玩具、智能中控、语音控制终端等产品可实现1. 5 米范围远距离拾音、唤醒、打断和对话 2. 空气炸锅、风扇、厨房电器等高噪音环境下稳定响应 3. 支持唤醒词打断、实时打断、AI 播报中插话 4. 支持修改唤醒词适合品牌定制 5. 支持 Wi-Fi、蓝牙、4G 三种联网方式 6. 支持一个屏幕、两个屏幕、双屏异显 7. 支持四博小助手配网、知识库、声音克隆、自建大模型 8. 支持 MCP / UART 接入客户自己的控制系统 9. 基于 ESP32-S3方便客户进行二次开发《四博智联 AI 开发宝典》中四博 AI-Speaker 开发板已经明确支持“四博小助手”小程序、克隆、知识库、自建大模型和 MCP同时文档中也给出了 S3 AI-Speaker 的 ESP-IDF 工程配置、编译、烧录和 BluFi 配网流程可作为本方案的软件基础。2. 系统总体架构┌───────────────────────────────────────────────┐ │ 客户业务系统 / AI 云服务 │ │ │ │ ASR 语音识别 │ │ LLM 大模型 │ │ TTS 语音合成 │ │ 知识库 / 题库 / 内容平台 │ │ 设备管理 / OTA / 会员系统 │ └──────────────────────▲────────────────────────┘ │ │ WebSocket / HTTPS / MQTT │ ┌──────────────────────┴────────────────────────┐ │ 四博 AI 智能音箱 4G S3 设备端 │ │ │ │ ┌─────────────────────────────────────────┐ │ │ │ ESP32-S3 应用主控层 │ │ │ │ - FreeRTOS 任务调度 │ │ │ │ - 音频采集 / 播放控制 │ │ │ │ - 屏幕 UI / LVGL │ │ │ │ - 网络状态管理 │ │ │ │ - WebSocket AI 会话 │ │ │ │ - OTA 升级 │ │ │ │ - MCP / UART 扩展 │ │ │ └─────────────────────────────────────────┘ │ │ │ │ ┌─────────────┐ ┌─────────────┐ ┌──────────┐ │ │ │ Wi-Fi 联网 │ │ 蓝牙联网/配网 │ │ 4G 联网 │ │ │ └─────────────┘ └─────────────┘ └──────────┘ │ │ │ │ ┌─────────────┐ ┌─────────────┐ ┌──────────┐ │ │ │ 远场麦克风 │ │ 语音唤醒/打断 │ │ I2S 功放 │ │ │ └─────────────┘ └─────────────┘ └──────────┘ │ │ │ │ ┌─────────────┐ ┌─────────────┐ ┌──────────┐ │ │ │ 主屏显示 │ │ 副屏表情显示 │ │ 外设控制 │ │ │ └─────────────┘ └─────────────┘ └──────────┘ │ └───────────────────────────────────────────────┘3. 硬件方案定义3.1 推荐硬件组成主控平台 - ESP32-S3 / 四博 S3R8 系列方案 联网方式 - Wi-Fi - 蓝牙上网 / 蓝牙配网 - 4G 模块 语音输入 - 远场麦克风 - 可选双麦 / 阵列麦克风 - 离线语音前端 / VB6824 类语音芯片 语音输出 - I2S Codec - 功放 - 4Ω 3W 喇叭 显示部分 - 单屏 LCD - 双屏 LCD - 支持双屏异显 扩展接口 - UART - I2C - SPI - GPIO - USB - 电池接口 - 充电管理《开发宝典》中 AI-C5 方案已包含 4G 模组、喇叭、咪头、电池和屏幕等硬件配置并支持 Wi-Fi 与 4G 模式切换这部分可以作为 4G 版本智能音箱的硬件设计参考。4. 软件任务架构设备端建议按 FreeRTOS 多任务方式组织app_main ├── board_init_task ├── network_manager_task ├── audio_capture_task ├── voice_wakeup_task ├── ai_session_task ├── tts_player_task ├── display_task ├── mcp_uart_task ├── ota_task └── key_event_task4.1 FreeRTOS 任务划分typedef enum { SYS_EVT_NONE 0, SYS_EVT_NET_CONNECTED, SYS_EVT_NET_DISCONNECTED, SYS_EVT_WAKEUP_DETECTED, SYS_EVT_REALTIME_INTERRUPT, SYS_EVT_ASR_START, SYS_EVT_ASR_END, SYS_EVT_TTS_START, SYS_EVT_TTS_END, SYS_EVT_MCP_FRAME, SYS_EVT_OTA_START, SYS_EVT_OTA_DONE, } sys_event_t; typedef enum { AI_STATE_BOOTING 0, AI_STATE_NET_CONFIG, AI_STATE_CONNECTING, AI_STATE_IDLE, AI_STATE_LISTENING, AI_STATE_THINKING, AI_STATE_SPEAKING, AI_STATE_INTERRUPTED, AI_STATE_UPGRADING, } ai_state_t; static QueueHandle_t g_sys_evt_queue; static ai_state_t g_ai_state AI_STATE_BOOTING; static void post_sys_event(sys_event_t evt) { if (g_sys_evt_queue) { xQueueSend(g_sys_evt_queue, evt, 0); } }5. 主程序代码骨架#include freertos/FreeRTOS.h #include freertos/task.h #include freertos/queue.h #include esp_log.h #include nvs_flash.h static const char *TAG SIBO_AI_SPEAKER; void board_power_init(void); void board_gpio_init(void); void display_init(void); void audio_codec_init(void); void microphone_init(void); void speaker_init(void); void voice_frontend_init(void); void network_manager_init(void); void ai_protocol_init(void); void mcp_uart_init(void); void ota_service_init(void); void network_manager_task(void *arg); void ai_session_task(void *arg); void audio_capture_task(void *arg); void tts_player_task(void *arg); void display_task(void *arg); void mcp_uart_task(void *arg); void key_event_task(void *arg); void app_main(void) { esp_err_t ret nvs_flash_init(); if (ret ! ESP_OK) { ESP_LOGW(TAG, NVS 初始化失败尝试擦除后重新初始化); nvs_flash_erase(); ESP_ERROR_CHECK(nvs_flash_init()); } ESP_LOGI(TAG, 四博 AI 智能音箱 4G S3 版本启动); g_sys_evt_queue xQueueCreate(16, sizeof(sys_event_t)); board_power_init(); board_gpio_init(); display_init(); audio_codec_init(); microphone_init(); speaker_init(); voice_frontend_init(); network_manager_init(); ai_protocol_init(); mcp_uart_init(); ota_service_init(); xTaskCreate(network_manager_task, network_manager, 4096, NULL, 6, NULL); xTaskCreate(audio_capture_task, audio_capture, 8192, NULL, 7, NULL); xTaskCreate(ai_session_task, ai_session, 8192, NULL, 6, NULL); xTaskCreate(tts_player_task, tts_player, 4096, NULL, 5, NULL); xTaskCreate(display_task, display_task, 4096, NULL, 4, NULL); xTaskCreate(mcp_uart_task, mcp_uart, 4096, NULL, 5, NULL); xTaskCreate(key_event_task, key_event, 2048, NULL, 4, NULL); ESP_LOGI(TAG, 系统任务创建完成); }6. 三模联网设计6.1 联网状态机开机 ↓ 读取上一次联网模式 ↓ 优先尝试 Wi-Fi ↓ 失败 尝试蓝牙上网 / 蓝牙配网 ↓ 失败 尝试 4G 模块 ↓ 成功 建立 WebSocket AI 会话 ↓ 进入 AI 待机状态6.2 网络模式定义typedef enum { NET_MODE_WIFI 0, NET_MODE_BT, NET_MODE_4G, } net_mode_t; typedef enum { NET_STATUS_IDLE 0, NET_STATUS_CONNECTING, NET_STATUS_CONNECTED, NET_STATUS_FAILED, } net_status_t; typedef struct { net_mode_t mode; net_status_t status; int retry; bool ip_ready; bool ai_connected; } net_ctx_t; static net_ctx_t g_net_ctx { .mode NET_MODE_WIFI, .status NET_STATUS_IDLE, .retry 0, .ip_ready false, .ai_connected false, };6.3 网络切换逻辑static void net_switch_next_mode(void) { if (g_net_ctx.mode NET_MODE_WIFI) { g_net_ctx.mode NET_MODE_BT; ESP_LOGI(NET, 切换到蓝牙上网模式); } else if (g_net_ctx.mode NET_MODE_BT) { g_net_ctx.mode NET_MODE_4G; ESP_LOGI(NET, 切换到 4G 上网模式); } else { g_net_ctx.mode NET_MODE_WIFI; ESP_LOGI(NET, 切换到 Wi-Fi 上网模式); } g_net_ctx.status NET_STATUS_IDLE; g_net_ctx.retry 0; g_net_ctx.ip_ready false; g_net_ctx.ai_connected false; }6.4 网络管理任务static bool wifi_start_connect(void); static bool bt_network_start(void); static bool modem_4g_start(void); static bool ai_ws_connect(void); static bool network_is_ip_ready(void); void network_manager_task(void *arg) { while (1) { switch (g_net_ctx.status) { case NET_STATUS_IDLE: g_net_ctx.status NET_STATUS_CONNECTING; if (g_net_ctx.mode NET_MODE_WIFI) { ESP_LOGI(NET, 开始 Wi-Fi 联网); wifi_start_connect(); } else if (g_net_ctx.mode NET_MODE_BT) { ESP_LOGI(NET, 开始蓝牙上网); bt_network_start(); } else { ESP_LOGI(NET, 开始 4G 联网); modem_4g_start(); } break; case NET_STATUS_CONNECTING: if (network_is_ip_ready()) { ESP_LOGI(NET, 网络已获取 IP); g_net_ctx.status NET_STATUS_CONNECTED; g_net_ctx.ip_ready true; post_sys_event(SYS_EVT_NET_CONNECTED); } else { g_net_ctx.retry; if (g_net_ctx.retry 15) { ESP_LOGW(NET, 联网超时); g_net_ctx.status NET_STATUS_FAILED; } } break; case NET_STATUS_CONNECTED: if (!g_net_ctx.ai_connected) { ESP_LOGI(NET, 开始连接 AI WebSocket); if (ai_ws_connect()) { g_net_ctx.ai_connected true; ESP_LOGI(NET, AI 服务连接成功); } else { ESP_LOGW(NET, AI 服务连接失败); g_net_ctx.status NET_STATUS_FAILED; } } break; case NET_STATUS_FAILED: ESP_LOGW(NET, 当前网络模式失败准备切换); post_sys_event(SYS_EVT_NET_DISCONNECTED); net_switch_next_mode(); break; } vTaskDelay(pdMS_TO_TICKS(1000)); } }7. 4G 模块 AT 指令控制7.1 UART 初始化#include driver/uart.h #define MODEM_UART_PORT UART_NUM_1 #define MODEM_UART_TX_PIN 17 #define MODEM_UART_RX_PIN 18 #define MODEM_UART_BAUD 115200 #define MODEM_BUF_SIZE 1024 static void modem_uart_init(void) { uart_config_t uart_config { .baud_rate MODEM_UART_BAUD, .data_bits UART_DATA_8_BITS, .parity UART_PARITY_DISABLE, .stop_bits UART_STOP_BITS_1, .flow_ctrl UART_HW_FLOWCTRL_DISABLE, }; uart_driver_install(MODEM_UART_PORT, MODEM_BUF_SIZE * 2, 0, 0, NULL, 0); uart_param_config(MODEM_UART_PORT, uart_config); uart_set_pin(MODEM_UART_PORT, MODEM_UART_TX_PIN, MODEM_UART_RX_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); ESP_LOGI(4G, 4G UART 初始化完成); }7.2 AT 指令发送与等待static bool modem_send_cmd_wait(const char *cmd, const char *expect, int timeout_ms) { uint8_t rxbuf[MODEM_BUF_SIZE] {0}; uart_flush(MODEM_UART_PORT); uart_write_bytes(MODEM_UART_PORT, cmd, strlen(cmd)); int len uart_read_bytes( MODEM_UART_PORT, rxbuf, sizeof(rxbuf) - 1, pdMS_TO_TICKS(timeout_ms) ); if (len 0) { ESP_LOGW(4G, AT 无响应: %s, cmd); return false; } rxbuf[len] 0; ESP_LOGI(4G, AT 返回: %s, (char *)rxbuf); if (strstr((char *)rxbuf, expect)) { return true; } return false; }7.3 4G 模块就绪检测static bool modem_4g_check_ready(void) { if (!modem_send_cmd_wait(AT\r\n, OK, 1000)) { ESP_LOGE(4G, 4G 模块无响应); return false; } modem_send_cmd_wait(ATE0\r\n, OK, 1000); if (!modem_send_cmd_wait(ATCPIN?\r\n, READY, 3000)) { ESP_LOGE(4G, SIM 卡未就绪); return false; } modem_send_cmd_wait(ATCSQ\r\n, OK, 1000); if (!modem_send_cmd_wait(ATCREG?\r\n, OK, 1000)) { ESP_LOGW(4G, 查询注册状态失败); } if (!modem_send_cmd_wait(ATCGATT?\r\n, CGATT: 1, 3000)) { ESP_LOGE(4G, 4G 网络未附着); return false; } ESP_LOGI(4G, 4G 网络已就绪); return true; }7.4 4G 联网入口static bool modem_4g_start(void) { modem_uart_init(); if (!modem_4g_check_ready()) { g_net_ctx.status NET_STATUS_FAILED; return false; } /* * 实际项目中这里有两种实现 * 1. 使用 4G 模块内部 TCP/WebSocket/HTTP AT 指令 * 2. 使用 PPP/ECM把 4G 模块作为 ESP-IDF 网络接口 * * 推荐量产方案 * 如果项目已有 WebSocket/HTTP 代码优先做 PPP/ECM * 这样上层 AI 会话层不用区分 Wi-Fi 还是 4G。 */ g_net_ctx.status NET_STATUS_CONNECTED; g_net_ctx.ip_ready true; return true; }8. 语音前端与实时打断8.1 AI 状态机static void ai_set_state(ai_state_t state) { g_ai_state state; switch (state) { case AI_STATE_BOOTING: ESP_LOGI(AI, 状态启动中); display_show_status(启动中); break; case AI_STATE_NET_CONFIG: ESP_LOGI(AI, 状态配网中); display_show_status(请使用小程序配网); break; case AI_STATE_CONNECTING: ESP_LOGI(AI, 状态联网中); display_show_status(联网中); break; case AI_STATE_IDLE: ESP_LOGI(AI, 状态空闲); display_show_status(你好小智); display_show_expression(idle); break; case AI_STATE_LISTENING: ESP_LOGI(AI, 状态聆听中); display_show_status(正在聆听); display_show_expression(listening); break; case AI_STATE_THINKING: ESP_LOGI(AI, 状态思考中); display_show_status(正在思考); display_show_expression(thinking); break; case AI_STATE_SPEAKING: ESP_LOGI(AI, 状态说话中); display_show_status(正在回答); display_show_expression(speaking); break; case AI_STATE_INTERRUPTED: ESP_LOGI(AI, 状态已打断); display_show_status(已打断); display_show_expression(interrupt); break; case AI_STATE_UPGRADING: ESP_LOGI(AI, 状态升级中); display_show_status(升级中); break; } }8.2 唤醒词打断逻辑static bool g_tts_playing false; static bool g_realtime_interrupt_enable true; void voice_on_wakeup_detected(void) { ESP_LOGI(VOICE, 检测到唤醒词); if (g_ai_state AI_STATE_SPEAKING g_tts_playing) { ESP_LOGI(VOICE, AI 播报中检测到唤醒词执行唤醒词打断); audio_player_stop(); ai_ws_send_interrupt(); g_tts_playing false; ai_set_state(AI_STATE_INTERRUPTED); vTaskDelay(pdMS_TO_TICKS(100)); } ai_set_state(AI_STATE_LISTENING); ai_ws_send_listen_start(); audio_capture_start(); }8.3 实时打断逻辑void voice_on_realtime_speech_detected(void) { if (!g_realtime_interrupt_enable) { return; } if (g_ai_state AI_STATE_SPEAKING g_tts_playing) { ESP_LOGI(VOICE, 检测到用户插话执行实时打断); audio_player_stop(); ai_ws_send_interrupt(); g_tts_playing false; ai_set_state(AI_STATE_INTERRUPTED); vTaskDelay(pdMS_TO_TICKS(100)); ai_set_state(AI_STATE_LISTENING); audio_capture_start(); ai_ws_send_listen_start(); } }8.4 高噪音场景模式针对空气炸锅、抽油烟机、风扇等高噪音环境可以增加场景模式typedef enum { NOISE_MODE_NORMAL 0, NOISE_MODE_KITCHEN, NOISE_MODE_FAN, NOISE_MODE_MUSIC, } noise_mode_t; static noise_mode_t g_noise_mode NOISE_MODE_NORMAL; void audio_set_noise_mode(noise_mode_t mode) { g_noise_mode mode; switch (mode) { case NOISE_MODE_NORMAL: ESP_LOGI(AUDIO, 普通环境模式); voice_frontend_set_agc_level(1); voice_frontend_set_vad_threshold(40); break; case NOISE_MODE_KITCHEN: ESP_LOGI(AUDIO, 厨房高噪音模式); voice_frontend_set_agc_level(2); voice_frontend_set_vad_threshold(65); voice_frontend_enable_noise_suppression(true); break; case NOISE_MODE_FAN: ESP_LOGI(AUDIO, 风扇噪音模式); voice_frontend_set_agc_level(2); voice_frontend_set_vad_threshold(60); voice_frontend_enable_noise_suppression(true); break; case NOISE_MODE_MUSIC: ESP_LOGI(AUDIO, 背景音乐模式); voice_frontend_set_agc_level(1); voice_frontend_set_vad_threshold(70); voice_frontend_enable_aec(true); break; } }9. AI WebSocket 会话层9.1 会话事件typedef enum { AI_WS_EVT_CONNECTED 0, AI_WS_EVT_DISCONNECTED, AI_WS_EVT_ASR_TEXT, AI_WS_EVT_LLM_TEXT, AI_WS_EVT_TTS_AUDIO, AI_WS_EVT_TTS_DONE, AI_WS_EVT_ERROR, } ai_ws_evt_t;9.2 WebSocket 初始化骨架#include esp_websocket_client.h static esp_websocket_client_handle_t g_ws NULL; static void ai_ws_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) { esp_websocket_event_data_t *data (esp_websocket_event_data_t *)event_data; switch (event_id) { case WEBSOCKET_EVENT_CONNECTED: ESP_LOGI(AI_WS, WebSocket 已连接); ai_set_state(AI_STATE_IDLE); break; case WEBSOCKET_EVENT_DISCONNECTED: ESP_LOGW(AI_WS, WebSocket 已断开); ai_set_state(AI_STATE_CONNECTING); break; case WEBSOCKET_EVENT_DATA: ESP_LOGI(AI_WS, 收到 AI 数据长度%d, data-data_len); ai_ws_parse_message(data-data_ptr, data-data_len); break; case WEBSOCKET_EVENT_ERROR: ESP_LOGE(AI_WS, WebSocket 错误); break; } } static bool ai_ws_connect(void) { esp_websocket_client_config_t ws_cfg { .uri wss://your-ai-server.example.com/xiaozhi/v1/, .reconnect_timeout_ms 5000, .network_timeout_ms 10000, }; g_ws esp_websocket_client_init(ws_cfg); if (!g_ws) { return false; } esp_websocket_register_events( g_ws, WEBSOCKET_EVENT_ANY, ai_ws_event_handler, NULL ); esp_websocket_client_start(g_ws); return true; }9.3 发送监听开始 / 打断事件static void ai_ws_send_json(const char *json) { if (!g_ws || !esp_websocket_client_is_connected(g_ws)) { ESP_LOGW(AI_WS, WebSocket 未连接发送失败); return; } esp_websocket_client_send_text(g_ws, json, strlen(json), portMAX_DELAY); } void ai_ws_send_listen_start(void) { ai_ws_send_json( { \type\:\listen\, \state\:\start\ } ); } void ai_ws_send_listen_stop(void) { ai_ws_send_json( { \type\:\listen\, \state\:\stop\ } ); } void ai_ws_send_interrupt(void) { ai_ws_send_json( { \type\:\interrupt\, \reason\:\barge_in\ } ); }9.4 发送音频数据void ai_ws_send_audio_frame(const uint8_t *audio, size_t len) { if (!g_ws || !esp_websocket_client_is_connected(g_ws)) { return; } esp_websocket_client_send_bin( g_ws, (const char *)audio, len, portMAX_DELAY ); }10. 音频采集任务#define AUDIO_FRAME_SIZE 640 static bool g_audio_capture_running false; void audio_capture_start(void) { g_audio_capture_running true; } void audio_capture_stop(void) { g_audio_capture_running false; } void audio_capture_task(void *arg) { uint8_t audio_frame[AUDIO_FRAME_SIZE]; while (1) { if (!g_audio_capture_running) { vTaskDelay(pdMS_TO_TICKS(20)); continue; } int len microphone_read(audio_frame, sizeof(audio_frame)); if (len 0) { /* * 可在此处加入 * 1. AEC * 2. AGC * 3. NS 降噪 * 4. VAD 端点检测 * 5. Opus 编码 */ ai_ws_send_audio_frame(audio_frame, len); } if (voice_frontend_is_speech_end()) { ESP_LOGI(AUDIO, 检测到语音结束); audio_capture_stop(); ai_ws_send_listen_stop(); ai_set_state(AI_STATE_THINKING); } vTaskDelay(pdMS_TO_TICKS(10)); } }11. TTS 播放任务typedef struct { uint8_t *data; size_t len; } tts_audio_packet_t; static QueueHandle_t g_tts_queue; void tts_player_init(void) { g_tts_queue xQueueCreate(8, sizeof(tts_audio_packet_t)); } void tts_enqueue_audio(uint8_t *data, size_t len) { tts_audio_packet_t pkt { .data data, .len len, }; xQueueSend(g_tts_queue, pkt, portMAX_DELAY); } void tts_player_task(void *arg) { tts_audio_packet_t pkt; while (1) { if (xQueueReceive(g_tts_queue, pkt, portMAX_DELAY)) { if (!g_tts_playing) { g_tts_playing true; ai_set_state(AI_STATE_SPEAKING); } speaker_write(pkt.data, pkt.len); free(pkt.data); } } }AI 返回 TTS 结束时void ai_on_tts_done(void) { ESP_LOGI(TTS, TTS 播放结束); g_tts_playing false; ai_set_state(AI_STATE_IDLE); }12. MCP / UART 扩展协议《开发宝典》中四博 ATMCP 协议通过 UART 实现语义到控制指令的映射标准串口参数为115200、8N1、无校验、1 位停止位。模块收到合法 AT 指令后返回 OK通过ATADDMCP可把自然语言映射成 MCU 可执行的二进制控制帧。12.1 MCP 场景设计语音“切换到 4G 上网” 动作ESP32-S3 切换 4G 网络模式 语音“打开厨房模式” 动作启用高噪声拾音参数 语音“声音调到 80” 动作设置音量为 80 语音“关闭屏幕” 动作LCD 背光关闭 语音“打开副屏表情” 动作副屏显示 AI 表情 语音“开始配网” 动作进入 BluFi / SoftAP 配网模式12.2 MCP UART 初始化#define MCP_UART_PORT UART_NUM_2 #define MCP_UART_TX_PIN 41 #define MCP_UART_RX_PIN 42 #define MCP_UART_BAUD 115200 #define MCP_RX_BUF_SIZE 512 static void mcp_uart_init(void) { uart_config_t uart_config { .baud_rate MCP_UART_BAUD, .data_bits UART_DATA_8_BITS, .parity UART_PARITY_DISABLE, .stop_bits UART_STOP_BITS_1, .flow_ctrl UART_HW_FLOWCTRL_DISABLE, }; uart_driver_install(MCP_UART_PORT, MCP_RX_BUF_SIZE * 2, 0, 0, NULL, 0); uart_param_config(MCP_UART_PORT, uart_config); uart_set_pin(MCP_UART_PORT, MCP_UART_TX_PIN, MCP_UART_RX_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); ESP_LOGI(MCP, MCP UART 初始化完成); }12.3 发送 AT 指令static void mcp_send_line(const char *line) { uart_write_bytes(MCP_UART_PORT, line, strlen(line)); } static void mcp_register_commands(void) { mcp_send_line(AT\r\n); // 音量控制返回一个音量参数 V mcp_send_line( ATADDMCP1,set_volume,设置音箱音量,F1,1,V\r\n ); // 厨房高噪声模式固定返回命令 mcp_send_line( ATADDMCP0,set_kitchen_mode,打开厨房高噪音模式,2,F2,01\r\n ); // 网络切换N1 WiFiN2 蓝牙N3 4G mcp_send_line( ATADDMCP1,switch_network,切换联网方式,F3,1,N\r\n ); // 屏幕亮度 mcp_send_line( ATADDMCP1,set_brightness,设置屏幕亮度,F4,1,B\r\n ); // 表情切换 mcp_send_line( ATADDMCP1,set_expression,设置副屏表情,F5,1,E\r\n ); // 进入配网模式 mcp_send_line( ATADDMCP0,start_config,开始配网,2,F6,01\r\n ); }12.4 MCP 帧格式解析《开发宝典》中 MCP 设备帧格式为0x55 0xAA LEN CMD DATA... 0xAA 0x55代码解析typedef struct { uint8_t len; uint8_t cmd; uint8_t data[32]; } mcp_frame_t; static bool mcp_parse_frame(const uint8_t *buf, int len, mcp_frame_t *out) { if (len 5) { return false; } if (buf[0] ! 0x55 || buf[1] ! 0xAA) { return false; } uint8_t payload_len buf[2]; if (len payload_len 4) { return false; } if (buf[payload_len 2] ! 0xAA || buf[payload_len 3] ! 0x55) { return false; } out-len payload_len; out-cmd buf[3]; int data_len payload_len - 1; if (data_len 0) { memcpy(out-data, buf[4], data_len); } return true; }12.5 MCP 指令处理static void mcp_handle_frame(const mcp_frame_t *frame) { switch (frame-cmd) { case 0xF1: ESP_LOGI(MCP, 设置音量: %d, frame-data[0]); audio_set_volume(frame-data[0]); display_show_status(音量已调整); break; case 0xF2: ESP_LOGI(MCP, 打开厨房高噪声模式); audio_set_noise_mode(NOISE_MODE_KITCHEN); display_show_status(厨房模式); break; case 0xF3: ESP_LOGI(MCP, 切换网络: %d, frame-data[0]); if (frame-data[0] 1) { net_set_mode(NET_MODE_WIFI); } else if (frame-data[0] 2) { net_set_mode(NET_MODE_BT); } else if (frame-data[0] 3) { net_set_mode(NET_MODE_4G); } break; case 0xF4: ESP_LOGI(MCP, 设置屏幕亮度: %d, frame-data[0]); display_set_brightness(frame-data[0]); break; case 0xF5: ESP_LOGI(MCP, 设置副屏表情: %d, frame-data[0]); display_set_expression_by_id(frame-data[0]); break; case 0xF6: ESP_LOGI(MCP, 进入配网模式); ai_set_state(AI_STATE_NET_CONFIG); start_blufi_config(); break; case 0xFC: /* * 开发宝典中提到 * 如果模块发出 55 AA 01 FC AA 55 * MCU 需要重启 AI 模组并重新发送 MCP 映射。 */ ESP_LOGW(MCP, AI 模组请求恢复重启并重发 MCP); ai_module_reset(); vTaskDelay(pdMS_TO_TICKS(1000)); mcp_register_commands(); break; default: ESP_LOGW(MCP, 未知 MCP CMD: 0x%02X, frame-cmd); break; } }12.6 MCP UART 任务void mcp_uart_task(void *arg) { uint8_t rxbuf[128]; mcp_frame_t frame; mcp_register_commands(); while (1) { int len uart_read_bytes( MCP_UART_PORT, rxbuf, sizeof(rxbuf), pdMS_TO_TICKS(100) ); if (len 0) { if (mcp_parse_frame(rxbuf, len, frame)) { mcp_handle_frame(frame); } else { rxbuf[len] 0; ESP_LOGI(MCP, UART 文本返回: %s, (char *)rxbuf); } } vTaskDelay(pdMS_TO_TICKS(10)); } }13. 单屏 / 双屏 / 异显设计13.1 显示模式定义typedef enum { DISPLAY_MODE_SINGLE 0, DISPLAY_MODE_DUAL_SAME, DISPLAY_MODE_DUAL_DIFF, } display_mode_t; typedef enum { DISPLAY_MAIN 0, DISPLAY_SUB, } display_id_t; static display_mode_t g_display_mode DISPLAY_MODE_DUAL_DIFF;13.2 显示内容分工单屏模式 - 网络状态 - AI 状态 - 音量 - 时间 - 对话文本 - 天气 - OTA 状态 双屏同显 - 两个屏幕显示相同 UI 双屏异显 - 主屏文本、菜单、设置、状态 - 副屏AI 表情、眼睛动画、语音波形、状态图标13.3 LVGL 显示刷新骨架void display_show_status(const char *text) { lcd_select(DISPLAY_MAIN); lv_label_set_text(ui_status_label, text); } void display_show_ai_text(const char *text) { lcd_select(DISPLAY_MAIN); lv_label_set_text(ui_ai_text_label, text); } void display_show_expression(const char *expr) { if (g_display_mode DISPLAY_MODE_SINGLE) { return; } lcd_select(DISPLAY_SUB); if (strcmp(expr, idle) 0) { lv_img_set_src(ui_expression_img, img_idle); } else if (strcmp(expr, listening) 0) { lv_img_set_src(ui_expression_img, img_listening); } else if (strcmp(expr, thinking) 0) { lv_img_set_src(ui_expression_img, img_thinking); } else if (strcmp(expr, speaking) 0) { lv_img_set_src(ui_expression_img, img_speaking); } else if (strcmp(expr, interrupt) 0) { lv_img_set_src(ui_expression_img, img_interrupt); } }13.4 根据 AI 状态刷新 UIvoid display_update_by_state(ai_state_t state) { switch (state) { case AI_STATE_IDLE: display_show_status(待机中); display_show_ai_text(你好我在这里); display_show_expression(idle); break; case AI_STATE_LISTENING: display_show_status(聆听中); display_show_ai_text(请说话...); display_show_expression(listening); break; case AI_STATE_THINKING: display_show_status(思考中); display_show_ai_text(正在理解你的问题); display_show_expression(thinking); break; case AI_STATE_SPEAKING: display_show_status(回答中); display_show_expression(speaking); break; case AI_STATE_INTERRUPTED: display_show_status(已打断); display_show_ai_text(请继续说); display_show_expression(interrupt); break; case AI_STATE_NET_CONFIG: display_show_status(配网模式); display_show_ai_text(请使用四博小助手配网); break; default: break; } }14. 按键逻辑设计结合四博设备常见操作可以定义单击切换聆听 / 空闲 双击切换联网模式 / 进入唤醒词升级模式 三击进入配网模式 长按开关机 五击进入素材 / 调试模式14.1 按键事件处理typedef enum { KEY_EVT_SINGLE_CLICK 0, KEY_EVT_DOUBLE_CLICK, KEY_EVT_TRIPLE_CLICK, KEY_EVT_LONG_PRESS, KEY_EVT_FIVE_CLICK, } key_evt_t; void key_handle_event(key_evt_t evt) { switch (evt) { case KEY_EVT_SINGLE_CLICK: if (g_ai_state AI_STATE_IDLE) { ai_set_state(AI_STATE_LISTENING); audio_capture_start(); ai_ws_send_listen_start(); } else if (g_ai_state AI_STATE_LISTENING) { audio_capture_stop(); ai_ws_send_listen_stop(); ai_set_state(AI_STATE_IDLE); } break; case KEY_EVT_DOUBLE_CLICK: net_switch_next_mode(); display_show_status(切换联网方式); break; case KEY_EVT_TRIPLE_CLICK: ai_set_state(AI_STATE_NET_CONFIG); start_blufi_config(); break; case KEY_EVT_LONG_PRESS: display_show_status(准备关机); board_power_off(); break; case KEY_EVT_FIVE_CLICK: display_show_status(进入调试模式); enter_debug_mode(); break; } }15. OTA 升级设计开发宝典中 S3 AI-Speaker 工程可配置 OTA 地址设备重新编译烧录后可连接自己的后端服务开发宝典中也提到如果对工程编译环境不熟悉可使用四博在线烧录平台体验固件。15.1 OTA 检测流程设备启动 ↓ 获取当前固件版本 ↓ 请求 OTA 服务 ↓ 比较服务器版本 ↓ 如有新版本下载固件 ↓ 校验固件 ↓ 写入 OTA 分区 ↓ 重启进入新固件15.2 OTA 配置示例#define FIRMWARE_VERSION 1.0.0 #define OTA_CHECK_URL https://your-domain.com/v1/ota/check void ota_service_check(void) { char post_data[256]; snprintf(post_data, sizeof(post_data), { \model\:\sibo_ai_speaker_s3_4g\, \version\:\%s\, \chip\:\esp32s3\ }, FIRMWARE_VERSION ); ESP_LOGI(OTA, 检查 OTA: %s, post_data); /* * 实际实现 * 1. HTTP POST 到 OTA 服务 * 2. 获取版本号和固件 URL * 3. 调用 esp_https_ota */ }16. 客户系统接入方式16.1 方式一客户云平台接入四博 AI 音箱 ↓ WebSocket / HTTPS 客户 AI 网关 ↓ 客户 ASR / LLM / TTS / 知识库 ↓ 返回音频 / 文本 / 控制命令适合教育学习机 AI 故事机 客户自有内容平台 会员制 AI 服务 企业知识库问答16.2 方式二客户 MCU 接入客户 MCU ↑↓ UART / MCP 四博 AI 音箱 S3 主控 ↑↓ Wi-Fi / 蓝牙 / 4G AI 云端适合传统家电 玩具主控 灯控系统 机器人主控 智能中控设备16.3 方式三客户 App / 小程序接入客户 App / 小程序 ↓ 客户服务器 ↓ 设备管理 / AI 配置 / 内容下发 ↓ 四博 AI 音箱适合品牌客户 电商成品客户 需要用户体系的客户 需要素材管理的客户 需要知识库配置的客户17. 工程配置示例17.1 sdkconfig.defaults.board# 目标芯片 CONFIG_IDF_TARGETesp32s3 # 蓝牙与 BluFi 配网 CONFIG_BT_ENABLEDy CONFIG_USE_BLUFI_NET_CONFIGURINGy # Wi-Fi CONFIG_ESP_WIFI_ENABLEDy # 4G CONFIG_USE_4G_NETWORKy CONFIG_MODEM_UART_BAUD115200 # 音频 CONFIG_USE_AUDIO_CODECy CONFIG_USE_I2S_SPEAKERy CONFIG_USE_MICROPHONEy # AEC / 实时打断 CONFIG_USE_DEVICE_AECy CONFIG_USE_SERVER_AECn CONFIG_USE_REALTIME_INTERRUPTy # 显示 CONFIG_USE_LCD_DISPLAYy CONFIG_USE_DUAL_LCD_DISPLAYy CONFIG_USE_DIFFERENT_DISPLAYy # MCP CONFIG_USE_MCP_UARTy CONFIG_MCP_UART_BAUD115200 # OTA CONFIG_OTA_URLhttps://your-domain.com/v1/ota/ # AI 服务 CONFIG_AI_WEBSOCKET_URLwss://your-domain.com/xiaozhi/v1/17.2 Kconfig 菜单示例menu Sibo AI Speaker S3 4G config BOARD_TYPE_SIBO_AI_SPEAKER_S3_4G bool Sibo AI Speaker S3 4G default y config USE_WIFI_NETWORK bool Enable Wi-Fi network default y config USE_BT_NETWORK bool Enable Bluetooth network default y config USE_4G_NETWORK bool Enable 4G network default y config USE_REALTIME_INTERRUPT bool Enable realtime barge-in default y config USE_WAKEUP_INTERRUPT bool Enable wake word interrupt default y config USE_DUAL_LCD_DISPLAY bool Enable dual LCD display default y config USE_MCP_UART bool Enable MCP UART default y endmenu18. 编译与烧录流程《开发宝典》中四博 S3 方案使用 ESP-IDF 工程方式开发S3 AI-Speaker 章节给出了克隆工程、配置工程、编译、合并固件和烧录流程C5 章节也说明C5 编译建议使用 ESP-IDF 5.5。# 1. 进入 ESP-IDF 环境 . ~/esp/esp-idf/export.sh # 2. 设置目标芯片 idf.py set-target esp32s3 # 3. 打开配置菜单 idf.py menuconfig # 4. 编译工程 idf.py build # 5. 合并固件 idf.py merge-bin # 6. 烧录并查看日志 idf.py -p COMx flash monitor19. 技术卖点总结19.1 远场语音能力- 5 米范围内可唤醒 - 5 米范围内可打断 - 5 米范围内可连续对话 - 高噪声环境下仍能稳定响应 - 适合厨房、客厅、儿童房、展厅等复杂环境19.2 打断能力- 支持唤醒词打断 - 支持实时打断 - 支持 AI 播报过程中插话 - 支持修改唤醒词 - 支持品牌专属唤醒词19.3 三模联网- Wi-Fi家庭和固定场景 - 蓝牙手机辅助联网和快速配网 - 4G户外、移动、无 Wi-Fi 场景19.4 显示能力- 支持单屏显示 - 支持双屏显示 - 支持双屏异显 - 可显示 AI 表情、状态、文本、天气、时间、音量、网络状态19.5 二次开发能力- 基于 ESP32-S3 - 基于 ESP-IDF - 支持 UART / MCP - 支持 WebSocket / HTTPS - 支持客户云平台 - 支持客户 App / 小程序 - 支持自定义知识库和自建大模型20. 技术推广版结尾四博 AI 智能音箱 4G S3 版本是一套面向量产和二次开发的 AI 语音硬件底座。它不仅支持传统 AI 音箱的语音问答能力还进一步集成了远距离拾音、高噪音环境识别、唤醒词打断、实时打断、唤醒词修改、Wi-Fi / 蓝牙 / 4G 三模联网、单屏 / 双屏 / 异显显示、MCP 语义控制和客户系统接入能力。对于客户来说四博方案可以快速完成从技术原型到成品量产的落地。客户既可以直接使用四博现有 AI 音箱方案也可以在 ESP32-S3 平台上接入自己的云服务、App、小程序、知识库、内容系统、控制协议和品牌唤醒词从而形成自有品牌的 AI 智能音箱、AI 学习机、AI 桌宠或 AI 中控产品。四博提供的不只是一个 AI 音箱硬件而是一套可联网、可打断、可显示、可扩展、可量产、可接入客户系统的 AI 智能硬件完整方案。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2551125.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…