基于 ESP-IDF 的桌面机器人固件,不依赖任何中转服务器,ESP32 直接调用云 API 完成 完整的语音对话闭环:
唤醒词 → 采集音频(16k) → ASR(WebSocket) → LLM(SSE) → TTS(WebSocket) → 播放(24k→16k)
- ASR:Qwen3-ASR-Flash-Realtime(DashScope Omni Realtime WebSocket,服务端 VAD 断句)
- TTS:Qwen-Audio-TTS(DashScope 单向流式 WebSocket,支持情感/富语言标签)
- LLM:任意 OpenAI 兼容接口(支持
base_url,自动禁用思考) - 多 Board:完整保留 RIG-Omni 的 boards 架构(arm / puppy / hover), 运动控制(xgo、xgo_action、ik、idle_motion)等实现全部保留
main/
├── application.cc # 应用主流程(唤醒、按键、状态机、显示)
├── cloud_api/ # ★ 直连云 API 模块(本项目新增)
│ ├── cloud_config.h # NVS("cloud") + Kconfig 配置读取
│ ├── asr_client.cc/h # Qwen3-ASR-Flash-Realtime WebSocket 客户端
│ ├── tts_client.cc/h # Qwen-Audio-TTS 流式 WebSocket 客户端
│ ├── llm_client.cc/h # OpenAI 兼容 SSE 客户端(禁思考)
│ ├── text_processor.cc/h # 情感/富语言标签解析、分句、文本清洗
│ └── cloud_api_protocol.cc/h # 对话编排器(状态机 + 音频编解码)
├── boards/ # 多板支持(arm/puppy/hover + common)
│ └── <board>/xgo.cc # 运动控制实现(保留)
└── protocol/ # 协议基类 Protocol(CloudApiProtocol 继承)
固件只有直连模式这一条协议路径:初始化 CloudApiProtocol,跳过 OTA 版本检查,
唤醒/按键后直接开始对话。服务端 MQTT/WebSocket 协议已移除。
三种方式(优先级从高到低):
- 网页配置(推荐):设备连上 WiFi 后访问
http://<设备IP>/, 在设置页填入 key 后保存,写入 NVScloud命名空间(掉电保留) - Kconfig 编译默认值:
idf.py menuconfig→Cloud API Direct Mode (BYOK)菜单 - 只填编译默认值即可出厂的固件
idf.py set-target esp32s3 # 按你的芯片选择
idf.py menuconfig # → Board Options → 选择 Board Type (puppy/arm/hover)各板型的 board_config.h、config.json(表情布局)与运动控制实现均已保留。
source $IDF_PATH/export.sh # 或 source ~/esp/esp-idf-v5.5/export.sh
idf.py build
idf.py -p /dev/cu.usbmodem* flash monitor| 配置 | 默认值 | 说明 |
|---|---|---|
CLOUD_API_ASR_API_KEY |
"" | ASR key(DashScope) |
CLOUD_API_ASR_MODEL |
qwen3-asr-flash-realtime | ASR 模型 |
CLOUD_API_TTS_API_KEY |
"" | TTS key(DashScope) |
CLOUD_API_TTS_MODEL |
qwen-audio-3.0-tts-plus | TTS 模型 |
CLOUD_API_TTS_VOICE |
Cherry | TTS 音色 |
CLOUD_API_LLM_API_KEY |
"" | LLM key |
CLOUD_API_LLM_BASE_URL |
https://dashscope.aliyuncs.com/compatible-mode/v1 | OpenAI 兼容 base_url |
CLOUD_API_LLM_MODEL |
qwen-plus | LLM 模型 |
CLOUD_API_LANGUAGE |
zh | ASR 语言 |
CLOUD_API_SYSTEM_PROMPT |
小鹿人设 | 系统提示词 |
| 键 | 类型 | 默认值 | 说明 |
|---|---|---|---|
asr_api_key |
string | Kconfig | ASR key |
asr_model |
string | qwen3-asr-flash-realtime | ASR 模型 |
tts_api_key |
string | Kconfig | TTS key |
tts_model |
string | qwen-audio-3.0-tts-plus | TTS 模型 |
tts_voice |
string | Cherry | TTS 音色 |
llm_api_key |
string | Kconfig | LLM key |
llm_base_url |
string | Kconfig | OpenAI 兼容 base_url(如 https://api.openai.com/v1) |
llm_model |
string | qwen-plus | LLM 模型 |
language |
string | zh | ASR 语言 |
system_prompt |
string | 小鹿人设 | 系统提示词 |
vad_threshold |
float | 0.2 | 服务端 VAD 灵敏度(0~1,越小越灵敏) |
silence_duration_ms |
int | 800 | 服务端断句静音时长(ms) |
max_history |
int | 10 | LLM 多轮记忆轮数 |
- 唤醒(默认唤醒词"小鹿同学",或按键)→ 打开音频通道,连接 ASR
- 上行音频(16k PCM,base64)持续发送,服务端 VAD 检测到停顿 →
返回
transcription.completed最终识别文本 - 断开 LLM 上的旧请求 → 携带历史发起新请求(SSE 流式,
enable_thinking:false) - 收到完整回复 → 文本清洗(去代码块/链接/markdown)→ 按句切分 → 发送 TTS(情感标签解析后整段合成)→ 音频流式播放
- 打断:说话/按键打断 → 取消 LLM、停止 TTS 播放,回到听状态
- 连续对话:TTS 播完自动回到听状态,可直接说下一句; 手动模式(按键触发)播完关闭通道
lukaka-server 或设备自带的 WiFi 配置页均可写入 NVS cloud 命名空间。
配置保存后重启设备生效(CloudConfig 在启动时读取一次)。
不装任何工具,浏览器即可烧录固件并写入全部配置(WiFi / LLM / ASR / TTS):
- 部署
flash-web(Flask 服务,HTTPS 访问) - 浏览器打开烧录页 → 填 WiFi、API Key 等 → 点"连接设备并烧录"
- 网页把配置生成 NVS 分区镜像,与 bootloader / 分区表 / 固件 / 动画资源 一次性写入,完成后设备自动重启连 WiFi
NVS 分区布局与 partitions/16m.csv 一致(nvs @ 0x9000),命名空间:
wifi:ssid/password(SsidManager 读取,支持 ssid1~9 多组)cloud:全部云 API 配置(下表,CloudConfig启动时读取)
新增配置项时注意:NVS key 最长 15 字符(如 silence_duration_ms 需简写为 silence_ms);
数字用 i32 类型、字符串用 string 类型,与 nvs_get_i32 / nvs_get_str 对应。
- ASR / TTS 使用 DashScope
wss://dashscope.aliyuncs.com,需要能访问外网 - LLM 可指向任意 OpenAI 兼容服务(含本地 vLLM/Ollama 等),请求体带
enable_thinking:false与thinking:{"type":"disabled"}禁用思考输出 - TTS 输出 24k PCM,固件内部重采样为 16k 后按 60ms 帧 Opus 编码播放
- 直连模式跳过 OTA 版本检查(避免默认 OTA URL 的空请求与重试耗时)