4、编码器与反馈:增量式编码器与绝对式编码器的工作原理、ABZ信号解读、转速与位置计算

做电机控制,说白了就是跟位置和速度打交道。你给电机下指令转多少圈,它到底转没转到?转得快不快?这些信息全靠编码器反馈回来。我见过不少新手,算法写得漂亮,结果一上电机就抖,查了半天发现是编码器信号没接对。嗯,这一章咱们就把编码器彻底吃透。

核心要点:编码器是电机控制的「眼睛」。增量式告诉你相对变化,绝对式告诉你当前在哪。两者各有千秋,选型时得看应用场景。

4.1 增量式编码器:简单可靠,但怕掉电

增量式编码器的工作原理,其实挺直观的。它内部有一个码盘,上面刻满了明暗相间的条纹。光通过条纹,被光敏元件接收,就产生了脉冲信号。码盘转一圈,输出固定数量的脉冲。

我个人习惯把增量式编码器想象成一个「计数器」。它不关心你从哪开始,只关心你走了多少步。你想想看,这就像你跑步时用的计步器——它知道你跑了多少步,但不知道你从哪条街开始跑的。

4.1.1 A、B、Z 三路信号解读

增量式编码器通常输出三路信号:A相、B相和Z相。这三路信号各有各的用处。

信号 作用 特点
A相 主脉冲输出,用于计数 每转固定脉冲数(如 1000 PPR)
B相 与A相相差90°相位,用于判向 A超前B为正转,B超前A为反转
Z相 零位脉冲,每圈输出一次 用于位置校准和归零

我在项目中遇到过一个问题:电机正反转判断老是出错。后来发现是A、B两相接反了。其实很简单,用示波器一看就知道——正转时A相上升沿比B相早,反转时B相上升沿比A相早。

我的小技巧:调试时先用低速手动转电机,观察A、B相的相位关系。确认正转方向后,再上高速。这样可以避免因接线错误烧驱动。

4.1.2 转速计算:M法、T法、M/T法

有了脉冲信号,怎么算转速?常用的方法有三种。我最早做项目时只用M法,后来发现低速不准,才补上了T法。

  • M法(测频法):固定时间窗口内数脉冲个数。适合高速,低速时误差大。
  • T法(测周法):测量两个脉冲之间的时间间隔。适合低速,高速时精度下降。
  • M/T法:结合两者,高低速都准。我现在的项目基本都用这个。
// M法转速计算示例(假设编码器 1000 PPR,采样周期 10ms)
uint32_t pulse_count = TIM2->CNT;  // 读取脉冲计数值
float speed_rpm = (pulse_count * 60.0f) / (1000 * 0.01f);
// 解释:60秒/分钟,1000脉冲/圈,0.01秒采样周期

注意:M法在低速时,如果采样周期内只抓到几个脉冲,误差会很大。我曾经在 10 RPM 以下用M法,结果转速波动 ±30%,后来换成M/T法才稳定下来。

4.2 绝对式编码器:一上电就知道位置

绝对式编码器和增量式最大的区别在于:它不需要找零位。上电瞬间,你就能读到当前绝对位置。这玩意儿内部用的是格雷码或多圈齿轮结构,每个位置对应唯一的编码值。

你想想看,这就像你手机上的GPS——它直接告诉你当前经纬度,而不是从起点开始算走了多远。对于需要断电记忆位置的应用(比如机械臂、数控机床),绝对式编码器是首选。

4.2.1 单圈 vs 多圈

类型 分辨率 圈数记忆 典型应用
单圈绝对式 12~18 bit(4096~262144 位置/圈) 不记忆圈数 伺服电机、机器人关节
多圈绝对式 单圈 + 12~16 bit 圈数 可记忆最多 4096 圈 数控机床、AGV 导航

我记得有一次做AGV项目,客户要求断电后重新上电,小车必须知道自己的精确位置。增量式编码器做不到,因为一掉电计数值就丢了。最后选了多圈绝对式编码器,通过SSI接口读取,上电直接拿到位置数据,省掉了归零流程。

4.2.2 通信接口:SSI、BiSS、EnDat

绝对式编码器不像增量式那样直接输出脉冲,它需要通过数字接口把位置数据传出来。常见的接口有几种:

  • SSI(同步串行接口):简单、便宜,但速度慢。适合低速应用。
  • BiSS(双向同步串行接口):开源协议,速度快,我最近的项目都在用。
  • EnDat(海德汉专利协议):性能强,但需要授权。高端数控机床常见。

选型建议:如果只是做原型验证,SSI 就够用了。量产产品建议用 BiSS,开源免授权,而且很多 MCU 已经有硬件支持。

4.3 位置计算:从脉冲到角度

不管是增量式还是绝对式,最终都要换算成机械角度。公式其实很简单:

// 增量式编码器位置计算
float angle_deg = (pulse_count % pulses_per_revolution) * (360.0f / pulses_per_revolution);

// 绝对式编码器位置计算(假设 16 bit 分辨率)
uint16_t raw_value = read_encoder_ssi();
float angle_deg = (raw_value * 360.0f) / 65536.0f;

这里有个坑:增量式编码器如果用了Z相归零,记得在Z相中断里把计数值清零。我刚开始做的时候忘了这步,结果每次上电位置都是随机的,电机乱转了好几次才反应过来。

避坑指南:我曾经在高速运行时读取绝对式编码器,发现数据偶尔跳变。后来查出来是通信线太长,信号反射导致误码。解决办法:降低通信速率,或者在接收端加 RC 滤波。

4.4 知识体系总览

下面这张图把编码器的核心逻辑串起来了。你可以看到,增量式和绝对式从原理到应用都有明显区别,但最终都服务于同一个目标:告诉控制器「电机现在在哪、转得多快」。

编码器与反馈知识体系 增量式编码器 绝对式编码器 A/B/Z 三路信号 相对位置,掉电丢失 格雷码 / 多圈齿轮 绝对位置,掉电记忆 转速计算:M法 / T法 / M/T法 位置计算:脉冲计数 → 角度 Z相归零校准 通信接口:SSI / BiSS / EnDat 位置计算:原始值 → 角度 多圈圈数解析 电机位置 & 速度反馈 增量式适合低成本、高速场景;绝对式适合高精度、断电记忆场景

4.5 实际项目中的选型建议

说了这么多理论,最后聊聊实际怎么选。我个人的经验是:

  • 普通直流电机/步进电机:增量式编码器就够了,成本低,控制简单。
  • 伺服电机:建议用绝对式,尤其是多圈绝对式。上电不用找零,省心很多。
  • 机器人关节:必须用绝对式。你总不希望每次开机机器人先来一套「归零动作」吧?
  • 高速主轴:增量式更合适。绝对式通信有延迟,高速下容易丢数据。

最后提醒一句:不管选哪种编码器,信号完整性一定要重视。屏蔽线、差分信号、合理的滤波——这些硬件细节决定了你的控制算法能不能发挥出来。我见过太多人算法写得完美,结果被一根劣质编码器线坑得死去活来。