教程 · 入门 · 阅读约 17 分钟

读取正交编码器,测出轮子的行驶距离与速度

解码正交编码器的信号,把计数换算成轮子的行驶距离和速度,处理方向判断与计数溢出,并在真实的机器人上标定测量结果。

轮子编码器把转动变成数字脉冲。数这些脉冲就能量出机器人走了多远;把它们按时间数起来就能估计速度。正交编码器提供两个脉冲通道,A 和 B,错开四分之一个周期。哪个通道先变,就揭示了方向。

编码器量的是相对运动,不是绝对位置。计数只有在开机之后或一次有意复位之后才有意义;而它也只有在你明确规定了“多少个计数算轮子转一圈”之后才有用。

读那个双通道模式

有效的正交状态是 00、01、11 和 10。往一个方向转就沿着这个序列走,反方向转则逆着走。每次只应该有一个位变化。像 00 直接跳到 11 这样的跳变,说明漏掉了一个边沿,或者噪声把信号搞坏了。

有三种常见的计数模式:

  • **1× 解码:**每周期数 A 通道的一个边沿。
  • **2× 解码:**数 A 通道的两个边沿。
  • **4× 解码:**数两个通道的每一个边沿。

所以一份写“每转 12 个脉冲”的数据手册,软件上可能产生每编码器轴转 12、24 或 48 个计数。如果编码器装在电机上而不是轮子上,还要乘上减速比。把完整的约定写在那个常数旁边;不明所以的两倍和四倍因子是里程计最常见的缺陷之一。

正交编码器两个输出通道的时序图。通道 A 画在通道 B 上方,两者是同频方波,B 比 A 滞后四分之一个周期。四条竖直虚线标出一个电周期内的四次跳变,编号一到四,并注明四个全数起来就是一颗 300 CPR 编码器每转 1200 个计数。旁边注解指出相位偏移的含义:B 滞后 A 表示前进,B 超前 A 表示轮子在倒转。
一个周期,四条可数的边沿。哪个通道超前告诉你方向;你数几条边沿决定你的距离是对的,还是差了一个四倍。 下载 SVG

把信号正确接上

先确定输出是推挽、开集还是开漏。集电极开路或漏极开路的输出需要上拉电阻,而那个上拉可能是内部的也可能是外部的,取决于边沿速率和接线方式。确认信号电压对控制器是安全的——5 V 的编码器输出可能烧掉 3.3 V 的输入。

让线缆远离电机线。跑得更长时,用编码器厂家给的线缆和终端指导。一条干净的数字边沿,比事后在软件里修假计数值钱得多。

在跑电机之前先用手慢慢转轮子。两个通道都应该在有效逻辑电平之间交替。如果有一个卡住了,先修接线再调代码。

解出方向而不丢计数

速度适中时,在通道 A 每次变化时触发一次中断,采样 B 来定方向:

volatile long encoderCount = 0;

void onEncoderA() {
  bool a = digitalRead(ENCODER_A);
  bool b = digitalRead(ENCODER_B);
  encoderCount += (a == b) ? 1 : -1;
}

符号取决于通道顺序和物理安装。把 A 和 B 对调或者把结果取反,让轮子前进对应正计数。在硬件边界上一次做完这件事,而不是把符号变化散落在里程计代码里。

边沿速率高时,反复调用 digitalRead() 可能太慢。用硬件正交外设、一个成熟的平台编码器库,或者针对该控制器的直接端口访问。选之前先估算最坏情况:每秒边沿数 = 每轮转计数 × 轮子每秒最大转数。

把中断里的活保持简短。更新计数,然后返回。打印、浮点换算和控制计算都属于主循环。

把计数换算成轮子行程

设 N 是每轮转的解码计数,D 是有效轮径。轮周长是 πD,于是:

distance = count × πD / N

对一只 65 mm 的轮子和每轮转 1,440 个解码计数来说,每个计数约合 0.142 mm。那个数学分辨率不等于真实精度:轮胎压缩、轮子打滑和直径误差通常要大得多。

安全地读多字节计数器。在小型单片机上,中断可能在主循环读到一半时更新它。短暂关中断,或者用平台的原子设施:

noInterrupts();
long snapshot = encoderCount;
interrupts();

float distanceM = snapshot * (PI * wheelDiameterM) / countsPerWheelRev;

用足够宽的有符号计数器,并对快照之间求差。无符号的模减也能处理回绕,但只有在类型和采样间隔都是有意为之的前提下。

估计速度而不放大噪声

在固定采样间隔上,计算计数差:

velocity = (newCount - oldCount) × distancePerCount / elapsedTime

间隔短响应快,但会把低速量化成零和一跳一计数。间隔长更平滑,但加了滞后。先从控制环周期附近起步,只有在控制器真的需要时才做几采样平均。

对非常慢的运动,测量边沿之间的时间可能比在固定窗口里数边沿更好。无论用哪种方法,都要用单调时钟打时间戳,并用实测的流逝时间,而不是假设每一轮循环都完美地按时刻执行。

在整条上传动上标定

在轮子上做个标记,让它精确转十圈并记录计数。除以十可以减小“在各个边沿之间停下来”的影响。然后让机器人沿一段量过的直线走,比较编码器距离和地面距离,调整有效轮径。

左右轮分别标定。如果机器人报告的距离相等却走弯,说明两个有效直径或者传动增益不同。保留各自独立的缩放系数;真实的轮胎和减速箱需要这个标定旋钮。

在第二个速度上重复一次。变化很大就提示打滑、轮毂松动、漏掉的边沿或时序问题,而不是简单的直径误差。

坏读数的诊断

  • **静止时计数在变:**电气噪声或输入悬空;检查信号和上拉。
  • **计数量级正好差 2 倍或 4 倍:**软件解码模式和数据手册的脉冲定义不一致。
  • **方向随机翻转:**有一个通道嘈杂或采样太晚;检查边沿质量和解码方法。
  • **高速时计数卡住:**控制器跟不上那个边沿速率;改用硬件解码或降低中断开销。
  • **距离可重复但不对:**标定有效轮径和减速比。
  • **距离随地面变化:**编码器量的是轮子转动,不是地面真值;轮子打滑是真实存在的不确定度。

可靠的计数是差速里程计的输入,而速度反馈可以闭合PID 控制器模拟器里探索的那个电机环。那份位姿也是每个路径跟踪器都假定的输入,这也是为什么它的误差就变成了它们的误差。

下一步

数数只是一半。测出来的速度之所以值得拥有,是因为你可以保持它——见闭环轮速控制,它把 PWM 从一个电压变成一个速度,也正是它阻止了机器人因为一台电机变弱而走弯。在全向底盘上,这就不再是个锦上添花的做法:四个轮速的比例就是转向,而开环没有任何东西可以保持它们。

探索关联图谱

本教程所属的搭建

包含本教程的项目和学习路线。

延伸阅读

参考资料