灰度循迹的第一步不是 PID,而是把多个离散传感器状态转换成连续的位置偏差。只有偏差方向和大小可信,后面的方向环才有正确输入。
本文以 Tracker.c 的八路算法为例。该文件目前标注为“备用未调用”,因此本文侧重解释算法和接入方法,不把它描述成已经运行的车辆功能。
本篇目标与可观察结果
目标是把八个离散 GPIO 状态转换成一个连续横向偏差。串口或 OLED 至少应能观察八路 0/1 状态、有效通道数、偏差值和 line_detected。
八路数字灰度 → 通道位置映射 → 有效位置平均 → 偏差值 + 是否检测到线八路输入如何组织
Tracker_Read() 接收状态数组和偏差输出指针。函数先检查空指针,再读取八个数字输入。
代码把左侧三路映射为 -3、-2、-1,中间两路映射为 0,右侧三路映射为 1、2、3。这是一套无量纲传感器索引坐标。
中间两路都取零,意味着无论哪一路单独命中,偏差都为零。这样中心区域较宽、抗抖动更强,但无法区分线落在中间偏左还是偏右。
加权质心原理
若多路同时有效,代码对所有有效通道的位置求平均:
offset = Σ(state[i] × position[i]) / Σstate[i]例如左侧 -2、-1 两路同时有效,偏差为 -1.5;左右对称通道同时有效,偏差会接近零。
这种算法比“只取最外侧通道”连续,但它隐含一个条件:数字传感器的物理间距近似等距。若实际排布不等距,应使用实测横坐标作为权重。
IQ 定点计算
偏差类型为 _iq,除法使用 _IQdiv()。IQmath 用定点数在没有高性能浮点单元的 MCU 上表达小数,具体小数位由全局 IQ 格式决定。
调用者必须使用同一 IQ 配置,不能把 _iq 当作普通整数直接打印或参与浮点计算。调试时可使用匹配的 IQ 转换宏显示实际数值。
源码定义了 DIS_INRERVAL = _IQ(1.5),注释却写“1.0 cm”,并且位置计算没有使用该宏。因此当前偏差不是厘米;宏名、注释和实现之间存在不一致。
失线返回值
没有任何有效通道时,分母为零。源码不执行除法,而是返回 false。有有效通道时写入偏差并返回 true。
这比用某个特殊偏差值表示失线更可靠,因为“偏差为零”本身是正常居中状态。上层应显式保存:
bool line_detected = Tracker_Read(states, &offset);失线后的策略属于应用层:可以减速并按最后方向搜索,也可以安全停车。Tracker.c 没有替调用者做决定。
如何接入方向环
方向环的误差可直接使用 offset,但正负号必须通过低输出测试确认:
if (Tracker_Read(states, &offset)) { steer = DirectionPID_Update(0, offset); left_command = base_command - steer; right_command = base_command + steer;} else { LineLost_Handle();}这里的三个函数是教学伪代码,接入时应替换为工程中的真实接口。若车辆向左偏时控制量让它继续左转,需要交换误差符号或左右差速方向。
输入极性与硬件边界
源码通过 GPIO 电平形成 0/1 状态,但传感器型号、比较器门限、黑线/白底对应电平和供电电压仍需在实际硬件上确认。
因此不能断言 1 一定代表黑线。接入前应逐路遮挡或压线,记录原始 GPIO,确认极性后再决定是否取反。
传感器板供电、电平和输入保护必须以实际模块原理图、器件手册和主控数据手册为准。软件算法不能替代硬件核对。
常见故障与排查
| 现象 | 可能原因 | 排查方式 |
|---|---|---|
| 偏差始终为零 | 中间两路触发、输入映射错误或所有通道相互对称 | 同时打印八路状态 |
| 左右方向相反 | 权重顺序或差速符号与安装方向不一致 | 手动把线移到单侧观察偏差 |
| 宽线时偏差跳动 | 多路门限不一致、传感器高度变化 | 记录每路切换顺序 |
| 失线后车辆继续跑 | 上层忽略了 false 返回值 | 单独记录 line_detected |
| 偏差被当作厘米 | 未进行物理坐标标定 | 测量通道间距并重建权重 |
接入真实传感器前还要确认什么
| 检查项 | 当前代码表现 | 接入要求 |
|---|---|---|
| 位置计算 | Tracker_Read() 使用八路加权平均 | 用实际安装顺序核对权重左右方向 |
| 失线表达 | 无有效通道时返回 false | 上层必须单独处理失线,不能沿用旧偏差 |
| 偏差单位 | 当前结果是无量纲通道坐标 | 需要厘米时,用实测横坐标替换权重 |
| 工程调用 | 文件目前标注为备用未调用 | 接入调度任务并记录调用周期 |
| 输入极性 | 代码未给出黑白电平定义 | 逐路实测后统一完成取反或映射 |
本篇总结
Tracker.c把八路数字输入转换成-3…3的无量纲连续偏差。- 加权质心允许多路同时命中,但依赖通道位置映射合理。
- 两个中心通道共用零权重,中心容差更宽,分辨率也更低。
- 失线应使用布尔状态表达,不能和零偏差混为一谈。
- 该文件目前只是备用算法,接入前还要确认输入极性、IQ 格式和真实调用接口。