下面是一套偏 工程落地 / 技术评审 / 客户方案书 风格的"四博 AI 智能拍学机 / AI 智能音箱一体化方案"。这里把"AI 智能拍学机"定义为:AI 智能音箱 + 摄像头拍题学习 + 屏幕交互 + 学习游戏 + 大模型辅导 + 远程管理 + 客户系统接入。
方案基于你上传的《四博智联 AI 开发宝典》《深圳四博智联 AI 硬件选型表 2026》和《2026 年四博智联模组选型手册-乐鑫系》。资料中明确提到,ESP32-C2 / C3 / S3 加 VB6824 语音方案已经成熟应用于电子吧唧、S3 双目、S3 拍学机、地球仪、拍拍灯等方向;VB6824 可完成音频编解码、AEC、语音唤醒、改唤醒词等功能,让主控芯片专注通信和 UI。
四博 AI 智能拍学机 / AI 智能音箱技术方案
1. 产品定位
本方案面向一款儿童学习类 AI 硬件,产品形态可以是:
AI 智能拍学机
= AI 智能音箱
+ 摄像头拍题
+ 屏幕显示
+ 学习辅导
+ 互动游戏
+ 语音对话
+ 本地内容
+ 远程管理
+ 客户系统接入
核心功能包括:
1. AI 对话:
语音唤醒、连续对话、知识问答、百科解释、故事陪伴。
2. 拍照学习:
拍题识别、OCR、错题讲解、英语单词识别、绘本识别、口算批改。
3. 学习模式:
语文、数学、英语、百科、绘本阅读、单词记忆、每日学习任务。
4. 游戏模式:
口算闯关、单词消消乐、成语接龙、记忆训练、听音辨词、AI 猜谜。
5. 远程管理:
家长端管理、内容下发、学习报告、OTA、参数配置、日志诊断。
6. 二次开发:
支持 ESP-IDF、DOIT_AI、小智协议、AT+MCP、HTTP、MQTT、WebSocket。
硬件建议采用 ESP32-S3R8 + 16M Flash + 8M PSRAM + VB6824 + 摄像头 + 屏幕 + 麦克风 + 喇叭。四博选型资料中,AI 智能相机形态已经包含 2.0 寸屏、4G 选配、存储卡选配、摄像头、镜片、主板、麦克风、电池包、喇叭和线材,主控为 ESP32S3R8 + 16M Flash + VB6824,可选小智、豆包、ChatGPT 等大模型,适合品牌 B 端客户或方案商客户定制。
2. 推荐硬件架构
2.1 整体框图
┌──────────────────────────────────────────────────────────────┐
│ 四博 AI 智能拍学机 / AI 音箱 │
├──────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────┐ UART / GPIO │
│ │ VB6824 语音前端 │◄─────────────────────────────┐ │
│ │ - 离线唤醒 │ │ │
│ │ - AEC 回声消除 │ │ │
│ │ - 降噪 │ │ │
│ │ - 唤醒词打断 │ │ │
│ │ - 改唤醒词 │ │ │
│ └─────────┬────────────┘ │ │
│ │ MIC / 回采音频 │ │
│ ▼ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ ESP32-S3R8 + 16M Flash + 8M PSRAM │ │
│ │ - Wi-Fi / BLE BluFi │ │
│ │ - WebSocket AI 对话 │ │
│ │ - 摄像头采集 / JPEG 编码 │ │
│ │ - OCR / VLM / 拍题后端请求 │ │
│ │ - LCD UI / 游戏界面 │ │
│ │ - 本地学习游戏引擎 │ │
│ │ - SD 卡 / Flash 内容缓存,可选 │ │
│ │ - OTA / 远程管理 / 日志 │ │
│ │ - MCP 工具调用 / 客户系统接入 │ │
│ └───────┬───────────────┬───────────────┬────────────────┘ │
│ │ │ │ │
│ ┌───────▼──────┐ ┌──────▼──────┐ ┌──────▼────────┐ │
│ │ Camera │ │ LCD / Touch │ │ I2S AMP+SPK │ │
│ │ 拍题 / 识物 │ │ 学习/游戏UI │ │ TTS/提示音 │ │
│ └──────────────┘ └─────────────┘ └───────────────┘ │
│ │
│ 可选扩展:4G 模组 / 7014 蓝牙 PAN / SD 卡 / IMU / 触摸按键 │
└──────────────────────────────────────────────────────────────┘
云端 / 私有化后端:
┌──────────────────────────────────────────────────────────────┐
│ OTA │ WebSocket │ ASR │ LLM │ TTS │ OCR │ VLM │ 题库 │ 家长后台 │
└──────────────────────────────────────────────────────────────┘
3. 主控选型
推荐使用四博 ESPS3-32-N16R8 / ESPS3-32E-N16R8。
根据乐鑫系模组选型手册,ESPS3-32 系列支持 ESP32-S3 / S3R2 / S3R8,提供 N4、N8、N8R2、N16R2、N16R8 等子型号,18 × 25.5mm 通用模组,兼容 ESP32-S3-WROOM-1 系列;ESPS3-32E 为 18 × 19.2mm,兼容 ESP32-S3-WROOM-1U 系列。
推荐配置:
主控:ESP32-S3R8
Flash:16MB
PSRAM:8MB
无线:2.4GHz Wi-Fi + BLE
显示:SPI / RGB / I8080 LCD
摄像头:DVP Camera
音频:I2S 输出 + MIC / VB6824
选择 ESP32-S3 的原因:
1. 适合音视频 / AI 市场;
2. 支持摄像头 DVP;
3. 支持 LCD 屏幕;
4. PSRAM 可承载 JPEG buffer、UI buffer、WebSocket buffer;
5. ESP-IDF 生态成熟;
6. 适合客户二次开发和量产。
开发宝典中的多模态方案 DOIT_ESPS3_AI_EYE_Vision 就是基于 ESP32-S3,集摄像头、双目显示和触摸交互于一体,硬件与软件全开源,可直接用于二次开发或量产制造。
4. 功能架构
4.1 AI 音箱能力
用户:"你好小智,帮我讲一个恐龙故事。"
↓
VB6824 唤醒
↓
ESP32-S3 建立 AI 会话
↓
WebSocket 上传音频
↓
ASR + LLM + TTS
↓
喇叭播放 + 屏幕显示文字 / 表情
支持能力:
1. 唤醒词唤醒;
2. 按键唤醒;
3. AI 多轮对话;
4. TTS 播报;
5. 声音克隆;
6. 知识库问答;
7. MCP 工具扩展;
8. 客户自有大模型接入。
4.2 拍题学习能力
用户:"小博,帮我看一下这道题。"
↓
摄像头拍照
↓
JPEG 压缩
↓
上传 OCR / VLM / 拍题服务
↓
返回题目文本、答案、步骤、知识点
↓
LLM 生成儿童友好解释
↓
屏幕显示步骤 + TTS 讲解
典型学习场景:
数学:
- 口算批改
- 应用题讲解
- 竖式计算识别
- 错题归因
语文:
- 生字解释
- 拼音纠错
- 课文朗读
- 成语解释
英语:
- 单词识别
- 跟读评分
- 中英互译
- 情景对话
绘本:
- 拍图讲故事
- 识别画面内容
- 提问互动
4.3 游戏能力
游戏不建议做复杂 3D,而建议做 轻量级学习游戏:
1. 口算闯关;
2. 单词选择;
3. 成语接龙;
4. 听音辨词;
5. 看图猜物;
6. 记忆翻牌;
7. 学习打卡;
8. 积分成长系统。
游戏逻辑本地运行,题库和成长数据可云端同步:
本地:
- UI 渲染
- 按键 / 触摸输入
- 计时
- 分数
- 简单题库
云端:
- 学习报告
- 个性化推荐
- 错题本
- 家长端任务
- 排行榜,可选
AI 硬件选型表中提到 ESP32-S3 + 7014 + 摄像头 + 4G 高端方案具有开发者生态好、可多模态、可以玩游戏、可以当蓝牙音箱等特点,这类能力非常适合扩展成 AI 拍学机。
5. 软件系统设计
5.1 组件划分
main/
app_main.c
components/
board/
board_config.h
board_init.c
audio/
audio_focus.c
tts_player.c
wakeup_frontend.c
ai/
ai_session.c
websocket_client.c
mcp_uart_bridge.c
camera/
camera_service.c
image_capture.c
learning/
study_session.c
ocr_client.c
vlm_client.c
homework_solver.c
wrong_book.c
game/
game_engine.c
math_quiz.c
word_game.c
idiom_game.c
ui/
display_manager.c
screen_learning.c
screen_game.c
screen_status.c
remote/
remote_manager.c
mqtt_shadow.c
ota_manager.c
customer/
customer_http.c
customer_mqtt.c
5.2 FreeRTOS 任务
| 任务 | 优先级 | 作用 |
|---|---|---|
audio_frontend_task |
高 | 唤醒、打断、录音状态 |
ai_session_task |
高 | AI WebSocket、ASR、LLM、TTS |
camera_task |
中高 | 拍照、JPEG buffer 管理 |
learning_task |
中高 | 拍题、OCR、VLM、学习结果处理 |
game_task |
中 | 学习游戏状态机 |
ui_task |
中 | 屏幕刷新、学习界面、游戏界面 |
remote_task |
中 | 远程管理、家长端命令、状态上报 |
mcp_uart_task |
中高 | AT+MCP 语音工具调用 |
ota_task |
低 | 固件 OTA、资源 OTA |
log_task |
低 | 学习日志、错误日志上传 |
6. 开发环境与工程编译
开发宝典说明,小智 AI 硬件设备的开源代码可在 VSCode 中安装 ESP-IDF 扩展和编译工具进行编译烧录;多模态工程使用 VSCode 打开,ESP-IDF 版本需大于等于 5.3.2,并设置目标芯片为 esp32s3。
6.1 DOIT_AI 基础工程
git clone https://github.com/SmartArduino/DOIT_AI.git
cd DOIT_AI
idf.py set-target esp32s3
idf.py menuconfig
idf.py build
idf.py -p /dev/ttyUSB0 flash monitor
6.2 多模态视觉工程
git clone https://github.com/SmartArduino/DOIT_ESPS3_AI_EYE_Vision.git
cd DOIT_ESPS3_AI_EYE_Vision
idf.py set-target esp32s3
idf.py menuconfig
idf.py build
idf.py -p /dev/ttyUSB0 flash monitor
6.3 推荐 menuconfig
Board Type:
Sibo AI Study Camera Speaker S3
Audio:
VB6824 Enable = y
USE_DEVICE_AEC = y
Camera:
Enable Camera = y
Pixel Format = JPEG
Frame Size = VGA / SVGA
Display:
LCD Enable = y
Study UI = y
Game UI = y
Network:
Wi-Fi = y
BluFi Provisioning = y
4G Optional = n / y
AI:
Xiaozhi WebSocket = y
MCP Enable = y
Vision Tool = y
Learning:
OCR Enable = y
Homework Solver Enable = y
Local Game Engine = y
Remote:
MQTT Shadow = y
OTA = y
Log Upload = y
7. 关键代码示例
下面代码为工程骨架示例,可直接作为 ESP-IDF 组件起点。GPIO、屏幕驱动、摄像头型号、后端接口 URL 需要按实际 PCB 和客户平台调整。
7.1 板级配置 board_config.h
#pragma once
#include "driver/gpio.h"
#include "driver/uart.h"
#include "driver/spi_master.h"
/*
* 四博 AI 智能拍学机 / AI 智能音箱
* ESP32-S3R8 + 16M Flash + 8M PSRAM + VB6824 + Camera + LCD
*/
#define BOARD_NAME "SIBO_AI_STUDY_CAMERA_S3"
/* ---------- AI / VB6824 UART ---------- */
#define AI_UART UART_NUM_1
#define AI_UART_BAUD 115200
#define AI_UART_TX_GPIO GPIO_NUM_42
#define AI_UART_RX_GPIO GPIO_NUM_41
#define AI_RESET_GPIO GPIO_NUM_40
/* ---------- Camera DVP,示例,量产需按 PCB 修改 ---------- */
#define CAM_PIN_PWDN GPIO_NUM_NC
#define CAM_PIN_RESET GPIO_NUM_NC
#define CAM_PIN_XCLK GPIO_NUM_15
#define CAM_PIN_SIOD GPIO_NUM_4
#define CAM_PIN_SIOC GPIO_NUM_5
#define CAM_PIN_D0 GPIO_NUM_11
#define CAM_PIN_D1 GPIO_NUM_9
#define CAM_PIN_D2 GPIO_NUM_8
#define CAM_PIN_D3 GPIO_NUM_10
#define CAM_PIN_D4 GPIO_NUM_12
#define CAM_PIN_D5 GPIO_NUM_13
#define CAM_PIN_D6 GPIO_NUM_14
#define CAM_PIN_D7 GPIO_NUM_16
#define CAM_PIN_VSYNC GPIO_NUM_6
#define CAM_PIN_HREF GPIO_NUM_7
#define CAM_PIN_PCLK GPIO_NUM_21
/* ---------- LCD SPI ---------- */
#define LCD_SPI_HOST SPI2_HOST
#define LCD_SPI_SCLK_GPIO GPIO_NUM_35
#define LCD_SPI_MOSI_GPIO GPIO_NUM_36
#define LCD_CS_GPIO GPIO_NUM_37
#define LCD_DC_GPIO GPIO_NUM_38
#define LCD_RST_GPIO GPIO_NUM_39
#define LCD_BL_GPIO GPIO_NUM_45
/* ---------- I2S Speaker ---------- */
#define I2S_BCLK_GPIO GPIO_NUM_1
#define I2S_LRCK_GPIO GPIO_NUM_2
#define I2S_DOUT_GPIO GPIO_NUM_3
#define AMP_EN_GPIO GPIO_NUM_46
/* ---------- Keys / Touch ---------- */
#define KEY_BOOT_GPIO GPIO_NUM_0
#define KEY_CAPTURE_GPIO GPIO_NUM_47
#define KEY_GAME_GPIO GPIO_NUM_48
/* ---------- Remote / Backend ---------- */
#define AI_WS_URL "wss://ai.customer.com/xiaozhi/v1/"
#define OTA_URL "https://ota.customer.com/study_camera/ota/"
#define OCR_API_URL "https://api.customer.com/v1/ocr"
#define VLM_API_URL "https://api.customer.com/v1/vision"
#define STUDY_API_URL "https://api.customer.com/v1/study/solve"
#define MQTT_URI "mqtts://mqtt.customer.com"
7.2 摄像头初始化与拍照
#include "esp_log.h"
#include "esp_camera.h"
#include "board_config.h"
#define TAG "CAMERA"
static camera_fb_t *s_last_fb = NULL;
esp_err_t camera_service_init(void)
{
camera_config_t config = {
.pin_pwdn = CAM_PIN_PWDN,
.pin_reset = CAM_PIN_RESET,
.pin_xclk = CAM_PIN_XCLK,
.pin_sccb_sda = CAM_PIN_SIOD,
.pin_sccb_scl = CAM_PIN_SIOC,
.pin_d7 = CAM_PIN_D7,
.pin_d6 = CAM_PIN_D6,
.pin_d5 = CAM_PIN_D5,
.pin_d4 = CAM_PIN_D4,
.pin_d3 = CAM_PIN_D3,
.pin_d2 = CAM_PIN_D2,
.pin_d1 = CAM_PIN_D1,
.pin_d0 = CAM_PIN_D0,
.pin_vsync = CAM_PIN_VSYNC,
.pin_href = CAM_PIN_HREF,
.pin_pclk = CAM_PIN_PCLK,
.xclk_freq_hz = 20000000,
.ledc_timer = LEDC_TIMER_2,
.ledc_channel = LEDC_CHANNEL_5,
.pixel_format = PIXFORMAT_JPEG,
.frame_size = FRAMESIZE_VGA,
.jpeg_quality = 12,
.fb_count = 2,
.fb_location = CAMERA_FB_IN_PSRAM,
.grab_mode = CAMERA_GRAB_LATEST,
};
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
ESP_LOGE(TAG, "camera init failed: 0x%x", err);
return err;
}
ESP_LOGI(TAG, "camera init done");
return ESP_OK;
}
camera_fb_t *camera_capture_jpeg(void)
{
if (s_last_fb) {
esp_camera_fb_return(s_last_fb);
s_last_fb = NULL;
}
s_last_fb = esp_camera_fb_get();
if (!s_last_fb) {
ESP_LOGE(TAG, "capture failed");
return NULL;
}
ESP_LOGI(TAG, "capture jpeg len=%u", s_last_fb->len);
return s_last_fb;
}
void camera_release_last(void)
{
if (s_last_fb) {
esp_camera_fb_return(s_last_fb);
s_last_fb = NULL;
}
}
7.3 拍题识别客户端
这个模块负责把摄像头图片上传给后端 OCR / VLM / 拍题服务,并接收解析结果。
#include <stdio.h>
#include <string.h>
#include "esp_log.h"
#include "esp_http_client.h"
#include "esp_camera.h"
#include "board_config.h"
#define TAG "STUDY_SOLVER"
typedef enum {
STUDY_SUBJECT_UNKNOWN = 0,
STUDY_SUBJECT_MATH,
STUDY_SUBJECT_CHINESE,
STUDY_SUBJECT_ENGLISH,
STUDY_SUBJECT_GENERAL,
} study_subject_t;
typedef struct {
study_subject_t subject;
char question[512];
char answer[512];
char steps[1024];
char knowledge[256];
int confidence;
} study_result_t;
extern camera_fb_t *camera_capture_jpeg(void);
extern void camera_release_last(void);
extern void display_show_study_result(const study_result_t *result);
extern void ai_tts_speak_text(const char *text);
static esp_err_t upload_homework_image(camera_fb_t *fb,
study_subject_t subject,
study_result_t *out)
{
if (!fb || !out) {
return ESP_ERR_INVALID_ARG;
}
char subject_header[16];
switch (subject) {
case STUDY_SUBJECT_MATH:
snprintf(subject_header, sizeof(subject_header), "math");
break;
case STUDY_SUBJECT_CHINESE:
snprintf(subject_header, sizeof(subject_header), "chinese");
break;
case STUDY_SUBJECT_ENGLISH:
snprintf(subject_header, sizeof(subject_header), "english");
break;
default:
snprintf(subject_header, sizeof(subject_header), "auto");
break;
}
esp_http_client_config_t config = {
.url = STUDY_API_URL,
.method = HTTP_METHOD_POST,
.timeout_ms = 20000,
.buffer_size = 4096,
};
esp_http_client_handle_t client = esp_http_client_init(&config);
esp_http_client_set_header(client, "Content-Type", "image/jpeg");
esp_http_client_set_header(client, "X-Device-Id", "study_camera_001");
esp_http_client_set_header(client, "X-Subject", subject_header);
esp_http_client_set_post_field(client, (const char *)fb->buf, fb->len);
esp_err_t err = esp_http_client_perform(client);
int status = esp_http_client_get_status_code(client);
ESP_LOGI(TAG, "study api status=%d err=%s", status, esp_err_to_name(err));
/*
* 量产工程中这里应读取 HTTP response body 并解析 JSON。
* 示例返回:
* {
* "subject": "math",
* "question": "12 + 35 = ?",
* "answer": "47",
* "steps": "先算个位 2+5=7,再算十位 1+3=4,所以结果是47。",
* "knowledge": "两位数加法",
* "confidence": 92
* }
*/
out->subject = subject;
snprintf(out->question, sizeof(out->question), "12 + 35 = ?");
snprintf(out->answer, sizeof(out->answer), "47");
snprintf(out->steps, sizeof(out->steps),
"先算个位:2 加 5 等于 7;再算十位:1 加 3 等于 4,所以答案是 47。");
snprintf(out->knowledge, sizeof(out->knowledge), "两位数加法");
out->confidence = 92;
esp_http_client_cleanup(client);
return err;
}
void study_capture_and_solve(study_subject_t subject)
{
ai_tts_speak_text("好的,我来帮你看一下这道题。");
camera_fb_t *fb = camera_capture_jpeg();
if (!fb) {
ai_tts_speak_text("摄像头打开失败,请检查摄像头连接。");
return;
}
study_result_t result = {0};
esp_err_t err = upload_homework_image(fb, subject, &result);
camera_release_last();
if (err != ESP_OK) {
ai_tts_speak_text("题目识别失败,请稍后再试。");
return;
}
display_show_study_result(&result);
ai_tts_speak_text(result.steps);
/*
* TODO:
* 1. 保存到错题本;
* 2. 上传学习记录;
* 3. 推荐相似题;
* 4. 给家长端推送学习报告。
*/
}
7.4 本地学习游戏引擎
这里给一个轻量级"口算闯关"游戏框架。真实产品可以扩展英语单词、成语接龙、记忆训练等模式。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "esp_log.h"
#define TAG "GAME"
typedef enum {
GAME_NONE = 0,
GAME_MATH_QUIZ,
GAME_WORD_SELECT,
GAME_IDIOM_CHAIN,
} game_type_t;
typedef struct {
int a;
int b;
char op;
int answer;
int options[4];
int correct_index;
} math_question_t;
typedef struct {
game_type_t type;
int level;
int score;
int combo;
int question_index;
math_question_t current_math;
} game_session_t;
static game_session_t s_game = {0};
extern void display_game_question(const math_question_t *q, int score, int level);
extern void display_game_result(bool correct, int score);
extern void ai_tts_speak_text(const char *text);
static int rand_range(int min, int max)
{
return min + rand() % (max - min + 1);
}
static void generate_math_question(int level, math_question_t *q)
{
int max = 10 + level * 5;
q->a = rand_range(1, max);
q->b = rand_range(1, max);
q->op = '+';
q->answer = q->a + q->b;
q->correct_index = rand_range(0, 3);
for (int i = 0; i < 4; i++) {
if (i == q->correct_index) {
q->options[i] = q->answer;
} else {
int delta = rand_range(-5, 5);
if (delta == 0) {
delta = 3;
}
q->options[i] = q->answer + delta;
}
}
}
void game_start_math_quiz(int level)
{
if (level < 1) {
level = 1;
}
s_game.type = GAME_MATH_QUIZ;
s_game.level = level;
s_game.score = 0;
s_game.combo = 0;
s_game.question_index = 0;
generate_math_question(level, &s_game.current_math);
display_game_question(&s_game.current_math, s_game.score, s_game.level);
ai_tts_speak_text("口算闯关开始,请选择正确答案。");
}
void game_answer_option(int option_index)
{
if (s_game.type != GAME_MATH_QUIZ) {
return;
}
bool correct = option_index == s_game.current_math.correct_index;
if (correct) {
s_game.combo++;
s_game.score += 10 + s_game.combo;
ai_tts_speak_text("回答正确,继续加油。");
} else {
s_game.combo = 0;
ai_tts_speak_text("这题不对,我们再试一题。");
}
display_game_result(correct, s_game.score);
s_game.question_index++;
/*
* 每 5 题升一级。
*/
if (s_game.question_index > 0 && s_game.question_index % 5 == 0) {
s_game.level++;
ai_tts_speak_text("恭喜升级,难度提高了。");
}
generate_math_question(s_game.level, &s_game.current_math);
display_game_question(&s_game.current_math, s_game.score, s_game.level);
}
void game_stop(void)
{
s_game.type = GAME_NONE;
ai_tts_speak_text("游戏结束,学习也要注意休息。");
/*
* TODO:
* 上传游戏成绩:
* device_id、user_id、game_type、score、level、duration。
*/
}
7.5 AT+MCP:语音控制拍题、学习和游戏
开发宝典中的 AT+MCP 非常适合做二次开发。协议使用标准 UART,默认 115200, 8N1;通过 AT+ADDMCP 可以把"人话"映射为 MCU 可执行的二进制控制帧;AI 模组还会主动上报开机、配网、联网、监听、说话、升级、激活等状态。
7.5.1 MCP 命令定义
CMD_CAPTURE_SOLVE 0xF1 拍照解题
CMD_START_GAME 0xF2 开始学习游戏
CMD_ANSWER_GAME 0xF3 回答游戏选项
CMD_SET_STUDY_MODE 0xF4 切换学习模式
CMD_SHOW_WRONG_BOOK 0xF5 查看错题本
CMD_PARENT_REPORT 0xF6 上传 / 查询学习报告
CMD_CUSTOMER_API 0xF7 接入客户系统
7.5.2 MCP 注册与解析代码
#include <stdio.h>
#include <string.h>
#include "esp_log.h"
#include "driver/uart.h"
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "board_config.h"
#define TAG "MCP"
#define FRAME_H1 0x55
#define FRAME_H2 0xAA
#define FRAME_T1 0xAA
#define FRAME_T2 0x55
#define CMD_STATUS 0xFF
#define CMD_RECOVER 0xFC
#define CMD_CAPTURE_SOLVE 0xF1
#define CMD_START_GAME 0xF2
#define CMD_ANSWER_GAME 0xF3
#define CMD_SET_STUDY_MODE 0xF4
#define CMD_SHOW_WRONG_BOOK 0xF5
#define CMD_PARENT_REPORT 0xF6
#define CMD_CUSTOMER_API 0xF7
typedef enum {
STUDY_SUBJECT_UNKNOWN = 0,
STUDY_SUBJECT_MATH = 1,
STUDY_SUBJECT_CHINESE = 2,
STUDY_SUBJECT_ENGLISH = 3,
STUDY_SUBJECT_GENERAL = 4,
} study_subject_t;
extern void study_capture_and_solve(study_subject_t subject);
extern void game_start_math_quiz(int level);
extern void game_answer_option(int option_index);
extern void wrong_book_show(void);
extern void report_upload_now(void);
extern void customer_scene_control(uint8_t scene_id, uint8_t action);
static void mcp_send_line(const char *line)
{
uart_write_bytes(AI_UART, line, strlen(line));
uart_write_bytes(AI_UART, "\r\n", 2);
ESP_LOGI(TAG, "MCU -> AI: %s", line);
}
static void ai_reset_module(void)
{
gpio_set_direction(AI_RESET_GPIO, GPIO_MODE_OUTPUT);
gpio_set_level(AI_RESET_GPIO, 0);
vTaskDelay(pdMS_TO_TICKS(300));
gpio_set_level(AI_RESET_GPIO, 1);
vTaskDelay(pdMS_TO_TICKS(1500));
}
static void mcp_register_tools(void)
{
mcp_send_line("AT");
mcp_send_line("AT+WIFICFG=0");
mcp_send_line("AT+CONNECT");
/*
* 用户:"帮我看一下这道数学题"
* AI -> MCU: 55 AA 02 F1 01 AA 55
* data[0] = subject
*/
mcp_send_line(
"AT+ADDMCP=1,capture_solve,拍照识别并讲解题目,F1,1,subject"
);
/*
* 用户:"开始口算游戏,难度二"
*/
mcp_send_line(
"AT+ADDMCP=1,start_math_game,开始口算闯关游戏,F2,1,level"
);
/*
* 用户:"我选第三个"
*/
mcp_send_line(
"AT+ADDMCP=1,answer_game,回答当前游戏选项,F3,1,option"
);
/*
* 用户:"切换到英语学习模式"
*/
mcp_send_line(
"AT+ADDMCP=1,set_study_mode,切换学习科目模式,F4,1,subject"
);
/*
* 用户:"查看我的错题本"
*/
mcp_send_line(
"AT+ADDMCP=0,show_wrong_book,查看错题本,2,F5,01"
);
/*
* 用户:"把今天的学习报告发给家长"
*/
mcp_send_line(
"AT+ADDMCP=0,parent_report,上传或查询学习报告,2,F6,01"
);
/*
* 用户:"打开客户平台的一号课程"
*/
mcp_send_line(
"AT+ADDMCP=1,customer_api,调用客户学习平台接口,F7,2,scene_id,action"
);
}
static void handle_ai_status(uint8_t status)
{
switch (status) {
case 0x01:
ESP_LOGI(TAG, "AI starting");
break;
case 0x02:
ESP_LOGI(TAG, "AI configuring");
break;
case 0x03:
ESP_LOGI(TAG, "AI idle");
break;
case 0x04:
ESP_LOGI(TAG, "AI connecting");
break;
case 0x05:
ESP_LOGI(TAG, "AI listening");
break;
case 0x06:
ESP_LOGI(TAG, "AI speaking");
break;
case 0x07:
ESP_LOGI(TAG, "AI upgrading");
break;
case 0x08:
ESP_LOGI(TAG, "AI activating");
break;
default:
ESP_LOGW(TAG, "unknown AI status=0x%02X", status);
break;
}
}
static void mcp_handle_frame(uint8_t cmd, const uint8_t *data, uint8_t len)
{
if (cmd == CMD_RECOVER) {
/*
* 开发宝典要求:
* 收到 55 AA 01 FC AA 55 后,MCU 重启 AI 模组并重新发送 MCP 映射。
*/
ai_reset_module();
mcp_register_tools();
return;
}
if (cmd == CMD_STATUS && len >= 1) {
handle_ai_status(data[0]);
return;
}
switch (cmd) {
case CMD_CAPTURE_SOLVE:
if (len >= 1) {
study_capture_and_solve((study_subject_t)data[0]);
} else {
study_capture_and_solve(STUDY_SUBJECT_UNKNOWN);
}
break;
case CMD_START_GAME:
if (len >= 1) {
game_start_math_quiz(data[0]);
} else {
game_start_math_quiz(1);
}
break;
case CMD_ANSWER_GAME:
if (len >= 1) {
/*
* 语音传 1~4,内部转 0~3。
*/
int option = data[0] > 0 ? data[0] - 1 : 0;
game_answer_option(option);
}
break;
case CMD_SET_STUDY_MODE:
if (len >= 1) {
ESP_LOGI(TAG, "set study mode=%u", data[0]);
/*
* TODO:
* study_set_subject(data[0]);
* display_show_subject(data[0]);
*/
}
break;
case CMD_SHOW_WRONG_BOOK:
wrong_book_show();
break;
case CMD_PARENT_REPORT:
report_upload_now();
break;
case CMD_CUSTOMER_API:
if (len >= 2) {
customer_scene_control(data[0], data[1]);
}
break;
default:
ESP_LOGW(TAG, "unknown MCP cmd=0x%02X len=%u", cmd, len);
break;
}
}
static void mcp_rx_task(void *arg)
{
uint8_t frame[160];
uint8_t pos = 0;
int expected = -1;
while (1) {
uint8_t b = 0;
int n = uart_read_bytes(AI_UART, &b, 1, pdMS_TO_TICKS(100));
if (n <= 0) {
continue;
}
if (pos == 0 && b != FRAME_H1) {
continue;
}
if (pos == 1 && b != FRAME_H2) {
pos = 0;
expected = -1;
continue;
}
frame[pos++] = b;
if (pos == 3) {
uint8_t len = frame[2];
if (len == 0 || len > 150) {
pos = 0;
expected = -1;
continue;
}
expected = 2 + 1 + len + 2;
}
if (expected > 0 && pos >= expected) {
uint8_t len = frame[2];
if (frame[3 + len] == FRAME_T1 &&
frame[4 + len] == FRAME_T2) {
uint8_t cmd = frame[3];
const uint8_t *data = &frame[4];
uint8_t data_len = len - 1;
mcp_handle_frame(cmd, data, data_len);
}
pos = 0;
expected = -1;
}
}
}
void mcp_uart_bridge_start(void)
{
uart_config_t cfg = {
.baud_rate = AI_UART_BAUD,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_DEFAULT,
};
uart_driver_install(AI_UART, 2048, 2048, 0, NULL, 0);
uart_param_config(AI_UART, &cfg);
uart_set_pin(
AI_UART,
AI_UART_TX_GPIO,
AI_UART_RX_GPIO,
UART_PIN_NO_CHANGE,
UART_PIN_NO_CHANGE
);
ai_reset_module();
mcp_register_tools();
xTaskCreate(mcp_rx_task, "mcp_rx", 4096, NULL, 10, NULL);
}
7.6 远程管理:设备影子与学习报告
设备状态 JSON
{
"device_id": "study_camera_001",
"fw_version": "1.0.0",
"wifi_rssi": -55,
"battery": 82,
"ai_state": "idle",
"camera_ready": true,
"study_mode": "math",
"today": {
"study_minutes": 35,
"questions": 18,
"correct": 15,
"wrong": 3,
"game_score": 260
}
}
上报代码
#include <stdio.h>
#include "esp_log.h"
#define TAG "STUDY_REPORT"
typedef struct {
int study_minutes;
int questions;
int correct;
int wrong;
int game_score;
} study_daily_report_t;
static void mqtt_publish(const char *topic, const char *payload)
{
/*
* TODO:
* esp_mqtt_client_publish(client, topic, payload, 0, 1, 0);
*/
ESP_LOGI(TAG, "MQTT %s => %s", topic, payload);
}
void report_upload_daily(const study_daily_report_t *r)
{
char payload[512];
snprintf(payload, sizeof(payload),
"{"
"\"device_id\":\"study_camera_001\","
"\"study_minutes\":%d,"
"\"questions\":%d,"
"\"correct\":%d,"
"\"wrong\":%d,"
"\"game_score\":%d"
"}",
r->study_minutes,
r->questions,
r->correct,
r->wrong,
r->game_score
);
mqtt_publish("sibo/study_camera/study_camera_001/report/daily", payload);
}
void report_upload_now(void)
{
study_daily_report_t report = {
.study_minutes = 35,
.questions = 18,
.correct = 15,
.wrong = 3,
.game_score = 260,
};
report_upload_daily(&report);
}
7.7 客户系统接入示例
客户可以把拍学机接入自己的教育平台、题库平台、家长端 APP 或小程序。
#include <stdio.h>
#include <string.h>
#include "esp_http_client.h"
#include "esp_log.h"
#define TAG "CUSTOMER_API"
esp_err_t customer_scene_control(uint8_t scene_id, uint8_t action)
{
char body[128];
snprintf(body, sizeof(body),
"{\"device_id\":\"study_camera_001\",\"scene_id\":%u,\"action\":%u}",
scene_id,
action);
esp_http_client_config_t config = {
.url = "https://customer.example.com/api/v1/device/scene",
.method = HTTP_METHOD_POST,
.timeout_ms = 8000,
};
esp_http_client_handle_t client = esp_http_client_init(&config);
esp_http_client_set_header(client, "Content-Type", "application/json");
esp_http_client_set_header(client, "Authorization", "Bearer ${token}");
esp_http_client_set_post_field(client, body, strlen(body));
esp_err_t err = esp_http_client_perform(client);
int status = esp_http_client_get_status_code(client);
ESP_LOGI(TAG, "customer api status=%d err=%s",
status, esp_err_to_name(err));
esp_http_client_cleanup(client);
return err;
}
8. 后端服务设计
建议后端拆成以下服务:
1. AI WebSocket Gateway:
负责设备端语音对话、ASR、LLM、TTS。
2. OCR / VLM Service:
负责拍题识别、绘本识别、看图问答。
3. Study Engine:
负责错题本、学习计划、知识点推荐、题库匹配。
4. Game Service:
负责游戏题库、排行榜、成长积分、奖励策略。
5. Parent Admin:
家长端管理、学习报告、设备限制、内容管控。
6. OTA Service:
固件 OTA、资源 OTA、灰度升级。
7. Device Management:
设备绑定、设备影子、日志、远程诊断。
8. Customer API Gateway:
对接客户教育平台、App、小程序、私有化系统。
开发宝典中说明,设备默认可连接小智官方服务,也可以运行开源后端服务,让设备连接到自己的后端;后端包含 OTA 接口和 WebSocket 接口,并可配置 LLM、TTS、人设等参数。
后端配置示例:
server:
websocket_url: "wss://ai.customer.com/xiaozhi/v1/"
ota_url: "https://ai.customer.com/xiaozhi/ota/"
mqtt_uri: "mqtts://mqtt.customer.com"
ai:
ASR: "FunASR"
LLM: "CustomerLLM"
TTS: "DoubaoTTS"
VLM: "CustomerVisionModel"
Intent: "function_call"
study:
ocr_url: "https://api.customer.com/v1/ocr"
solve_url: "https://api.customer.com/v1/study/solve"
wrong_book_enable: true
parent_report_enable: true
game:
local_game_enable: true
cloud_rank_enable: false
daily_task_enable: true
9. OTA 与资源管理
推荐 16MB Flash 分区:
# 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, 0x300000
ota_0, app, ota_0, 0x320000, 0x300000
ota_1, app, ota_1, 0x620000, 0x300000
storage, data, fat, 0x920000, 0x500000
coredump, data, coredump,0xE20000, 0x100000
资源管理建议:
storage/
prompt/ 提示音
avatar/ AI 形象素材
game/ 本地游戏资源
study/ 本地题库 / 单词表
cache/ TTS 缓存
log/ 日志
OTA 策略:
1. 主控固件 OTA:
ESP32-S3 双 OTA 分区,失败回滚。
2. 资源 OTA:
游戏题库、提示音、表情动画、单词表单独更新。
3. AI 参数 OTA:
大模型地址、人设、TTS 音色、学习策略远程下发。
4. 灰度升级:
按 project_id / batch_id / device_id 分批升级。
5. 安全:
HTTPS OTA + 固件签名 + token 鉴权。
10. 产测方案
10.1 工厂测试项目
主控:
- ESP32-S3 Flash / PSRAM 检测
- Wi-Fi MAC / BLE MAC
- NVS SN 写入
- 固件版本读取
语音:
- VB6824 UART 通信
- 麦克风电平
- 喇叭播放
- 唤醒词测试
- 播放中打断测试
摄像头:
- 摄像头初始化
- 拍照 JPEG 大小检测
- 图像方向检测
- 亮度检测
- 后端上传测试
屏幕:
- 白屏 / 黑屏 / RGB 纯色
- 背光 PWM
- 学习 UI 显示
- 游戏 UI 显示
学习:
- 拍题上传
- OCR 返回
- 题目讲解
- 错题本写入
游戏:
- 按键输入
- 题目生成
- 计分逻辑
- 音效播放
远程:
- MQTT 连接
- 学习报告上报
- OTA 检查
- 日志上传
10.2 产测命令建议
FACTORY ENTER
FACTORY SET_SN=SBOSTUDY20260001
FACTORY WIFI_SCAN
FACTORY WIFI_CONNECT=ssid,password
FACTORY MIC_LEVEL
FACTORY SPK_PLAY=1000HZ
FACTORY WAKE_TEST
FACTORY CAMERA_CAPTURE
FACTORY OCR_TEST
FACTORY LCD_TEST
FACTORY GAME_TEST
FACTORY MQTT_CONNECT
FACTORY REPORT_UPLOAD
FACTORY OTA_CHECK
FACTORY EXIT
11. 推荐产品版本
11.1 基础 AI 学习音箱版
ESP32-S3R8 + 16M Flash
VB6824
麦克风 + 喇叭
1.54 寸屏
Wi-Fi + BLE BluFi
AI 问答
故事机
口算游戏
远程 OTA
适合:AI 故事机、儿童学习音箱、桌面陪伴设备。
11.2 AI 智能拍学机标准版
ESP32-S3R8 + 16M Flash + 8M PSRAM
VB6824
摄像头
2.0 寸屏
麦克风 + 喇叭
电池
Wi-Fi
拍题识别
OCR / VLM
学习游戏
错题本
家长端报告
适合:儿童拍题机、学习机、教育硬件、绘本助手。
11.3 高端多模态游戏学习版
ESP32-S3R8 + 16M Flash + 8M PSRAM
VB6824
摄像头
2.0 / 4.75 寸高清屏
触摸 / 按键
SD 卡
4G 选配
7014 蓝牙 PAN 选配
AI 对话
拍题讲解
绘本识别
学习游戏
声音克隆
知识库
MCP 工具
客户私有后端
适合:品牌 B 端客户、教育机构、方案商客户、海外 AI 学习产品。
12. 方案总结
四博 AI 智能拍学机建议采用 ESP32-S3R8 + 16M Flash + 8M PSRAM + VB6824 + 摄像头 + 屏幕 + 麦克风 + 喇叭 的平台化架构。
ESP32-S3 负责摄像头、屏幕、联网、AI WebSocket、学习游戏、远程管理和客户系统接入;VB6824 负责离线唤醒、AEC、降噪、语音唤醒、改唤醒词和打断;摄像头负责拍题、绘本识别和看图问答;屏幕负责题目步骤、游戏界面和学习反馈;后端负责 OCR、VLM、大模型讲解、错题本、家长报告和 OTA。
这套方案既可以做 AI 智能音箱 ,也可以升级成 AI 拍学机、AI 学习机、AI 游戏学习终端、AI 绘本助手,并且支持 ESP-IDF、DOIT_AI、AT+MCP、HTTP、MQTT、WebSocket 等多种二次开发路径,适合客户快速打样、定制和量产。