共计 2110 个字符,预计需要花费 6 分钟才能阅读完成。
背景痛点
AB 相编码器是电机控制中常用的位置和速度传感器,通过两路相位差 90 度的脉冲信号(A 相和 B 相)提供精确的运动反馈。但在实际应用中,新手常遇到以下问题:

- 信号毛刺:由于电机干扰或接线不良,AB 相信号可能出现抖动,导致计数错误
- 方向误判:软件解码时容易因信号延迟造成方向判断失误
- 低速精度差:常规测频法在低速时分辨率不足,导致转速波动明显
技术对比:定时器捕获 vs 正交解码
- 定时器捕获法 :通过外部中断捕获脉冲边沿,软件判断相位差
- 优点:适用所有 MCU
-
缺点:CPU 占用高,高速时可能丢失脉冲
-
硬件正交解码 :利用定时器的编码器接口模式
- 优点:自动处理四倍频和方向判断,零 CPU 占用
- 缺点:需要特定硬件支持(如 STM32 的 TIMx)
核心实现
硬件连接(Arduino Uno 为例)
/* AB 相编码器接线图 */
编码器 A 相 —— D2(外部中断 0)编码器 B 相 —— D3(外部中断 1)编码器 VCC —— 5V
编码器 GND —— GND
/* 推荐增加 RC 滤波(R=1kΩ, C=100nF)*/
STM32 硬件正交解码示例
// PlatformIO 环境配置(platformio.ini)[env:bluepill_f103c8]
platform = ststm32
board = bluepill_f103c8
framework = arduino
// 编码器接口初始化
void setup() {
// 定时器 3 配置为编码器模式
TIM_Encoder_InitTypeDef encoderConfig;
encoderConfig.EncoderMode = TIM_ENCODERMODE_TI12;
encoderConfig.IC1Polarity = TIM_ICPOLARITY_RISING;
encoderConfig.IC2Polarity = TIM_ICPOLARITY_RISING;
encoderConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
encoderConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
encoderConfig.IC1Prescaler = TIM_ICPSC_DIV1;
encoderConfig.IC2Prescaler = TIM_ICPSC_DIV1;
encoderConfig.IC1Filter = 6; // 适当滤波
encoderConfig.IC2Filter = 6;
HAL_TIM_Encoder_Init(&htim3, &encoderConfig);
HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_ALL);
}
// 读取计数值(注意处理溢出)int32_t getEncoderCount() {
static uint16_t lastCnt = 0;
static int32_t totalCnt = 0;
uint16_t currCnt = TIM3->CNT;
int16_t diff = (int16_t)(currCnt - lastCnt);
totalCnt += diff;
lastCnt = currCnt;
return totalCnt;
}
转速计算公式
RPM = (Δcount × 60) / (PPR × 4 × Δt)
其中:Δcount = 采样周期内的脉冲变化量
PPR = 编码器每转脉冲数(如 500 线)4 = 四倍频系数
Δt = 采样时间 (s)
避坑指南
- 信号滤波参数选择
- 典型值:R=1kΩ,C=100nF(截止频率≈1.6kHz)
-
高速场合:减小电容值(如 10nF)避免信号延迟
-
中断防溢出处理
// Arduino 外部中断示例 volatile int32_t encoderCount = 0; void interruptA() { static uint8_t lastState = 0; uint8_t currState = digitalRead(pinA) | (digitalRead(pinB) << 1); // 状态机实现四倍频解码 if((lastState == 0x00 && currState == 0x01) || (lastState == 0x01 && currState == 0x03) || (lastState == 0x03 && currState == 0x02) || (lastState == 0x02 && currState == 0x00)) {encoderCount++;} else {encoderCount--;} lastState = currState; } -
低速测周法策略
- 当 RPM < 100 时,改为测量单个脉冲周期
- 计算公式:RPM = 60 / (PPR × 4 × T)
测试验证
使用示波器观察 AB 相信号:
– 原始信号:可能带有毛刺(示波器触发设置建议:A 相上升沿)
– 滤波后:波形干净,相位差保持 90°
扩展思考:ESP32 移植要点
- 利用 PCNT 外设实现硬件计数
- 注意 ESP32 的引脚中断响应速度较慢,建议启用 RTOS 任务专用于编码器处理
- 双核特性可利用:Core0 处理计数,Core1 计算转速
结语
通过硬件正交解码配合适当的信号处理,可以实现稳定可靠的 AB 相编码器测速。实际项目中还需考虑机械安装同心度、电缆屏蔽等非电气因素。建议先用示波器验证信号质量,再逐步优化算法参数。
正文完
