HARDWARE DESIGN SPEC
多拉丁 Duolading · 设计书
一台轮式桌面 AI 机器人:屏幕当脸、麦克风当耳、按键当嘴、摄像头当眼、轮子当腿。
树莓派 3B 当身体,PC 当算力坞,3D 打印当骨架,全锡焊装配。
版本 v0.1(草稿)
预算 ¥200
平台 Raspberry Pi 3B
装配 锡焊 / 无面包板
状态 待轩轩验收
看不太懂技术细节?先看人话版:《多拉丁 · 从大类开始》 —— 只讲"买哪几大类、能不能连、怎么控制",带图标清单、接线地图和可旋转的 3D 布局构想图。本页是它下面的技术设计书。
0 · 文档信息
| 项 | 值 |
|---|---|
| 项目名 | 多拉丁(Duolading)—— 巴拉丁的硬件姊妹机 |
| 文档类型 | 硬件 / 系统设计书(Design Spec),非进度台账 |
| 版本 | v0.1 草稿(讨论稿,未定版) |
| 部署位置 | https://docs.monefortress.com/duolading/ |
| 源文件 | 本机 docs-site/duolading/index.html |
| 项目登记 | 尚未登记进 PROJECTS.yaml(需先立项) |
| 验收口径 | 本设计书尚未由轩轩验收,所有数值为设计目标而非实测 |
证据分级声明:本文中的性能、帧率、价格均为估算值,标注「需自测」的项目必须在真机上实测后才能当作结论。任何写着「可用 / 完成」的说法,以轩轩手测为准。
1 · 项目定位
1.1 一句话
做一台能看、能听、能说、能走、能上台面的桌面伙伴,而不是一台实验板。
1.2 与巴拉丁的关系
| 项 | 巴拉丁 Balading | 多拉丁 Duolading |
|---|---|---|
| 形态 | 手机上的 App(DSH 手机端) | 桌上的轮式机器人 |
| 角色 | 随身的大脑入口 | 有身体的伙伴 |
| 共同点 | 都接同一套 DSH 大脑 / 同一个算力坞;命名、协议、记忆体系对齐 | |
1.3 四条设计原则(不可妥协)
① 不用面包板与杜邦线飞线所有连接走焊接:HAT 原型板点对点焊 → 定版自制 PCB。线束进端子台与热缩管。
② 身体与大脑分离身体只暴露一组 API;AI、行为、语音都调 API,不碰 GPIO 细节。硬件换三代,上层不改。
③ 先验证最不确定的部分阶段 0 零成本验证「AI 能不能跑起来」,再花钱买动力件。
④ 结构件全部可打印底盘、支架、面板、外壳走 3D 打印;买的只有标准件与电子模块。
2 · 需求与范围
2.1 用户故事
- 我按下它头上的说话键,说「往前一点」,它看着我、答一句话,然后真的向前走 20 厘米。
- 我把它放在桌上,它待机时会左右张望、眨眼、打盹;我在键盘上敲字,它脸上的表情变。
- 它往前走遇到桌沿或障碍会自己停,不会掉下去。
- 换电池或者插充电宝都能用,不能因为切电源把它重启了。
2.2 MVP 范围(第一版必须有)
| # | 能力 | 验收口径 |
|---|---|---|
| M1 | 屏幕显示表情与状态 | 上电后屏幕上出现眼睛,随状态变化(非静态图) |
| M2 | 按键录音 + 播放语音 | 按住说话键说一句,松开后 5 秒内它出声回答 |
| M3 | 两轮移动 | 键盘/网页遥操作,前进后退原地转,走直线不跑偏超过 15 度/米 |
| M4 | 前方测距与自动停 | 障碍物 20 厘米内自动停止 |
| M5 | 双电源切换不重启 | 充电宝与电池互相切换时 Pi 不掉电重启 |
2.3 明确的非目标(这一版不做)
- 不做双足 / 平衡机器人——microduck 类形态是具身智能课题,不是本项目目标。
- 不做本地大模型推理——Pi 3B 没有 NPU、只有 1GB 内存,本地 LLM 不可行。
- 不做机械臂 / 抓取。
- 不做语音唤醒词——第一版一律按键触发(push-to-talk),唤醒词留到第二版。
- 不把机器人暴露到公网——只在局域网内通信。
3 · 系统架构
3.1 三层架构
┌──────────────────────────────┐ ┌───────────────────────────────┐
│ 身体 · 多拉丁(Pi 3B) │ │ 算力坞 · PC(Windows) │
│ │ 局域网 │ │
│ · 屏幕(脸) │WebSocket│ · Whisper(语音转文字) │
│ · 麦克风 / 按键(耳与嘴) │◄──────►│ · DSH / LLM(决策与人格) │
│ · 摄像头(眼) │ JSON │ · edge-tts(文字转语音) │
│ · 电机 + 轮子(腿) │ │ · 行为策略 / 记忆 │
│ · 超声波 / IMU(触觉) │ │ · 网页式遥操作台 │
│ │ │ │
│ 只做「执行 + 感知」 │ │ 只做「思考 + 说话」 │
└──────────────────────────────┘ └───────────────────────────────┘
可选上行:云端 API(仅当 PC 不在线时的降级方案)
为什么这样分:Pi 3B 跑不动语音识别与大模型,但它天生适合做「实时控制 + 传感器采集」。把重活放到局域网内的 PC 上,延迟只有毫秒级,比调云 API 快一个数量级,而且零费用、可离线。
3.2 数据流
| 方向 | 路径 | 时延目标 |
|---|---|---|
| 上行 身体 → 大脑 | 按键事件 / 录音音频 / 测距 / 姿态 / 电量 | 事件 < 20ms;音频块流式 |
| 下行 大脑 → 身体 | 动作指令 / 说话文本 / 表情切换 | 指令 < 50ms |
| 闭环 一次对话 | 按键 → 录音 → ASR → LLM → TTS → 出声 | 端到端 2–5 秒(局域网) |
3.3 分层边界(谁能碰 GPIO)
- 只有 Pi 上的
body服务碰 GPIO / SPI / ALSA。 - PC 上的任何代码(含 DSH)只能调 body 的 API,不许 SSH 进去直接点灯。
- 这条边界保证:换板子(3B → Pi 5 → Jetson)时,上层一行不改。
4 · 硬件设计
4.1 树莓派 3B 能力边界(先认清手里的牌)
| 能做好 | 做不好 / 不能做 |
|---|---|
| GPIO / I2C / SPI / UART 实时控制 | 本地大模型推理(1GB 内存、无 NPU,不可行) |
| USB 麦克风录音、ALSA 播放 | 高分辨率视频实时推理(OpenCV 只能低帧率跑小模型) |
| CSI 摄像头取流、截图 | 大内存服务(同时开桌面 + 浏览器 + 推理会 OOM) |
| 驱动 SPI 小屏(经 DMA 镜像) | 多路高速 USB 并发(4 个口共用一条 USB2 通道) |
系统选择建议:装 32 位 Raspberry Pi OS Lite,关掉桌面(除非屏幕方案需要帧缓冲)。3B 的 1GB 内存经不起折腾,能省的都省。
4.2 采购清单(第一批 · 目标 ≤ ¥200)
假设已有:树莓派 3B、TF 卡、充电宝;3D 打印机(结构件自打印)。价格为大致的电商估算,需以实际下单为准。
| # | 物料 | 规格 / 备注 | 估算 |
|---|---|---|---|
| 1 | SPI TFT 屏 | 2.8 寸 ILI9341 320×240(带触摸),选型理由见 4.5 | ¥33 |
| 2 | TT 双轴减速马达 ×2 + 橡胶轮 ×2 + 万向轮 ×1 | 双轴出线好焊,轮径 65mm 左右 | ¥25 |
| 3 | TB6612FNG 电机驱动模块 | 比 L298N 效率高、发热小、支持 3.3V 逻辑 | ¥9 |
| 4 | DC-DC 降压模块 5V/3A | MP1584 / MP2315 类,给 Pi 独立 5V 轨 | ¥8 |
| 5 | 树莓派 HAT 原型板 | 40 针排母 + 洞洞区,点对点焊接的载体 | ¥9 |
| 6 | 排针 / 排母 / 镀锡铜线 / 漆包线 | 焊接走线用,替代杜邦线 | ¥15 |
| 7 | KF301 螺钉端子 ×5 | 电机线、电源线全部进端子台,可拆可换 | ¥5 |
| 8 | 12mm 自复位按键 ×3 | 说话 / 模式 / 复位 | ¥4 |
| 9 | HC-SR04 超声波 + 分压电阻 | 1kΩ + 2kΩ 分压,保护 3.3V 引脚 | ¥7 |
| 10 | USB 免驱麦克风 | UAC 免驱,插上即识别 | ¥25 |
| 11 | M3 铜柱螺丝套装 + 热缩管 | 固定打印件 | ¥15 |
| 12 | 焊锡丝 / 助焊剂 / 吸锡带 | 如已有可省 | ¥15 |
| 13 | 嘉立创 PCB 打样(定版用) | 5 片摊薄,第二版才需要 | ¥15 |
| 合计 | ≈ ¥185 | ||
不含摄像头(阶段 0 先用旧件)、音箱(用旧耳机)、电池(先用充电宝)。这几项进第二批。
第二批(后续再加)
| 物料 | 说明 | 估算 |
|---|---|---|
| 18650 ×2 + 电池盒 + 2S 保护板 + 8.4V 充电器 | 脱离充电宝的自主供电,见 4.3 | ¥70 |
| USB 摄像头 / CSI Camera Module | 眼睛 | ¥25–50 |
| 3.5mm 小音箱 | 旧耳机 / 旧蓝牙音箱可 0 元 | ¥20 |
| SG90 云台舵机 ×2 | 摄像头转头,必须独立 5V 供电 | ¥20 |
4.3 供电架构
铁律:电机与树莓派绝不共用一路 5V。电机启动瞬间的电流冲击会把 5V 拉塌,现象是「小车一动就黑屏重启」——大多数人会误以为是代码 bug。
阶段 A(MVP):充电宝供电
充电宝 5V/2A+ ──┬──► Pi 3B(USB 口,或焊到板上的 5V 端子)
│
└──► TB6612 VM(电机低速可用 5V,扭矩偏小)
结论:零成本、能跑通,先用它把软件闭环做完。
阶段 B(扩展):2S 电池 + 双路自动切换
┌── 充电宝 5V ───────────────┐
│ ▼
│ [理想二极管 OR] ──► 5V 轨 ──► Pi 3B
2S 18650 ──► DC-DC 5V/3A ────────────┘ │
(7.4V) │ └── 1000µF 电容(抗瞬时掉压)
└──► TB6612 VM(7.4V 直供,扭矩充足)──► 电机
充电:2S 保护板 + 8.4V 充电器,或直接买带 BMS 的成品电池组。
| 方案 | 优点 | 缺点 |
|---|---|---|
| 理想二极管 OR 模块 | 切换不断电,压降仅几十 mV | 多花 ¥10 左右 |
| 肖特基二极管 OR(SS34) | 便宜、随便焊 | 压降 0.3–0.4V,Pi 会报欠压警告 |
| 机械开关切换 | 最简单 | 切换瞬间掉电 → Pi 重启,不推荐 |
4.4 引脚分配表(定版,禁止随意改动)
本表是焊接与 PCB 布线的唯一依据。改动前必须先改本表,再改板子。
| 物理脚 | GPIO | 功能 | 去向 |
|---|---|---|---|
| 1 / 17 | 3V3 | 电源 | 传感器逻辑、分压上端 |
| 2 / 4 | 5V | 电源 | 独立 5V 轨输入 |
| 3 | GPIO2 | I2C1 SDA | IMU / ToF(预留) |
| 5 | GPIO3 | I2C1 SCL | IMU / ToF(预留) |
| 7 | GPIO4 | KEY_TALK | 说话键(按下录音) |
| 11 | GPIO17 | KEY_MODE | 模式键(跟随 / 巡逻 / 待机) |
| 13 | GPIO27 | KEY_RESET | 复位键(重启 body 服务) |
| 12 | GPIO18 | LCD_BL | 屏幕背光,PWM 调亮度 |
| 16 | GPIO23 | SONAR_TRIG | 超声波触发 |
| 18 | GPIO24 | LCD_RST | 屏幕复位 |
| 19 | GPIO10 | SPI0 MOSI | 屏幕数据 |
| 21 | GPIO9 | SPI0 MISO | 屏幕读回 / 触摸数据 |
| 22 | GPIO25 | LCD_DC | 屏幕 数据 / 命令 选择 |
| 23 | GPIO11 | SPI0 SCLK | 屏幕时钟 |
| 24 | GPIO8 | SPI0 CE0 | 屏幕片选 |
| 26 | GPIO7 | SPI0 CE1 | 触摸片选 |
| 29 | GPIO5 | MOTOR_AIN1 | 左轮方向 1 |
| 31 | GPIO6 | MOTOR_AIN2 | 左轮方向 2 |
| 32 | GPIO12 | MOTOR_PWMA | 左轮调速(硬件 PWM0) |
| 33 | GPIO13 | MOTOR_PWMB | 右轮调速(硬件 PWM1) |
| 35 | GPIO19 | TOUCH_IRQ | 触摸中断(可选) |
| 36 | GPIO16 | MOTOR_BIN1 | 右轮方向 1 |
| 37 | GPIO26 | MOTOR_BIN2 | 右轮方向 2 |
| 38 | GPIO20 | MOTOR_STBY | 驱动使能(拉低即停) |
| 40 | GPIO21 | SONAR_ECHO | 超声波回波(须分压) |
| 8 / 10 | GPIO14 / 15 | UART | 调试串口,保留 |
| 6,9,14,20,25,30,34,39 | GND | 地 | 公共地,必须与电池负极共地 |
硬件 PWM 的正确开法:默认的
dtoverlay=pwm-2chan 会占用 GPIO18 / GPIO19,与本表的背光和触摸中断冲突。必须显式指定引脚:dtoverlay=pwm-2chan,pin=12,func=4,pin2=13,func2=4HC-SR04 警告:它的 ECHO 输出是 5V 电平,直连 GPIO 会永久损坏引脚。必须用 1kΩ / 2kΩ 分压到 3.3V。想省事就换 I2C 的 VL53L0X(3.3V 原生,测距更准)。
4.5 屏幕子系统(STM32 那种 SPI 屏怎么接到 Pi 上)
选型
| 型号 | 分辨率 | 驱动成熟度 | 建议 |
|---|---|---|---|
| ILI9341(2.4 / 2.8 寸) | 320×240 | 最好 | 首选:便宜、资料多、帧率最高 |
| ST7789(1.3–2.0 寸) | 240×240 / 320×240 | 好 | 想要小圆脸可选 |
| ILI9486(3.5 寸) | 480×320 | 中 | 想要大脸可选,帧率减半 |
| ILI9488(3.5 寸) | 480×320 | 偏弱 | 不推荐首选,驱动踩坑多 |
驱动路线
| 路线 | 原理 | 帧率(3B,需自测) | 评价 |
|---|---|---|---|
| fbcp-ili9341 | 用户态直接写 SPI,把 HDMI 帧缓冲镜像到小屏 | 320×240 约 40–60fps | 推荐:快、不动内核、不用 overlay |
| 内核 fbtft overlay | 内核把屏注册成 /dev/fb1 | 约 5–15fps | 简单但卡,表情动画勉强 |
| luma.lcd(Python) | Python 直接画 | 更低 | 适合静态信息,不适合动画 |
路线 A 的妙处:用 fbcp-ili9341 时,Pi 照常输出 HDMI 帧缓冲,屏幕只是「镜子」。也就是说你的 UI 可以用任何东西画——pygame、Qt、甚至浏览器 kiosk 渲染到 HDMI,然后原封不动出现在小屏上。把 HDMI 分辨率设成和屏幕一致(320×240)效果最好。
路线 B:不占 GPIO 的替代(零成本)
用旧手机 / 旧平板当脸:Pi 起一个本地网页服务,手机浏览器全屏打开就是机器人的表情屏。优点是不占一根 GPIO、分辨率高、还能顺手放视频;缺点是多了个设备和一根充电线。建议:阶段 0 先用路线 B 把 AI 闭环跑通,屏幕到货再切路线 A。
4.6 焊接与装配工艺(三条路线)
| 路线 | 做法 | 周期 | 适用 |
|---|---|---|---|
| ① HAT 原型板点对点焊 | 40 针排母焊到原型板上,TB6612、降压模块、端子台全部焊上去,用漆包线 / 镀锡铜线走线 | 1 天 | 第一版就用这个:验证引脚表 |
| ② 自制 PCB(嘉立创打样) | 按 4.4 引脚表画 HAT 尺寸(65×56.5mm)的板,模块做成排母座插焊,走线全在铜箔上 | 2–3 周(含打样) | 引脚验证无误后定版,最干净 |
| ③ 买成品 Robot HAT | 直接扣在 40 针上,只焊排针和端子 | 当天 | 省事,但引脚被厂商定死,和 SPI 屏可能抢针 |
焊接规范
- 烙铁 320–350℃,0.8mm 锡丝配助焊剂。
- 模块先焊电源脚和大电容 / 端子台,再焊信号线,避免返工时烫坏模块。
- 所有对外线(电机、电源、传感器)进 KF301 螺钉端子,可拆可换,不直接焊死在板上。
- 线束用热缩管 + 扎带固定;电机线双绞,减少对信号的干扰。
- 焊完先用万用表蜂鸣档逐个量:5V 对 GND 不能短路,确认后再上电。
4.7 机械结构与 3D 打印件
| 件号 | 零件 | 要点 |
|---|---|---|
| P1 | 下层底盘 | 两侧电机支架孔位按实购马达测绘;前部万向轮;留走线孔 |
| P2 | 上层电子托板 | Pi 的 4 个 M2.5 孔 + HAT 柱位;电池仓 |
| P3 | 屏幕前脸支架 | 倾角 15–25°,屏幕排针朝内插排母 |
| P4 | 按键面板 | 12mm 圆孔 ×3,孔壁留 0.2mm 余量 |
| P5 | 麦克风 / 摄像头支架 | 咪头朝前上方,避免被电机噪声直吹 |
| P6 | 外壳与头部(后期) | 可参考 microduck 的萌感,但结构是轮式 |
- 材料:PLA+ 或 PETG;底盘受力件建议 PETG 或加厚壁。
- 预留 M3 热熔铜螺母孔(孔径约 4.0–4.2mm),方便反复拆装。
- 先买电机再建模,孔位以实物为准;打印公差按 0.2mm 放。
- 建模由 AI 用参数化脚本(OpenSCAD)生成,轩轩复核尺寸后打印。
5 · 软件设计
5.1 身体 API 契约(唯一对外接口)
Pi 上跑一个 body 服务,对外只暴露下面这些能力。上层(DSH、行为脚本、遥操作台)只能调它们。
| 动作 | 参数 | 返回 | 说明 |
|---|---|---|---|
move | speed: -1.0~1.0, duration_ms | ack | 前进 / 后退,到时间自动停 |
turn | rate: -1.0~1.0, duration_ms | ack | 原地转(两轮反向) |
stop | — | ack | 立即停,拉低 STBY |
speak | text, voice? | ack + 播放时长 | 文本转语音并播放 |
listen_start | max_seconds | 录音会话 id | 开麦克风(按键按下时触发) |
listen_stop | session | wav 路径 / 大小 | 停止录音并落盘 |
face | emotion, intensity | ack | 切换表情 |
distance | — | cm | 读一次超声波 |
status | — | 电量 / 温度 / 服务状态 | 健康检查 |
事件(身体主动上报)
| 事件 | 载荷 | 用途 |
|---|---|---|
button | key: talk / mode / reset,edge: down / up | 触发录音、切模式、复位 |
sonar | cm,10Hz | 避障与「有人在附近」判断 |
audio_level | rms 0~1 | 说话时屏幕做声波反馈 |
heartbeat | uptime / 电量 / CPU 温度 | 掉线检测 |
5.2 进程与目录
/opt/duolading/ ├── body/ 身体服务(Pi,唯一碰 GPIO 的地方) │ ├── server.py WebSocket / HTTP 服务 │ ├── hardware/ gpio.py motor.py sonar.py keys.py lcd.py │ ├── audio/ rec.py play.py │ └── config.yaml 引脚表、标定值 ├── face/ 表情渲染(画到帧缓冲,或提供给网页) └── recordings/ 录音落盘(可选保留最近 N 条) systemd 单元: duolading-body.service 开机自启,崩溃自动重启 duolading-fbcp.service 屏幕镜像(用路线 A 时)
| 位置 | 技术选型 | 理由 |
|---|---|---|
| Pi · 身体服务 | Python 3 + gpiozero + websockets | gpiozero 是 Pi 官方库,按键 / 电机 / 超声都有现成封装,不必手写寄存器 |
| Pi · 屏幕 | pygame 或纯帧缓冲 + fbcp-ili9341 | 表情动画本质是低分辨率画图,pygame 足够 |
| PC · 语音 | faster-whisper(本地)+ edge-tts(免费) | PC 上毫秒级出结果,零 API 费用 |
| PC · 大脑 | DSH(复用现有 Agent) | 巴拉丁与多拉丁共用同一套人格与记忆 |
5.3 语音链路(一次对话的完整时序)
轩轩 多拉丁(Pi) 算力坞(PC) │ │ │ │ 按下说话键 │ │ ├────────────────►│ KEY_TALK down │ │ 说一句话 │ arecord 16kHz 单声道 开录 │ │ │ face = listen(屏幕竖耳) │ │ 松开 │ │ ├────────────────►│ 停录 → out.wav │ │ │──── 上传音频 + listen_stop ───────►│ │ │ │ faster-whisper 识别 │ │ │ → "往前一点" │ │ │ DSH / LLM 决策 │ │ │ → 回复 + 动作意图 │ │◄─── move(speed=0.5,dur=800) ───────│ │ │◄─── face(think) / speak(text) ─────│ │ │ edge-tts 生成 mp3 并回传 │ │ 听到回答 │ aplay 播放 │ │ 它往前走 │ 电机转动 │ │◄────────────────│ │ │ │──── sonar 10Hz 持续上报 ──────────►│ │ │◄─── stop(前方 20cm 有障碍)────────│
为什么用按键而不是唤醒词:3B 上跑唤醒词要么慢要么误触发,交互不确定性高。按键是「对讲机」式交互,触发确定、可测、失败模式简单。第一版用它把整条链路跑稳,第二版再加唤醒词。
5.4 行为状态机
┌─────────┐ 上电 ┌────────┐
│ BOOT ├────────►│ IDLE │◄───────────────┐
└─────────┘ └───┬────┘ │
按键 │ 超时 60s │
┌─────────────────┼──────────────┐ │
▼ ▼ ▼ │
┌──────────┐ ┌──────────┐ ┌────────┐ │
│LISTENING │ │ MOVING │ │ SLEEP ├───┘
└────┬─────┘ └────┬─────┘ └────────┘
│ 录音结束 │ 障碍 <20cm
▼ ▼
┌──────────┐ ┌──────────┐
│ THINKING │ │ AVOID │
└────┬─────┘ └────┬─────┘
│ 收到回复 │ 障碍解除
▼ └──────► IDLE
┌──────────┐
│ SPEAKING │──── 说完 ────► IDLE
└──────────┘
| 状态 | 屏幕表情 | 电机 | 退出条件 |
|---|---|---|---|
| BOOT | 开机眨眼 | 停 | 服务就绪 |
| IDLE | 呼吸 / 随机眨眼 / 左右张望 | 停 | 按键、收到 move |
| LISTENING | 竖耳、麦克风波纹 | 停 | 松开按键或超时 |
| THINKING | 转圈 / 思考泡泡 | 停 | 收到回复或超时 15s |
| SPEAKING | 嘴部随音量开合 | 停 | 播完 |
| MOVING | 眼睛朝行进方向看 | 转 | 到时 / 收到 stop |
| AVOID | 惊讶表情 | 急停后微退 | 障碍解除 |
| SLEEP | 闭眼打盹 | 停 | 按键 |
5.5 显示子系统
| 路线 | 渲染方式 | 优点 | 代价 |
|---|---|---|---|
| A · SPI 屏(fbcp-ili9341) | 任何写到 HDMI 帧缓冲的东西,镜像到小屏 | 完全自主、无需第二台设备 | 占 GPIO、屏幕小、需调帧率 |
| B · 旧手机网页 | Pi 起 HTTP 服务,手机浏览器 kiosk 全屏 | 0 成本、分辨率高、还能播视频 | 多一台设备与一根线 |
两条路线的表情资源与状态机是同一份:定义一组表情矢量(眼睛形状、瞳孔位置、嘴型、颜色),只换渲染层。
表情清单(v0.1)
idle 待机 · blink 眨眼 · listen 竖耳 · think 思考 · speak 说话 · happy 高兴 · alert 惊讶 · sleep 打盹 · lowbat 低电量 · error 出错
复用点:巴拉丁是 Web 技术栈,多拉丁的脸如果走路线 B,可以复用同一套前端渲染能力——两边的表情系统共用一份定义。
5.6 通信协议(WebSocket + JSON)
// 大脑 → 身体
{"type":"cmd","id":12,"action":"move","params":{"speed":0.5,"duration_ms":800}}
{"type":"cmd","id":13,"action":"face","params":{"emotion":"listen"}}
{"type":"cmd","id":14,"action":"speak","params":{"text":"好,我往前走一点"}}
// 身体 → 大脑
{"type":"ack","id":12,"ok":true,"took_ms":3}
{"type":"evt","name":"button","data":{"key":"talk","edge":"down"}}
{"type":"evt","name":"sonar","data":{"cm":42.3,"ts":1730000000}}
{"type":"evt","name":"heartbeat","data":{"uptime_s":812,"cpu_temp":54.2}}
// 出错
{"type":"ack","id":12,"ok":false,"error":"motor_busy"}
- 所有指令带
id,必须有ack;超时 1s 未 ack 视为失败。 - 安全优先级:
stop与避障永远高于其它指令,可打断正在执行的动作。 - 断线重连:身体每 2s 发心跳,大脑 6s 收不到就认为掉线并降级(屏幕显示「失联」表情)。
5.7 安全与运维
- 不暴露公网:body 服务只监听局域网地址,禁止端口映射到 VPS。
- 握手令牌:WebSocket 连接需携带 token(写在 Pi 的配置文件里,不进任何仓库)。
- 看门狗:body 服务崩溃由 systemd 自动拉起;电机有独立的软超时(单次动作最长 10s,到点强制停)。
- 急停:复位键长按 3 秒 = 断电级急停(拉低 STBY)。
6 · 路线图与验收
四个阶段,每阶段都必须能当场看到结果。验收按三档证据走:自动检查 → 真实运行 → 轩轩手测;只有第三档通过才算交付。
| 阶段 | 交付物 | 花费 | 验收方式(手测) |
|---|---|---|---|
| 阶段 0 零成本打通 AI | Pi 装系统、摄像头出图、旧手机当脸、PC 端语音闭环(按键先用键盘模拟) | ¥0 | 对着麦克风说一句,屏幕表情变化并在 5 秒内出声回答 |
| 阶段 1 身体成型 | 第一批物料到货;HAT 原型板焊接;底盘打印;前进后退原地转;屏幕切到 SPI 路线 | ≈¥185 | 网页 / 键盘遥控它绕桌一圈,全程不黑屏重启;屏幕上有表情 |
| 阶段 2 五感齐全 | 按键 + 录音 + 播放接到真硬件;超声波避障;行为状态机上线 | ¥0(含在阶段 1) | 按下它头上的键说话,它回答;手挡在它前面 20cm 内它自己停 |
| 阶段 3 上台面 | 外壳与头部打印上机;云台舵机转头;双电源切换;跟随 / 巡逻行为 | ¥110–150 | 放在桌上它会看着你转头,避开桌沿,切电源不重启 |
推进顺序的理由:最不确定的两件事是「AI 链路能不能跑通」和「软件闭环体验好不好」,这两个在阶段 0 花 0 元就能验证。硬件是确定性工作,晚点买反而更准——先跑通 API,才知道到底需要几个传感器。
6.1 里程碑登记约定
每阶段完成时在本设计书对应位置与项目 PROGRESS.md 上各记一条;里程碑只有四种状态:未开始 / 进行中 / 待轩轩验收 / 已完成,「已完成」只能由轩轩验收后改写。
7 · 风险与对策
| # | 风险 | 现象 | 对策 |
|---|---|---|---|
| R1 | 电机与 Pi 共电源 | 一动就黑屏 / 重启 | 独立 5V 轨 + 1000µF 电容 + 理想二极管 OR(见 4.3) |
| R2 | SPI 屏与其它模块抢针 | 屏亮但电机不动 / 触摸失灵 | 严格按 4.4 引脚表;先 HAT 原型板验证再定版 PCB |
| R3 | HC-SR04 的 5V 回波灌进 GPIO | 引脚永久损坏 | 1k / 2k 分压;或换 I2C 的 VL53L0X |
| R4 | SG90 舵机挂 Pi 的 5V | 抖动、重启、舵机没力 | 独立 5V 供电 + 与 Pi 共地 |
| R5 | fbcp 帧率不足 | 表情动画卡顿 | 选 ILI9341 320×240;HDMI 分辨率与屏幕对齐;不行就走网页路线 |
| R6 | 3B 内存不足 | OOM、服务被杀 | 32 位 Lite 系统、关桌面、单进程负责 GPIO、不在 Pi 上跑推理 |
| R7 | 自制 PCB 首版画错 | 白等 2 周 + 打样费 | 先用 HAT 原型板点对点焊跑通,再画板 |
| R8 | TT 马达无编码器 | 走不直、里程不可测 | 第一版接受;第二版换带编码器马达或加 IMU 闭环 |
| R9 | USB 带宽与供电 | 摄像头与麦克风同时用时掉线 | 4 个 USB 口共用一条 USB2 通道;麦克风 16kHz 单声道,避免同时开高码率视频 |
| R10 | 算力坞(PC)不在线 | 它变哑巴 | 降级:屏幕显示「失联」;可选云端 API 兜底 |
8 · 参考项目
| 方向 | 项目 | 借什么 |
|---|---|---|
| 形态对照 | pollen-robotics/microduck | 看它「为什么复杂」(双足 + 舵机 + 强化学习),明确本项目的轮式简化路线 |
| 底盘与库 | SunFounder Picar-X 文档 | 「身体 API」的现成范本,中文文档全,支持 3B |
| 底盘与库 | 微雪 AlphaBot2 维基 | 低成本底盘 + 扩展板的接线参考 |
| 自动驾驶 | Donkey Car 文档 | 「AI 决策 / 电机执行」解耦的工程范式 |
| 语音助手 | 78/xiaozhi-esp32 | 小智硬件端,按键 / 唤醒 / 对话流的交互参考 |
| 语音助手 | huangjunsen0406/py-xiaozhi | Python 客户端,可直接在树莓派上跑的语音助手实现 |
| 服务端 | xinnan-tech/xiaozhi-esp32-server | ASR / TTS / LLM 编排的服务端参考 |
| 屏幕驱动 | juj/fbcp-ili9341 | SPI 屏高速镜像驱动(本设计路线 A 的核心) |
| 视觉小车 | YahboomTechnology/Raspbot-V2 | 视觉小车套件开源代码(其目标平台是 Pi 5) |
9 · 附录
附录 A · 40 针速查
脚 1 3V3 脚 2 5V 脚 3 GPIO2 SDA 脚 4 5V 脚 5 GPIO3 SCL 脚 6 GND 脚 7 GPIO4 TALK 脚 8 GPIO14 TXD 脚 9 GND 脚 10 GPIO15 RXD 脚 11 GPIO17 MODE 脚 12 GPIO18 LCD_BL 脚 13 GPIO27 RESET 脚 14 GND 脚 15 GPIO22 (空) 脚 16 GPIO23 SONAR_TRIG 脚 17 3V3 脚 18 GPIO24 LCD_RST 脚 19 GPIO10 MOSI 脚 20 GND 脚 21 GPIO9 MISO 脚 22 GPIO25 LCD_DC 脚 23 GPIO11 SCLK 脚 24 GPIO8 LCD_CS 脚 25 GND 脚 26 GPIO7 TOUCH_CS 脚 27 GPIO0 脚 28 GPIO1 脚 29 GPIO5 AIN1 脚 30 GND 脚 31 GPIO6 AIN2 脚 32 GPIO12 PWMA 脚 33 GPIO13 PWMB 脚 34 GND 脚 35 GPIO19 T_IRQ 脚 36 GPIO16 BIN1 脚 37 GPIO26 BIN2 脚 38 GPIO20 STBY 脚 39 GND 脚 40 GPIO21 SONAR_ECHO
附录 B · 命令速查
# 开 SPI
sudo raspi-config nonint do_spi 0
# 硬件 PWM(避开 GPIO18 / 19,见 4.4 说明)
# /boot/firmware/config.txt 里加:
dtoverlay=pwm-2chan,pin=12,func=4,pin2=13,func2=4
# 列录音设备 / 录一段
arecord -l
arecord -D plughw:1,0 -f S16_LE -r 16000 -c 1 -d 5 test.wav
# 播放
aplay -D plughw:0,0 test.wav
# 读一个按键(gpiozero)
python3 -c "from gpiozero import Button; b=Button(4,pull_up=True); b.wait_for_press(); print('talk pressed')"
# CPU 温度与内存
vcgencmd measure_temp; free -h
# 屏幕镜像(路线 A,编译后)
git clone https://github.com/juj/fbcp-ili9341 && cd fbcp-ili9341
cmake -DSPI_BUS_CLOCK_DIVISOR=6 -DILI9341=ON .. && make -j
sudo ./fbcp-ili9341
附录 C · 采购备忘
- 马达轮子注意是「双轴」还是「单轴」,双轴更好焊。
- 替代件:HC-SR04 → VL53L0X(贵一点但 3.3V 原生、更准、不用分压);TB6612 → DRV8833(更小)或 L298N(便宜但发热大)。
- 省法:旧手机当屏、旧耳机当喇叭、旧 USB 摄像头当眼、旧充电宝当电源,可再省 ¥70。
- 打样:HAT 尺寸按 65×56.5mm、四个 M2.5 孔与树莓派对齐,第二版才打。
附录 D · 术语
| 词 | 含义 |
|---|---|
| 身体 / body | Pi 上负责 GPIO、电机、传感器的服务,唯一的硬件层 |
| 算力坞 | 局域网内的 PC,负责语音识别、大模型、语音合成 |
| fbcp | Frame Buffer Copy,把 Pi 的显示帧缓冲镜像到 SPI 小屏 |
| push-to-talk | 按住说话、松开结束,对讲机式交互 |
| HAT | 树莓派标准尺寸扩展板(65×56.5mm,带 40 针座) |
10 · 待定决策(需轩轩拍板)
| # | 问题 | 选项 | 影响 |
|---|---|---|---|
| Q1 | 屏幕走哪条路线 | A:买 2.8 寸 SPI 屏(¥33) B:先用旧手机(¥0) | A 需占 GPIO 并调驱动;B 快但有第二台设备 |
| Q2 | 第一批是否现在就下单选 SPI 屏 | 是 / 否 | 影响阶段 1 的启动时间 |
| Q3 | 有没有电烙铁与焊接经验 | 有 / 需买焊台 | 没有的话第一批要加 ¥50–80 |
| Q4 | 底盘自打印还是买成品底盘套件 | 自打印(¥25 买马达轮子) 买套件(¥60–120) | 自打印省 ¥50 左右,但要多轮建模迭代 |
| Q5 | 是否现在立项登记 | 是 / 否 | 立项后才有 PROGRESS.md 进度真值 |
| Q6 | 多拉丁的形态语言 | 拟鸭 / 拟猫 / 方脑袋 / 别的 | 决定外壳建模方向与屏幕形状 |
下一步产物(等确认后交付):① 最终下单清单(带链接与替代件)② 阶段 0 可运行代码骨架(body 服务 + PC 端语音闭环)③ 下层底盘 OpenSCAD 参数化模型(等马达实物测绘)。