本文档定义 OpenKidCar「干杯一号」大脑(Raspberry Pi)与小脑(Arduino Mega)之间的串口通信协议。
这份协议是"接口契约"的一部分,与 hardware_io_map.md 配套。两端代码必须严格按此实现。
| 参数 | 值 |
|---|---|
| 通信接口 | UART 串口 |
| 波特率 | 115200 |
| 数据格式 | 8 数据位 / 无校验 / 1 停止位(8N1) |
| 接线 | 树莓派 GPIO14/15 ↔ Arduino Serial1 (D18/D19) |
| 电平 |
- 小脑(Arduino)的 Serial1 专用于协议,调试日志走 Serial0(USB 口)
- 大脑(树莓派)的协议串口仅收发帧,日志走系统 stdout
否则日志字符会被当成协议解析,产生乱码和假命令。
协议采用可读文本行格式,每帧以换行 \n 结尾:
#命令:参数;CK:XX\n
| 字段 | 说明 |
|---|---|
# |
帧头,标志一帧开始 |
命令 |
命令名,大写字母(见第 3 节) |
:参数 |
参数,冒号分隔;多个参数用逗号 , 分隔;无参数可省略 |
;CK:XX |
校验段,XX 为 CRC8 校验和的十六进制两位(见 2.2) |
\n |
帧结束符 |
最大帧长:128 字节(含 \n)。超长帧直接丢弃,防止缓冲区溢出。
参数约束:参数不得包含 #、;、:、,、\n 这些特殊字符(当前受控枚举值均满足)。
对 命令:参数(不含 #、;CK:XX 本身)的所有字符计算 CRC-8/ATM(多项式 0x07,初值 0x00)。
Python 参考实现:
def crc8(data: bytes) -> int:
crc = 0
for b in data:
crc ^= b
for _ in range(8):
if crc & 0x80:
crc = ((crc << 1) ^ 0x07) & 0xFF
else:
crc = (crc << 1) & 0xFF
return crcArduino 参考实现:
uint8_t crc8(const char* data, size_t len) {
uint8_t crc = 0;
for (size_t i = 0; i < len; i++) {
crc ^= (uint8_t)data[i];
for (uint8_t j = 0; j < 8; j++) {
if (crc & 0x80) crc = (crc << 1) ^ 0x07;
else crc = (crc << 1);
}
}
return crc;
}示例:LIGHT:ON 的 CRC8 = 0xB7,完整帧为:
#LIGHT:ON;CK:B7\n
- 逐字符读取,遇到
#开始缓冲 - 读到
\n结束缓冲,得到一帧 - 校验通过 → 解析执行;校验失败 → 静默丢弃
- 帧重同步:若出现以下情况,清空缓冲,回到"等待
#"状态:- 收到非法字符(
#之前出现非空白字符,或缓冲中混入非法字节) - 缓冲超过 128 字节仍未见
\n - 帧超时(200ms 内未收到完整帧的
\n)
- 收到非法字符(
| 命令 | 参数 | 含义 | 是否需 ACK |
|---|---|---|---|
GEAR |
-1(R倒车) / 1-4 | 设置速度档位 | ✅ |
LIGHT |
ON / OFF | 前大灯 | ✅ |
STRIP |
模式,颜色,亮度 | RGB 灯带 | ✅ |
TURN |
L / R / OFF | 转向灯 | ✅ |
STEER |
0-180 | 转向角度(90=直行,舵机) | ✅ |
MUTE |
ON / OFF | 引擎音效静音 | ✅ |
HORN |
ON / OFF | 鸣笛 | ✅ |
BRAKE |
ON / OFF | 制动(缓刹) | ✅ |
EBRK |
ON / OFF | 远程急刹(最高优先级)/ 解除急刹 | ✅ 安全命令 |
STATUS |
GET | 请求状态上报 | ✅ |
PING |
- | 心跳请求 | ✅ |
ACK(见 4.3)。大脑据此确认命令是否生效,不回复视为未执行。
| 命令 | 参数 | 含义 | 示例 |
|---|---|---|---|
STAT |
速度,油门,档位,电压,温度,电流 | 状态上报 | STAT:12,55,3,24.6,32,3.2 |
BTN |
按钮名,PRESS/RELEASE | 按钮事件 | BTN:LIGHT_BTN,PRESS |
SEAT |
ON / OFF | 就座 / 离座 | SEAT:ON |
EBRK |
ON | 急刹被触发 | EBRK:ON |
PONG |
- | 心跳响应 | PONG |
ACK |
OK / ERR:原因 | 命令应答 | ACK:OK |
READY |
协议版本 | 小脑上电就绪 | READY:V0.3 |
上行命令无需 ACK(大脑被动接收,效果由后续命令/状态体现)。
| 按钮名 | 对应硬件 | 说明 |
|---|---|---|
LIGHT_BTN |
D24 大灯开关 | 切换大灯 |
MUTE_BTN |
D23 静音开关 | 切换静音 |
STRIP_BTN |
D25 灯带开关 | 切换灯带 |
HORN_BTN |
D26 喇叭按钮 | 按下=PRESS,松开=RELEASE |
EBRK_BTN |
D22 一键刹车 | 自锁按钮,PRESS |
TALK_BTN |
D27 对讲按钮 | 按住说话=PRESS,松开=RELEASE |
刹车灯(D3)由小脑本地逻辑直接响应,不走命令:
- 刹车踏板踩下 → 刹车灯亮(随踩踏深度调整亮度)
- 收到
BRAKE:ON/EBRK:ON→ 刹车灯亮 - 以上状态解除 → 刹车灯灭
① 小脑上电初始化完成
② 小脑 ──READY:V0.3──► 大脑 (带上协议版本)
③ 大脑 校验版本;若不符,记录告警(单机系统不强制拒绝)
④ 大脑 ──GEAR:2──► 小脑 (重新下发当前档位)
⑤ 大脑 ──LIGHT:ON──► 小脑 (重新下发灯光状态)
⑥ ... 持续下发全部执行状态,完成状态同步(见 4.5)
- 大脑每 1 秒 发
PING,小脑立即回PONG - 连续 3 次未收到
PONG→ 大脑判定小脑离线,进入安全模式:- 若在行驶中 → 平滑减速至停止
- 通过 4G 通知家长 APP
- 小脑若超过 5 秒未收到任何
PING→ 判定大脑离线,安全兜底:维持当前安全状态,若在行驶中平滑减速至停止 - 心跳频率与容错次数为可调参数,安全关键场景可缩短(如 500ms / 2 次)
- 小脑收到任何下行命令,处理后必须回复
ACK ACK:OK:执行成功;ACK:ERR:UNKNOWN:未知命令;ACK:ERR:INVALID_ARG:参数非法- 大脑在
ACK超时(默认 500ms)未收到 → 视为命令未执行,按 4.4 处理
安全命令不容丢失,大脑在收到 ACK 前持续重发:
EBRK:ON:每 100ms 重复发送,直到收到ACK:OK或超时 2s → 超时进入安全模式BRAKE:每 500ms 重复,直到收到ACK或超时 3s
- 大脑维护一份执行状态视图(档位、灯光、静音等),以本地决策为准
- 小脑重启 / 握手时,大脑按视图重新下发全部状态(4.1)
- 状态变化时(如大脑收到语音指令),大脑立即下发并等待 ACK,确保两端一致
① 小脑检测到 LIGHT_BTN 按下
② 小脑 ──BTN:LIGHT_BTN,PRESS──► 大脑
③ 大脑 解析:灯当前关 → 切换为开
④ 大脑 ──LIGHT:ON──► 小脑
⑤ 小脑 执行:D2 继电器闭合 → 大灯亮起
⑥ 小脑 ──ACK:OK──► 大脑 (大脑更新状态视图)
① 小脑 以 10Hz 定时上报油门深度
② 小脑 ──STAT:12,55,3,...──► 大脑
③ 大脑 根据"油门=55%"实时合成引擎音效
④ 大脑 通过音频输出 → 功放 → 扬声器播放(油门越大越响)
⑤ 若 MUTE_BTN 按下 → 小脑上报 → 大脑静音所有音源
| 情况 | 处理 |
|---|---|
| 校验失败 | 静默丢弃,不回复 |
| 帧超长 / 帧超时 / 非法字符 | 清空缓冲,重新帧同步 |
| 未知命令 | 回复 ACK:ERR:UNKNOWN |
| 参数非法 | 回复 ACK:ERR:INVALID_ARG |
| 下行命令 ACK 超时 | 按命令类别重发;安全命令持续重发(4.4) |
| 小脑离线(3 次心跳无响应) | 大脑安全模式 + APP 通知 |
| 大脑离线(5 秒无 PING) | 小脑安全兜底减速 |
- 行驶中:10Hz(100ms 一次)
- 静止且无人:1Hz(省电)
STAT:速度,油门,档位,电压,温度,电流
12 , 55 , 3 , 24.6, 32 , 3.2
| 参数 | 单位 | 来源 |
|---|---|---|
| 速度 | km/h | 轮速传感器 / 油门档位估算 |
| 油门 | % | A0 霍尔踏板 |
| 档位 | -1(R倒车) / 1-4 | 当前限速档位(-1=倒车,上限 6km/h) |
| 电压 | V | A3 分压采样 |
| 温度 | ℃ | A4 NTC |
| 电流 | A | A5 霍尔电流传感器 |
参数为位置参数,顺序严格固定,两端实现必须一致。新增参数追加在末尾。
- 新增命令:命令表(第 3 节)增加一行,两端同步实现,协议版本号 +0.1
- 新增按钮/传感器:
BTN参数表增加名称;STAT末尾追加参数位 - 兼容性:帧格式固定,命令允许增量添加,不得删除/改序已有命令
- 大脑(Python):
pyserial读串口,逐行解析,用状态机处理半行(粘包/断包);严格按 2.3 帧同步 - 小脑(Arduino):串口中断或
Serial.available()循环 + 行缓冲(128 字节);按 2.2 计算 CRC8 - 两端通用:CRC8、帧封装、帧解析建议做成独立模块,与业务逻辑分离,便于测试与复用
- 调试:协议串口专用(1.1),日志走独立通道;可用虚拟串口(Windows: com0com)在 PC 上联调两端
| 版本 | 日期 | 说明 |
|---|---|---|
| V0.1 | - | 初始文本协议雏形 |
| V0.2 | 2026-08-06 | 加入帧头/校验/心跳/安全模式,命令集覆盖 PRD 全功能 |
| V0.3 | 2026-08-06 | 校验升级为 CRC8;规定最大帧长 128B;加入帧重同步、统一 ACK、安全命令可靠投递、状态同步机制、串口专用原则;明确刹车灯本地逻辑 |
与 hardware_io_map.md 共同构成接口契约。