笔记 / 嵌入式Encoder正交解码测速

引言

算一笔账:2500 线增量编码器、4 倍频解码、电机 6000 rpm 满速,每秒 100 转 × 10000 个计数 = 1 MHz 的边沿流。用外部中断数边沿,CPU 每 1 μs 被打断一次,没有余力执行其它代码。降倍频也不行:分辨率直接砍半,速度环低速就抖。

出路是让硬件替 CPU 数。STM32 通用定时器自带编码器接口模式:两路正交信号直接接进定时器,边沿由硬件计数,方向由硬件判别,CPU 只需按控制周期读一次计数器。1 kHz 的 FOC 速度环,读一次 CNT 的开销接近于零。

一、编码器是什么

增量式光电编码器的结构:光源(LED)+ 透镜把光聚成平行光束,打在码盘上。码盘是一个刻有辐射状透光缝隙的圆盘,随转轴旋转;缝隙后面的固定光栅与码盘缝隙形成遮光/透光节拍,光电检测器件把光脉冲变成电脉冲,经转换电路整形输出。

透射式光电编码器结构(AKM 编码器技术教程 图4-1):LED 发光元件经透镜形成平行光,穿过随轴旋转的码盘与固定光栅,由光电检测器 A/B 两组检出;两组缝隙错开 1/4 节距,故 A/B 输出相位差 90°

两组检测缝隙在空间上错开 1/4 个节距,所以输出信号 A、B 相位差恒为 90°,这就是「正交」的物理来源。多数编码器还有第三路输出 Z(Index,零位脉冲):码盘上单独开一条缝,每转输出一个窄脉冲,作为角度参考点。

增量式编码器输出信号:码盘缝隙与 A/B/Z 三路波形——A/B 相位差 90°,Z 每转一个脉冲作零位参考

两类编码器的差别:

类型原理上电后位置典型场景
增量式数脉冲,只输出”变了多少”未知,需回零电机速度环、滚轮、3D 打印机
绝对式码盘每一位独立编码(常为格雷码)天然可知机器人关节、多圈计数、断电保持

绝对式单价高、线束多,电机控制里增量式仍是主流,代价是要额外处理两件事:上电时位置未知,以及丢脉冲会累积成误差。这两点在后面的章节里都会涉及。

二、正交信号与 4 倍频

A/B 相位差 90° 携带了方向信息:正转时 A 超前 B,反转时 B 超前 A。判别逻辑是:在谁的边沿上,看另一路的电平。A 上升沿时 B 为低是一个方向,B 为高是另一个方向。

一个 A 周期(码盘一条线)内有 4 个边沿:A↑、A↓、B↑、B↓。全都不放过,就是 4 倍频:

解码方式每线计数2500 线编码器每转计数
仅 A 相上升沿1×2500
A 相双沿2×5000
A/B 全部边沿4×10000

线刻多密决定了物理分辨率,倍频只是把每个线周期细分成 4 份。它的实际作用是把量化误差压缩到 1/4 线以内,低速时速度估算显著变细。

线数与倍频必须一起核对。拿到一颗新编码器,先手动转一整圈看 CNT 增量:如果不等于「线数 × 4」,多半是倍频模式配错,速度换算会全线出错。

三、STM32 编码器接口模式

编码器接口建立在通用定时器的计数与输入捕获单元上,定时器基础见 单片机定时器与中断系统详解。F1 的 TIM2~TIM5 都支持编码器接口。配置只有两个要点:从模式控制寄存器 SMCR 的 SMS 位选计数方式,CC1/CC2 把两路信号接成输入捕获:

SMS计数行为倍频
001仅 TI2 边沿计数,方向由 TI1 电平决定2×
010仅 TI1 边沿计数,方向由 TI2 电平决定2×
011TI1/TI2 边沿都计数4×

编码器接口模式的计数行为(RM0008 Figure 93):TI1/TI2 正交输入与计数器 CNT 的增减关系——正转阶梯上行、反转下行,抖动往返自动抵消

这张图对应编码器接口的三个特性:

  • 方向全自动:正转计数器加、反转减,抖动(正负边沿来回)自动抵消,不怕机械振动
  • DIR 位只读:编码器模式下方向由硬件管理,读 CR1 的 DIR 位可以知道当前转向,但写它没用
  • 输入滤波器可用:CCMR 里的 IC1F/IC2F 对输入做 N 次采样多数表决,电机碳刷火花、长线毛刺在这里挡掉

方向反了不必改接线:把 IC1Polarity 反转,等效于 A/B 相位对调,计数方向随之反转(RM0008 Figure 94 专门画了这件事)。改寄存器比重接编码器线方便。

四、测速三法

位置靠读 CNT 得到,速度需要另外计算。常用的有三种方法:

方法原理强项弱项
M 法(测频)固定时间窗 T 内数计数增量 ΔC高速精度好,实现最简单低速窗内脉冲少,误差大
T 法(测周)用高频时钟测相邻脉冲的间隔低速精度好高速周期太短,误差大
M/T 法同时测 ΔC 和 elapsed 时间,两者相除全速段一致实现最复杂

M 法相当于频率计在固定闸门时间内数脉冲,T 法相当于用高频时钟测量单个周期。两者的误差来源正好相反,低速时 M 法窗内脉冲太少,高速时 T 法的周期太短,所以有了兼顾全速段的 M/T 法。

M 法换算公式:

转速(rpm) = ΔC / (C_e × T) × 60
// C_e = 每转计数(线数 × 倍频),T = 采样窗口秒数

代入实数:10000 counts/rev、10 ms 窗口。1200 rpm 时 ΔC = 2000,±1 count 的量化误差只有 ±0.05%;降到 12 rpm,ΔC = 20,误差飙到 ±5%,速度环开始发抖,这就是低速要换 T 法或拉长窗口的原因。

T 法反过来:1 MHz 时钟测脉冲间隔,间隔 6000 个刻度 = 1 rpm,低速段测得又稳又准。

工程上多数情况走两条路:控制周期固定(如 1 kHz)用 M 法,代码只有三行;要求全速段精度的场合(力矩估计、观测器)才上 M/T。

五、HAL 配置示例

TIM2 编码器模式,PA0/PA1 接 A/B,4 倍频:

// 1. 时钟与引脚:PA0=TIM2_CH1(A), PA1=TIM2_CH2(B)
__HAL_RCC_TIM2_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();

GPIO_InitTypeDef gpio = {0};
gpio.Pin = GPIO_PIN_0 | GPIO_PIN_1;
gpio.Mode = GPIO_MODE_INPUT;      // F1 输入捕获引脚配成输入即可
gpio.Pull = GPIO_PULLUP;          // 开路输出编码器必须上拉
HAL_GPIO_Init(GPIOA, &gpio);

// 2. 编码器模式:SMS=011,双边沿双通道 = 4 倍频
TIM_Encoder_InitTypeDef enc = {0};
htim2.Instance = TIM2;
htim2.Init.Prescaler = 0;
htim2.Init.Period = 0xFFFF;                // 16 位计数器,ARR 拉满让回卷均匀
enc.EncoderMode = TIM_ENCODERMODE_TI12;
enc.IC1Polarity = TIM_ICPOLARITY_RISING;   // 反转方向就改这里
enc.IC1Selection = TIM_ICSELECTION_DIRECTTI;
enc.IC1Filter = 0x0F;                      // 最强输入滤波,抗长线毛刺
enc.IC2Polarity = TIM_ICPOLARITY_RISING;
enc.IC2Selection = TIM_ICSELECTION_DIRECTTI;
enc.IC2Filter = 0x0F;
HAL_TIM_Encoder_Init(&htim2, &enc);
HAL_TIM_Encoder_Start(&htim2, TIM_CHANNEL_ALL);

控制周期里读速度——差值法,16 位回卷由有符号溢出自然吸收:

static uint16_t last_cnt = 0;

uint16_t now = __HAL_TIM_GET_COUNTER(&htim2);
int16_t diff = (int16_t)(now - last_cnt);   // 回卷自动变号,不用 if 判断
last_cnt = now;
total_counts += diff;                       // int32_t 多圈累计位置

// 1 kHz 控制周期,10000 counts/rev:
float rpm = (float)diff * 60.0f / 10000.0f * 1000.0f;

Z 脉冲接 EXTI(或定时器 CH3 输入捕获,见 输出比较与输入捕获):中断里比对 CNT 与理论值,把累计误差一次清零。多圈场景下每转做一次校零,丢脉冲造成的漂移就被限制在一转之内,不会逐圈累加。

六、常见问题与注意事项

问题原因解决
位置读数来回抖、方向乱跳振动边沿或长线毛刺加大 IC1F/IC2F 滤波;信号线用双绞屏蔽
速度换算偏差固定比例线数×倍频配错手转一圈验证 CNT 增量
位置缓慢漂移干扰丢脉冲、机械打滑差分传输 + Z 脉冲校零
方向反了A/B 接反反转 IC1Polarity,不用动线
低速时速度为 0 或剧烈跳动M 法窗内脉冲太少拉长窗口、换 T 法/M-T 法
上电位置未知增量式原理性限制上电回零流程,或换绝对式编码器

两点工程经验:

  • 长线必须差分:编码器装在电机轴上,驱动板在几米外,单端信号沿电机线束走容易耦合干扰。工业编码器标配 RS-422 差分(A+/A−/B+/B−/Z+/Z−),板端用 AM26LV32 这类差分接收器收回来再进定时器
  • 编码器接口只是把计数搬进了外设,速度环的性能还取决于 PID 算法的基本原理和数学描述 的参数整定和 FOC 磁场定向控制的 C 语言实现 的电流环带宽,位置反馈的准确性是这两者的前提

总结

增量编码器把转动转换成两路正交脉冲,定时器的编码器接口把数脉冲的工作从 CPU 移到硬件:SMS 选倍频,CCx 配滤波与极性,CNT 给出位置,对 CNT 做差分得到速度。测速方法按速度段选 M 法、T 法或 M/T 法,精度的下限由「线数 × 倍频」决定。