4、增量式编码器详解:增量式编码器的结构、工作原理、零位脉冲(Z相)的作用

增量式编码器,说白了就是只告诉你“动了多少”,不告诉你“现在在哪”。它不像绝对式编码器那样一开机就知道位置,而是需要你从零开始数脉冲。很多刚入行的工程师觉得它不如绝对式高级,但我个人觉得,增量式在速度控制和低成本场景下,绝对是个好选择。

我最早接触增量式编码器是在一个伺服电机项目里。当时选型没注意Z相,结果每次断电重启都要手动回零,折腾了好几天。嗯,这里面的坑,咱们今天一个一个说清楚。

4.1 增量式编码器的结构

增量式编码器的内部结构其实不复杂。核心就三样东西:码盘、发光管和光敏接收管。码盘上刻着一圈一圈的透光和不透光条纹,像个小齿轮。发光管一照,接收管就能检测到光脉冲。

你想想看,码盘转一圈,接收管就输出一串脉冲。脉冲的个数,就代表了转过的角度。这就是增量式编码器最基础的原理。

核心结构组成:

  • 码盘(光栅盘):玻璃或金属材质,上面刻有等间距的透光/不透光条纹。
  • 发光源:通常是LED,发出稳定的光束。
  • 光敏接收器:将光信号转换为电信号,输出方波脉冲。
  • 信号处理电路:对原始信号进行整形、放大、差分输出等处理。

这里有个细节:码盘上的条纹数决定了编码器的分辨率。比如码盘有1000条条纹,那转一圈就输出1000个脉冲。但实际应用中,我们还会通过A、B相的倍频技术把分辨率翻倍甚至翻四倍。这个后面会细说。

4.2 工作原理:A、B相与相位差

增量式编码器通常输出两路信号:A相和B相。这两路信号是正交的,也就是相位差90度。为什么要有两路?因为单靠一路脉冲,你只能知道转了多少,但不知道往哪转。

我举个例子:A相上升沿时,如果B相是高电平,那就是正转;如果B相是低电平,那就是反转。这就是所谓的“正交解码”。

判断旋转方向的方法:

  • A相超前B相90° → 正转(顺时针)
  • B相超前A相90° → 反转(逆时针)

在实际项目中,我习惯用示波器同时抓A、B两路波形,一眼就能看出方向对不对。

为什么会这样?因为A、B相的相位关系是固定的。你只要检测A相和B相的边沿顺序,就能确定方向。这也是增量式编码器能实现“双向计数”的基础。

下面这张图展示了A、B相和Z相的关系,以及正反转时的波形差异。

增量式编码器A、B、Z相波形图 增量式编码器A、B、Z相波形示意图 正转(A超前B) A相 B相(滞后90°) 反转(B超前A) A相 B相(超前90°) Z相(零位脉冲) 每圈一个脉冲,用于归零 关键说明 • A相和B相相位差固定为90° • 通过检测边沿顺序判断方向 • Z相每圈只出现一次 • 可用于断电后的位置恢复 倍频方式: • 1倍频:只计A相上升沿 • 2倍频:计A相上升+下降沿 • 4倍频:计A、B相所有边沿

4.3 零位脉冲(Z相)的作用

Z相,也叫零位脉冲或索引脉冲。它每圈只输出一个脉冲,位置固定。它的作用说白了就是:给你一个绝对的参考点。

增量式编码器本身没有绝对位置信息。断电后重新上电,你只知道从当前位置开始数脉冲,但不知道这个位置对应机械的哪个角度。这时候Z相就派上用场了。

Z相使用中的常见坑:

  • Z相脉冲宽度很窄:通常只有1个A相脉冲的宽度,采样频率不够容易漏掉。
  • Z相位置与机械零点的对应关系:安装时如果没对齐,每次回零都会偏一个固定角度。
  • 多圈场景下的Z相使用:如果电机转了很多圈,Z相只能告诉你“这一圈”的零点,不能告诉你“第几圈”。

我曾经在一个AGV小车的轮子编码器上吃过亏。当时没接Z相,每次断电重启后,小车都不知道轮子转到哪了,只能靠限位开关硬碰硬找零。后来加了Z相,配合软件里的“找零程序”,问题就解决了。

4.4 增量式编码器的选型要点

选型时,我一般会关注这几个参数:

参数 说明 我的建议
分辨率(PPR) 每圈脉冲数,决定位置精度 根据系统要求的定位精度反推,留20%余量
输出类型 NPN、PNP、推挽、差分等 长距离传输用差分(RS-422),抗干扰好
Z相有无 是否需要零位参考 只要断电后需要回零,就必须有Z相
防护等级 IP等级,防尘防水 工业环境至少IP54,户外建议IP65以上
最高响应频率 编码器能输出的最高脉冲频率 要大于电机最高转速×分辨率,否则会丢脉冲

一个实用的选型公式:

最高转速(RPM)× 分辨率(PPR)÷ 60 = 最高输出频率(Hz)

这个频率必须小于控制器计数器的最大输入频率,否则会丢步。

4.5 信号处理实战:如何正确读取增量信号

读取增量式编码器的信号,看起来简单,但实际项目中容易出问题。我总结了几条经验:

  1. 硬件滤波不能省:编码器信号在长线传输时容易受干扰,建议在输入端加RC低通滤波,时间常数取1~10μs。
  2. 差分信号优先:如果距离超过2米,一定要用差分输出(A+、A-、B+、B-、Z+、Z-),抗共模干扰能力强。
  3. 软件去抖:在中断服务程序里做边沿检测时,加一个简单的延时去抖,防止毛刺导致误计数。
  4. Z相中断优先级最高:Z相脉冲很窄,如果被其他中断打断,可能就漏掉了。我习惯把Z相中断设为最高优先级。

下面是一个简单的STM32读取增量式编码器的代码片段,用的是定时器编码器模式:

// STM32 定时器编码器模式配置示例
void Encoder_Init(void)
{
    TIM_EncoderInterfaceConfigTypeDef sEncoderConfig;
    
    // 使能定时器时钟
    __HAL_RCC_TIM3_CLK_ENABLE();
    
    // 配置编码器模式
    sEncoderConfig.EncoderMode = TIM_ENCODERMODE_TI12;  // 4倍频模式
    sEncoderConfig.IC1Polarity = TIM_ICPOLARITY_RISING;
    sEncoderConfig.IC2Polarity = TIM_ICPOLARITY_RISING;
    sEncoderConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
    sEncoderConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
    sEncoderConfig.IC1Prescaler = TIM_ICPSC_DIV1;
    sEncoderConfig.IC2Prescaler = TIM_ICPSC_DIV1;
    sEncoderConfig.IC1Filter = 0x0F;  // 硬件滤波,降低干扰
    sEncoderConfig.IC2Filter = 0x0F;
    
    HAL_TIM_Encoder_Init(&htim3, &sEncoderConfig);
    HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_ALL);
}

// 读取当前计数值
int32_t Encoder_GetCount(void)
{
    return (int32_t)__HAL_TIM_GET_COUNTER(&htim3);
}

这段代码里,我特别把滤波系数设成了0x0F,也就是最长的采样窗口。为什么?因为工业现场的电噪声太厉害了,不加滤波的话,计数器会莫名其妙地跳变。你想想看,一个本来静止的电机,编码器读数却在来回跳,那控制就没法做了。

4.6 避坑指南:增量式编码器常见问题

我曾经踩过的坑,分享给你:

  • 坑1:Z相脉冲被漏掉——解决方案:用Z相触发外部中断,并在中断里锁存当前计数值。
  • 坑2:长线传输导致信号畸变——解决方案:改用差分输出,并在接收端加终端电阻(120Ω)。
  • 坑3:编码器安装偏心——解决方案:安装时用千分表打跳动,保证码盘与轴同心。
  • 坑4:电源纹波干扰——解决方案:编码器电源单独供电,或加LC滤波。

嗯,这里要注意:增量式编码器虽然便宜好用,但它有个天生的缺点——断电丢失位置。如果你的系统要求断电后还能记住位置,那就得考虑绝对式编码器,或者加电池备份。

我个人习惯在项目初期就确定好:是否需要断电记忆位置?如果需要,那就别犹豫,直接上绝对式。如果不需要,增量式绝对够用,性价比还高。