PDWN 浮空导致 ADS1256 进入 power-down 模式,DRDY 无响应且 SPI 总线 无输出。同时将 CS 管理从手动 GPIO 改为 SPIM 驱动自动控制,消除引脚 所有权冲突;读寄存器和读数据改用 spi_transceive 保证单次 CS 内完成。
GML670 Balance Board
当前目录是
GML670x4_V2。代码内的 CMake 项目名是GML670_V2,BLE 设备名是GML670_System。这份 README 只描述当前
V2工程已经落地的实现。更细的协议字段和示例帧见 BALANCE_BOARD_PROTOCOL.md。
目录
1. 产品概述
本工程是平衡板的 nRF5340 App Core 固件,当前版本的主链路很简单:
- 上电后等待 2 秒,初始化 BLE NUS 传输层并启动广播
- 初始化 ADS1256,完成一次 tare 去皮
- 创建独立的传感器线程,循环读取 4 路差分输入
- 在板端完成重量换算和 CoP(Center of Pressure,压力中心)解算
- 通过 BLE NUS 持续上报 17 字节 CoP 二进制帧
- 接收基站下发的阻力参数、Spotter 参数和心跳帧,并保存在内存里
当前实现已经把采样、解算和上行链路拆成了独立模块:main.c 只负责启动,BLE 在 src/ble_transport.c,ADS1256 在 src/ads1256.c,采样与 CoP 在 src/sensor.c。
2. 硬件组成
当前仓库里能直接确认的硬件如下:
| 器件 | 型号 / 对象 | 接口 | 作用 | 状态 |
|---|---|---|---|---|
| 主控 | nRF5340 DK App Core | - | 运行 BLE、SPI 采样和 CoP 解算 | ✅ |
| ADC | ADS1256 | SPI1 | 4 路多通道采样 | ✅ |
| 传感器输入 | 4 路差分输入 | ADS1256 MUX | 用于四角重量采样 | ✅ |
| 基站链路 | Nordic UART Service | BLE | 上报 CoP、接收控制参数 | ✅ |
| 编码器链路 | 预留 | BLE 协议 | 编码器上行帧已定义,当前固件不发送 | 🔲 |
ADS1256 相关引脚
app.overlay 当前把 ADS1256 接到 spi1,连线如下:
| 信号 | nRF5340 引脚 | 说明 |
|---|---|---|
| SCK | P1.15 |
spi1 时钟 |
| MOSI | P1.13 |
spi1 主发从收 |
| MISO | P1.14 |
spi1 主收从发 |
| CS | P1.12 |
片选 |
| DRDY | P1.11 |
数据就绪输入 |
| RESET | P1.10 |
ADS1256 复位控制 |
虽然 app.overlay 里有 ads1256@0 节点,但当前实现没有走单独的 Zephyr ADS1256 驱动,实际访问路径还是 src/ads1256.c 里直接操作 spi1 和 GPIO alias。
3. 系统架构
4 路差分传感器
|
v
ADS1256 + SPI1
|
v
src/ads1256.c
|
v
src/sensor.c (业务层)
|
+--> 去皮 / 17 次均值 / 死区抑制 / 重量换算 / CoP 解算
|
v
src/comm_protocol.c (协议层)
|
+--> 上行:组包 CoP/标定响应帧,调用 ble_transport_send()
+--> 下行:解析收到的帧,推入 msgq 供业务层消费
|
v
src/ble_transport.c (传输层)
|
+--> BLE NUS Notify / Write,纯字节收发
src/main.c 本身不承载采样逻辑,它只按顺序调用 ble_transport_init()、comm_protocol_init()、ble_transport_adv_start() 和 sensor_init()。
4. 功能需求与当前状态
4.1 采样与解算
| 项目 | 说明 | 状态 |
|---|---|---|
| 4 路轮询采样 | 通过 ADS1256 MUX 依次读取 0x01 / 0x23 / 0x45 / 0x67 四组差分通道 |
✅ |
| tare 去皮 | 每路读取 17 个样本,排序后取中位数作为零点偏移 | ✅ |
| 运行期滤波 | 每帧每通道采 17 次并取均值 | ✅ |
| 死区抑制 | 去皮后的均值落在 -250 ~ 250 counts 时压到 0 |
✅ |
| 重量换算 | ADC_TO_FORCE_SCALE 已按 GML670 50 kg 传感器参数推导 |
✅ |
| CoP 解算 | 根据四角重量计算 cop_x / cop_y / force |
✅ |
| 有效力阈值 | 总重量低于 0.5 kg 时,CoP 坐标置零并清除 force_valid |
✅ |
4.2 BLE 通信
| 项目 | 说明 | 状态 |
|---|---|---|
| BLE 角色 | Peripheral,使用 NUS 私有服务 |
✅ |
| 广播内容 | 广播包带 NUS UUID,扫描响应带设备名 | ✅ |
| 连接参数请求 | 连接后请求 7.5-15 ms 区间 |
✅ |
| CoP 上行 | 固定 17 字节二进制帧,目标频率约 50 Hz |
✅ |
| NUS 发送保护 | 仅在连接存在且通知已使能时发送,失败时短间隔重试 3 次 | ✅ |
| 断线重广播 | 断开 1 秒后重新广播 | ✅ |
| NUS 下行解析 | Resistance / Spotter / Heartbeat 三类帧已接收解析 | ✅ |
| 编码器上行 | 协议已预留,主循环未发送 | 🔲 |
4.3 控制参数与保护逻辑
| 项目 | 说明 | 状态 |
|---|---|---|
| Resistance 参数接收 | 接收 K / B / Tau 并保存到传输层静态变量 |
✅ |
| Spotter 参数接收 | 接收 threshold / enable 并保存到传输层静态变量 |
✅ |
| Heartbeat 接收 | 接收后刷新最近心跳时间戳 | ✅ |
| 阻力闭环控制 | 参数已接入协议层,控制逻辑未落地 | 🔲 |
| Spotter 保护动作 | 参数已接入协议层,保护动作未落地 | 🔲 |
4.4 传感器标定
标定分两级,通过 BLE 下行标定命令帧触发,平衡板执行后回复标定响应帧。帧格式详见 BALANCE_BOARD_PROTOCOL.md。
L1 标定(单通道零点 + 增益)
基站 平衡板
│ │
│── START_L1 ─────────────────>│ 进入 L1 模式
│<──────────────── OK ─────────│
│ │
│── TARE_CH (ch=0) ──────────>│ 空载,记录零点
│<──────────────── OK ─────────│
│ ...对 ch=1,2,3 重复... │
│ │
│── GAIN_CH (ch=0, 10kg) ────>│ 加载砝码,计算增益
│<──────────────── OK ─────────│
│ ...对 ch=1,2,3 重复... │
│ │
│── COMMIT_L1 ────────────────>│ 写入 NVS
│<──────────────── OK ─────────│
L2 标定(9 点网格空间修正)
L2 需要 L1 已完成。在 9 个已知位置分别放置标定负载,记录 CoP 误差用于空间修正。
基站 平衡板
│ │
│── START_L2 ─────────────────>│ 进入 L2 模式
│<──────────────── OK ─────────│
│ │
│── RECORD_GRID (pt=0) ──────>│ 在网格点 0 放置已知负载
│<──────────────── OK ─────────│
│ ...对 pt=1..8 重复... │
│ │
│── COMMIT_L2 ────────────────>│ 写入 NVS
│<──────────────── OK ─────────│
网格点编号(3×3,俯视):
6 ── 7 ── 8
│ │
3 ── 4 ── 5
│ │
0 ── 1 ── 2
点 4 为板面中心。
状态与持久化
- 标定数据通过 NVS 持久化,上电后自动加载
ERASE命令可清除全部标定数据,回退到出厂默认QUERY命令返回当前各级标定的有效性标志ABORT可在任意阶段中止标定流程,已测量数据不写入 NVS
5. BLE 协议规格
平衡板工作在 BLE Peripheral 角色,通过 Nordic UART Service 与基站交换二进制帧。
- 上行方向:平衡板 -> 基站,使用 NUS
Notify - 下行方向:基站 -> 平衡板,使用 NUS
Write - 广播内容:广播包带 NUS UUID,扫描响应带设备名
GML670_System
5.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,下发控制参数 |
5.2 连接参数
| 参数 | 当前值 | 说明 |
|---|---|---|
| 广播模式 | BT_LE_ADV_CONN_FAST_2 |
上电和断线后走同一入口启动 |
| 连接间隔请求 | 7.5-15 ms |
interval_min = 6,interval_max = 12 |
| 从站延迟 | 0 |
不跳过连接事件 |
| 监督超时 | 4000 ms |
timeout = 400 |
5.3 帧类型总览
| 类型名 | 值 | 方向 | 长度 | 频率 | 说明 |
|---|---|---|---|---|---|
PROTO_TYPE_COP |
0x01 |
平衡板 -> 基站 | 17 |
约 50 Hz |
CoP 上行帧 |
PROTO_TYPE_ENCODER |
0x02 |
平衡板 -> 基站 | 13 |
TBD | 编码器上行帧,预留 |
PROTO_TYPE_RESISTANCE |
0x10 |
基站 -> 平衡板 | 15 |
按需 | 阻力参数帧 |
PROTO_TYPE_SPOTTER |
0x11 |
基站 -> 平衡板 | 8 |
按需 | Spotter 参数帧 |
PROTO_TYPE_HEARTBEAT |
0x20 |
基站 -> 平衡板 | 4 |
~1 Hz |
心跳帧 |
5.4 当前上行主帧
CoP 帧固定 17 字节,结构如下:
| 字节偏移 | 字段 | 类型 | 说明 |
|---|---|---|---|
0 |
sync0 |
uint8 |
固定 0xAA |
1 |
sync1 |
uint8 |
固定 0x55 |
2 |
type |
uint8 |
固定 0x01 |
3 |
seq |
uint8 |
包序号,循环递增 |
4 |
flags |
uint8 |
bit0 表示 force_valid |
5-8 |
cop_x |
float32 LE |
压力中心 X 坐标,单位 mm |
9-12 |
cop_y |
float32 LE |
压力中心 Y 坐标,单位 mm |
13-16 |
force |
float32 LE |
总重量,单位 kg |
更完整的字段说明和示例帧见 BALANCE_BOARD_PROTOCOL.md。
6. ADS1256 / CoP 规格
6.1 初始化与采样流程
当前固件的 ADS1256 侧流程如下:
上电
|
+-- 配置 CS / DRDY / RESET GPIO
+-- 绑定 SPI1,频率 500 kHz
+-- 硬件复位 ADS1256
+-- 发送 CMD_SDATAC,关闭连续输出模式
+-- 写寄存器: STATUS=0x06, MUX=0x01, ADCON=0x07, DRATE=0xC0
+-- 发送 CMD_SELFCAL
+-- 回读关键寄存器做校验
+-- tare 去皮
|
+-- 传感器线程循环
|
+-- 依次切换 4 路 MUX
+-- 每路读 17 次并求均值
+-- 扣除零点偏移
+-- 死区抑制
+-- 重量换算
+-- CoP 解算
+-- 打包 CoP 帧并发送
6.2 关键参数
| 项目 | 当前值 | 说明 |
|---|---|---|
| SPI 频率 | 500 kHz |
spi_cfg.frequency = 500000 |
| STATUS | 0x06 |
ACAL=1,BUFEN=1 |
| PGA | 64 |
ADCON = 0x07 |
| 采样率 | 3750 SPS |
DRATE = 0xC0 |
| 每帧均值次数 | 17 |
AVG_COUNT = 17 |
| 去皮窗口 | 17 |
每路取 17 点,中位数为零点 |
| 死区 | ±250 counts |
DEADZONE_THRESHOLD = 250 |
| 板面半宽 | 100 mm |
BOARD_HALF_WIDTH_MM = 100.0f |
| 板面半长 | 100 mm |
BOARD_HALF_LENGTH_MM = 100.0f |
| CoP 最小有效总重 | 0.5 kg |
COP_MIN_FORCE_THRESHOLD = 0.5f |
| 调试日志频率 | 每 10 帧一次 | 目标运行状态下约 5 Hz |
6.3 CoP 判定规则
- 四路去皮后的 ADC 值先乘
ADC_TO_FORCE_SCALE,换算成重量 - 总重量低于
0.5 kg时,cop_x和cop_y置0.0f - 此时
flags.bit0 = 0,表示 CoP 坐标没有物理意义 - 总重量达到阈值后,再根据四角坐标做加权平均
当前四路传感器与板面坐标的映射如下:
| 通道 | 位置 | X | Y |
|---|---|---|---|
S0 |
右前 FR |
+100 |
+100 |
S1 |
右后 BR |
+100 |
-100 |
S2 |
左后 BL |
-100 |
-100 |
S3 |
左前 FL |
-100 |
+100 |
7. 开发环境与板级配置
当前工程采用标准 Zephyr / NCS 应用结构,目标板为 nrf5340dk/nrf5340/cpuapp。
prj.conf 当前可以直接确认的配置点包括:
CONFIG_BT=y,启用 BLECONFIG_BT_PERIPHERAL=y,工作在外设角色CONFIG_BT_NUS=y,启用 Nordic UART ServiceCONFIG_BT_DEVICE_NAME="GML670_System",设置广播设备名CONFIG_BT_NUS_SECURITY_ENABLED=n,关闭 NUS 安全限制- 日志走 RTT:
CONFIG_USE_SEGGER_RTT=y - 关闭 UART Console:
CONFIG_CONSOLE=n、CONFIG_UART_CONSOLE=n - 关闭 UART 日志后端:
CONFIG_LOG_BACKEND_UART=n - 关闭串口驱动:
CONFIG_SERIAL=n
app.overlay 当前只保留了 SPI1、ADS1256 设备节点和三根控制 GPIO 的定义,没有把 UART Console 复用回来。
8. 项目结构
当前阅读和维护时最关键的文件如下:
| 路径 | 说明 |
|---|---|
src/main.c |
启动入口,负责初始化 BLE、协议层和传感器子系统 |
src/ads1256.c |
ADS1256 SPI 读写、复位、寄存器配置和校验 |
src/sensor.c |
采样线程、tare、均值滤波、重量换算和 CoP 计算 |
src/comm_protocol.c |
协议收发解析层:上行组包、下行解析、msgq 分发 |
src/ble_transport.c |
BLE 广播、NUS 字节收发、断线重广播 |
inc/comm_protocol.h |
帧格式定义、标定子命令码、下行消息队列类型和协议 API |
app.overlay |
SPI1、CS、DRDY、RESET 的板级连线 |
prj.conf |
BLE、日志和控制台相关配置 |
BALANCE_BOARD_PROTOCOL.md |
协议专项说明、字段表和示例帧 |
9. 构建与烧录
在已经配置好 Zephyr / NCS 环境的前提下,可以直接在工程根目录执行:
west build -b nrf5340dk/nrf5340/cpuapp -p always .
west flash
如果只是重新编译当前应用,默认目标仍然是 nrf5340dk/nrf5340/cpuapp。
10. 日志与当前约束
10.1 日志
当前日志走 RTT,不占用 UART Console。启动后可以看到如下类型的信息:
- 启动 banner
- BLE transport 初始化结果
- ADS1256 关键寄存器回读结果
- tare 开始和结束
- Resistance / Spotter 下行参数日志
- 周期性的四角重量、总重、CoP 和帧耗时日志
Heartbeat 接收路径已经接入,但默认 DBG 级别下才单独打印。
10.2 当前约束
- 阻力参数、Spotter 参数和 Heartbeat 目前只做到协议接收、内存保存和日志留痕
- 编码器上行帧只在协议头里预留,当前没有实际数据源
- 传感器线程没有额外
k_msleep()节流,实际帧率由 ADS1256 采样和 BLE 发送耗时共同决定 - README 中的频率描述按当前
3750 SPS + 4 通道 * 17 次均值这套实现估算,目标运行频率约50 Hz - 当前实现默认四角传感器是固定几何布局,半宽和半长都是
100 mm
10.3 TODO
- L1 增益标定:当前使用理论推导值
ADC_TO_FORCE_SCALE,实测 10 kg 砝码显示 9 kg(约 10% 误差),需用已知砝码通过标定命令校准每通道增益 - BR 通道硬件排查:静止无马达状态下 BR 通道有 ±4600 counts 异常抖动(其余通道仅 ±500),疑似接触不良或安装松动
- 马达振动频率确认:当前 IIR 截止 1.2 Hz,若实际振动低于帧率一半(23.5 Hz)存在混叠,可能需要在 ADC 级做抗混叠或调整采样策略