Files
balance-board/doc/BALANCE_BOARD_PROTOCOL.md
T
pNexus 0979866a7c refactor(protocol): 新增 comm_protocol 协议收发解析层,ble_transport 退化为纯传输
- 删除 protocol.h,帧定义和标定命令码统一迁入 comm_protocol.h
- 新增 comm_protocol.c:上行组包(CoP/标定响应)、下行解析+msgq 分发
- ble_transport 剥离所有协议解析和参数 getter,仅保留字节收发+rx 回调注册
- main.c 初始化顺序:ble_transport → comm_protocol → adv_start → cal_init
- 更新 README 架构图和项目结构表,补充标定流程章节
- 更新 BALANCE_BOARD_PROTOCOL.md 增加标定命令/响应帧格式文档
2026-05-15 18:06:33 +08:00

11 KiB
Raw Blame History

平衡板协议说明

本文说明当前固件里的数据包格式和 BLE 通讯方式。

1. BLE 通讯方式

平衡板工作在 BLE Peripheral 角色,通过 Nordic UART ServiceNUS)与基站通信。

  • 上行方向:平衡板 -> 基站,使用 NUS Notify
  • 下行方向:基站 -> 平衡板,使用 NUS Write
  • 广播内容:包含设备名和 NUS 128-bit UUID

1.1 NUS UUID

项目 UUID 方向 说明
Service 6E400001-B5A3-F393-E0A9-E50E24DCCA9E - NUS 主服务
TX Characteristic 6E400003-B5A3-F393-E0A9-E50E24DCCA9E 平衡板 -> 基站 Notify,上报 CoP 和编码器数据
RX Characteristic 6E400002-B5A3-F393-E0A9-E50E24DCCA9E 基站 -> 平衡板 Write,下发阻力参数和控制命令

1.2 当前连接行为

  • 连接建立后,平衡板会请求 7.5-15 ms 连接区间(min=6, max=12)。
  • 所有数据通过 NUS 二进制帧发送,不走文本协议。

2. 数据包总览

当前协议使用双帧头 0xAA 0x55 作为包起始标记。所有多字节字段按 Little Endian 编码。

每帧末尾附加 1 字节 CRC-8/MAXIM 校验(poly=0x31, init=0x00, refin=true, refout=true, xorout=0x00)。校验范围为帧头之后、CRC 字节之前的所有字段(即跳过 sync0/sync1)。调用方式:crc8(data + 2, len - 3, 0x31, 0x00, true)

类型名 方向 长度 频率 说明
PROTO_TYPE_COP 0x01 平衡板 -> 基站 11 50 Hz 压力中心帧
PROTO_TYPE_ENCODER 0x02 平衡板 -> 基站 13 TBD 电机编码器帧(预留)
PROTO_TYPE_RESISTANCE 0x10 基站 -> 平衡板 16 按需 阻力参数帧
PROTO_TYPE_SPOTTER 0x11 基站 -> 平衡板 9 按需 保护模式帧
PROTO_TYPE_HEARTBEAT 0x20 基站 -> 平衡板 5 ~1 Hz 心跳帧
PROTO_TYPE_CAL_CMD 0x30 基站 -> 平衡板 10 按需 标定命令帧
PROTO_TYPE_CAL_RESP 0x31 平衡板 -> 基站 14 按需 标定响应帧

3. 上行数据包

3.1 压力中心帧 (CoP)

CoP 帧固定 11 字节,结构如下:

字节偏移 字段 类型 值/范围 说明
0 sync0 uint8 0xAA 帧头第 1 字节
1 sync1 uint8 0x55 帧头第 2 字节
2 type uint8 0x01 CoP 包类型
3 flags uint8 见下表 状态标志位
4-5 cop_x int16 LE - 压力中心 X 坐标 (cm)
6-7 cop_y int16 LE - 压力中心 Y 坐标 (cm)
8-9 force int16 LE - 总重量 (kg)
10 crc uint8 - CRC-8/MAXIM 校验

flags 位定义

名称 说明
bit0 COP_FLAG_FORCE_VALID 1 表示总力超过阈值,CoP 坐标有意义
bit1-7 预留 0

CoP 解算公式

传感器布局(俯视):

  S4 (FL) -------- S1 (FR)
  |       center        |
  S3 (BL) -------- S2 (BR)

传感器坐标(单位:cm,板面中心为原点):

传感器 位置 X Y
S1 右前 (FR) +10 +10
S2 右后 (BR) +10 -10
S3 左后 (BL) -10 -10
S4 左前 (FL) -10 +10

计算公式:

F_total = F0 + F1 + F2 + F3

CoP_X = (F0 * x0 + F1 * x1 + F2 * x2 + F3 * x3) / F_total
CoP_Y = (F0 * y0 + F1 * y1 + F2 * y2 + F3 * y3) / F_total

F_total < COP_MIN_FORCE_THRESHOLD 时,CoP 坐标无意义,flags.bit0 = 0cop_xcop_y0

示例

下面是一个 CoP 帧示例(CoP 有效,cop_x=3 cm, cop_y=5 cm, force=75 kg):

AA 55 01 01  03 00  05 00  4B 00  XX

含义如下:

  • AA 55:双帧头
  • 01CoP 包
  • 01flags = force_valid
  • 03 00cop_x = 3 cmLE int16
  • 05 00cop_y = 5 cmLE int16
  • 4B 00force = 75 kgLE uint16
  • XXCRC-8/MAXIM(对字节 [2..9] 计算)

3.2 电机编码器帧(预留)

编码器帧固定 13 字节,结构如下。该帧目前仅在协议中预留定义,固件暂不实现。

字节偏移 字段 类型 值/范围 说明
0 sync0 uint8 0xAA 帧头第 1 字节
1 sync1 uint8 0x55 帧头第 2 字节
2 type uint8 0x02 编码器包类型
3 flags uint8 0 预留
4-7 cable_length float32 LE - 拉索长度 (mm)
8-11 velocity float32 LE - 拉索速度 (mm/s)
12 crc uint8 - CRC-8/MAXIM 校验

4. 下行数据包

4.1 阻力参数帧

阻力参数帧固定 16 字节,用于基站向平衡板下发电机阻力控制参数。

字节偏移 字段 类型 值/范围 说明
0 sync0 uint8 0xAA 帧头第 1 字节
1 sync1 uint8 0x55 帧头第 2 字节
2 type uint8 0x10 阻力参数包类型
3-6 K float32 LE - 刚度 (N/m)
7-10 B float32 LE - 阻尼 (Ns/m)
11-14 Tau float32 LE - 时间常数 (s)
15 crc uint8 - CRC-8/MAXIM 校验

示例

AA 55 10  00 00 C8 42  00 00 48 41  CD CC 4C 3E  XX

含义如下:

  • AA 55 10:阻力参数帧头
  • 00 00 C8 42K = 100.0 N/m
  • 00 00 48 41B = 12.5 Ns/m
  • CD CC 4C 3ETau = 0.2 s
  • XXCRC-8/MAXIM

4.2 Spotter Mode 帧

Spotter 帧固定 9 字节,用于启用或关闭保护模式。

字节偏移 字段 类型 值/范围 说明
0 sync0 uint8 0xAA 帧头第 1 字节
1 sync1 uint8 0x55 帧头第 2 字节
2 type uint8 0x11 Spotter 包类型
3-6 threshold float32 LE - 保护力阈值 (N)
7 enable uint8 01 0 = 关闭, 1 = 启用
8 crc uint8 - CRC-8/MAXIM 校验

示例

启用 Spotter Mode,阈值 500 N

AA 55 11  00 00 FA 43  01  XX

4.3 心跳帧

心跳帧固定 5 字节,基站以约 1 Hz 频率发送,用于活性检测。

字节偏移 字段 类型 值/范围 说明
0 sync0 uint8 0xAA 帧头第 1 字节
1 sync1 uint8 0x55 帧头第 2 字节
2 type uint8 0x20 心跳包类型
3 counter uint8 0-255 滚动计数
4 crc uint8 - CRC-8/MAXIM 校验

示例

AA 55 20 05 XX

含义:心跳包,计数 5XX 为 CRC。

5. 标定协议

标定协议通过下行标定命令帧(0x30)和上行标定响应帧(0x31)完成传感器在线标定。标定分两级:L1 单通道零点/增益标定,L2 多点网格空间修正。

5.1 标定命令帧(下行)

标定命令帧固定 10 字节,由基站发送给平衡板:

字节偏移 字段 类型 值/范围 说明
0 sync0 uint8 0xAA 帧头第 1 字节
1 sync1 uint8 0x55 帧头第 2 字节
2 type uint8 0x30 标定命令包类型
3 subcmd uint8 见下表 子命令码
4 target uint8 0-3 / 0-8 通道号或网格点号
5-8 param float32 LE - 参数(如已知质量 kg
9 crc uint8 - CRC-8/MAXIM 校验

subcmd 子命令码定义

子命令码 名称 target 含义 param 含义 说明
0x01 START_L1 - - 进入 L1 标定模式
0x02 TARE_CH 通道号 (0-3) - 对指定通道执行零点标定
0x03 GAIN_CH 通道号 (0-3) 已知质量 (kg) 对指定通道执行增益标定
0x04 COMMIT_L1 - - 提交 L1 标定数据到 NVS
0x05 ABORT - - 中止当前标定流程
0x10 START_L2 - - 进入 L2 网格标定模式
0x11 RECORD_GRID 网格点号 (0-8) - 记录当前网格点 CoP 误差
0x12 COMMIT_L2 - - 提交 L2 标定数据到 NVS
0x20 ERASE - - 擦除所有标定数据
0x21 QUERY - - 查询当前标定状态

示例

对通道 2 执行增益标定,已知质量 10.0 kg:

AA 55 30 03 02  00 00 20 41  XX
  • AA 55 30:标定命令帧头
  • 03subcmd = GAIN_CH
  • 02target = 通道 2
  • 00 00 20 41param = 10.0 kgfloat32 LE
  • XXCRC-8/MAXIM

5.2 标定响应帧(上行)

标定响应帧固定 14 字节,平衡板在执行标定命令后回复:

字节偏移 字段 类型 值/范围 说明
0 sync0 uint8 0xAA 帧头第 1 字节
1 sync1 uint8 0x55 帧头第 2 字节
2 type uint8 0x31 标定响应包类型
3 status uint8 见下表 结果状态码
4 subcmd uint8 - 对应的子命令回显
5-12 data uint8[8] - 响应数据(上下文相关)
13 crc uint8 - CRC-8/MAXIM 校验

状态码定义

状态码 名称 说明
0x00 OK 命令执行成功
0x01 ERR_STATE 状态机不允许此操作
0x02 ERR_NVS NVS 读写失败
0x03 ERR_PARAM 参数非法

data 字段含义

data[8] 内容取决于子命令:

子命令 data 内容 说明
TARE_CH data[0..3] = 零点 ADC 值 (int32 LE) 通道去皮后的零点偏移
GAIN_CH data[0..3] = 增益 (float32 LE) kg/count 换算系数
QUERY data[0] = L1 zero valid, data[1] = L1 gain valid, data[2] = L2 valid 各级标定有效性标志
其他 全零 无附加数据

示例

通道 2 增益标定成功,增益 = 5.322e-5 kg/count

AA 55 31 00 03  XX XX XX XX 00 00 00 00  XX
  • AA 55 31:标定响应帧头
  • 00status = OK
  • 03subcmd = GAIN_CH(回显)
  • 前 4 字节 data:增益值 float32 LE
  • 后 4 字节 data:填 0
  • 末字节:CRC-8/MAXIM

6. 当前实现约束

  • CoP 帧固定 11 字节,可在最小 ATT MTU 23(NUS 有效负载 20 字节)下传输。
  • 50 Hz CoP 上行流隐式充当平衡板到基站的活性检测,因此心跳仅为下行。
  • 传感器通道到物理位置的映射:MUX {0x01, 0x23, 0x45, 0x67} → FL/FR/BR/BL。
  • BOARD_HALF_WIDTH_CM = 10BOARD_HALF_LENGTH_CM = 10(后续可能调整)。
  • ADC_TO_FORCE_SCALE 当前为占位值 1.0f,待 10 kg 砝码标定后修正。
  • ARM Cortex-M33 为小端架构,float32 在 packed struct 中天然符合 Little Endian 要求。