一颗编码器把三种输出都写成 65536,不代表它们同样精确
首发于公众号「如是有为」 · 查看原文

假设一台电机同时给你三种角度读数:屏幕上的数字、PWM 占空比、还有 A/B 脉冲。它们最后都被软件换算成 32768。你会认为电机正好转了半圈,而且三种读法同样可靠。
这个判断很自然,也可能刚好错了。
就像三个人都报“今天 20 度”,一个看了室外温度计,一个看了空调面板,还有一个是根据昨天的天气估出来的。数字碰巧相同,测量过程并没有因此变成同一种东西。
编码器里常见的“统一为 16 位”,就有点像这个问题。I²C 角度字可能真的有 16 位,PWM 和 ABZ 则要经过各自的周期、边沿和计数换算。最后都塞进 0 到 65535,只能说明它们使用同一把软件刻度,不能直接说明它们同样精确。
我不太喜欢在规格表里看到这种句子,不是因为统一接口不好,而是因为它很容易把后面的分辨率、计数模式和溢出边界藏掉。
65536 有时只是换算终点
先拿最容易混淆的三种量摆在一起。
I²C 角度字如果真是 16 位,一圈分成 65536 个码,这个说法比较直接。PWM 就要看定时器的周期和有效位数。假如它实际只有 13 位,软件最后把结果放大到 65536,低出来的那几位只是插值,传感器并没有因此多看见什么。
ABZ 更麻烦。它交给主控的是边沿,主控先数边沿,再根据码盘线数和解码模式换成角度。下面的 96 线、四倍频只是演示计算,不对应任何具体产品:一圈原始计数是 384,把 384 个位置摊到 65536 个码上,每个计数约对应 170.67 个归一化码。这个数可以用于统一接口,但它不等于 ABZ 真有 16 位的角度分辨率。
我会把这句话写在驱动说明的最前面:统一的是数值范围,不是测量能力。
否则后面很容易出现一种看似合理的测试:I²C、PWM、ABZ 都输出 32768,于是三路“对上了”。其实它们只是在同一时刻被换成了同一个数字,原始量是否真的对应,还没有被证明。
解码模式错一次,整圈就会差一半
AB 两路信号接上以后,定时器究竟数哪些边沿,不能靠工程师脑中的“正交就是四倍频”来补齐。芯片和 MCU 通常会把这件事做成几个模式:只数 TI1,只数 TI2,或者两路的边沿都数。具体选了哪一档,要回到寄存器配置里看。
拿刚才的 96 线示意码盘算一遍就很直观。二倍频时,一圈是 192 个计数;四倍频时,一圈是 384 个。假如硬件实际在二倍频,软件常量却写着 counts_per_turn = 384,角度换算就会小一半。机械轴已经转完一圈,程序只走到半圈;再转一圈,数值才绕完整个范围。
这类问题不太会在第一眼暴露出来。A、B 还有相位差,计数器也在增加,串口打印的角度看起来连续,电机甚至能正常闭环。只要没有拿机械角做一次比例校验,它就能混在“通信正常”里继续跑。
我会用一个很笨、但很有效的办法:把轴固定在 90°,记录原始计数;再把轴转到 180°,再记一次。随后分别用二倍频和四倍频的公式算。两组结果里,总有一组会对上真实机械角,另一组会露出比例错误。这个动作比再看一遍注释可靠。
出口取模,挡不住累加器走到边界
还有一种代码很容易得到好评,因为它短:
accum += delta;
position = accum % counts_per_turn;
短时间看,它确实能工作。位置连续,正反转也能处理,程序不必每圈清零。
只是 accum 还在一直长。最后一行的取模,发生在它已经增长之后。只要它是有符号整数,就绕不开边界。
如果一圈计数恰好是 2 的幂,某些边界会碰巧落在整圈位置,问题可能迟迟不出现。下面继续用 96 线、四倍频这个独立示意数:一圈计数是 384,若采用 30 位有符号累加器,2^30 除以 384 余 256。累加器翻过边界以后,取模结果会多出这 256 个计数,换算成角度是:
360° × 256 / 384 = 240°
240° 已经不是量化噪声。这个数是为了把边界问题算清楚,不是某一颗器件的现场读数。它也未必在普通动作里出现,短时间台架测试很可能抓不到。一直单向转的耐久台、输送辊、风机,才是需要把运行时间算进去的地方。
这里有个容易混在一起的概念:周期输出可以取模,内部状态却不能因此假设自己永远安全。更稳妥的写法,是让累加器始终保持在有限范围,或使用明确处理环绕的无符号差分。
三条输出要分开验,统一格式留到最后
把三条输出都做成一个角度类型,对上层软件很友好。我并不反对这样做。真正需要警惕的是,接口统一以后,测试表也跟着只剩一个“角度误差”。
I²C 要看原始角度字和机械参考角;PWM 要看周期、占空比端点,以及解码后的量化步长;ABZ 要看实际计数模式、每圈原始计数、正反转,还有长时间单向运行。
这几项放在同一张表里,反而能看出问题到底藏在哪里。I²C 读数准,说明芯片的数字角度通路可能没问题;ABZ 只差一半,优先查计数模式和每圈常量;短时间正常、长时间跳角,则把视线移到累加器边界。
我更愿意把“统一格式”和“统一精度”拆成两列。前一列是软件接口设计,后一列得由传感器、输出电路、定时器和机械参考一起证明。两列写在一起,评审时很容易把格式当成精度,等客户发现问题再回头找比例关系,成本就高了。
公开来源
ST:STM32G0 Reference Manual,Encoder interface mode——说明编码器接口可选择只数 TI1、只数 TI2 或同时数两路边沿。
ST:Introduction to timers in STM32 microcontrollers——说明编码器模式 3 对应 X4 分辨率。
Microchip:Interfacing Quadrature Encoder Using CCL with TCA and TCB——说明增量编码器的正交解码与计数实现。

关注公众号「如是有为」
微信扫一扫,新文章先在公众号发出。