共计 1547 个字符,预计需要花费 4 分钟才能阅读完成。
背景痛点
在电机控制系统中,AB 双相霍尔编码器是获取转速和位置的关键传感器。但在实际应用中,我们常遇到以下问题:

- 信号抖动 :电机运行时产生的电磁干扰会导致编码器信号出现毛刺
- 相位偏差 :AB 两相信号在传输过程中可能出现微小的相位差
- 高速漏脉冲 :当电机转速较高时,容易丢失脉冲导致计数不准确
传统解决方案存在明显不足:
- 纯硬件滤波虽然简单,但难以兼顾高速和低速场景
- 简单的软件去抖算法在转速变化时效果不稳定
技术方案
硬件层设计
推荐使用二阶 RC 低通滤波电路,参数选择要点:
- 截止频率计算:f_c=1/(2πRC),建议设置为编码器最高信号频率的 3 - 5 倍
- PCB 布局注意事项:
- 滤波电路尽量靠近编码器接口
- 信号线走等长线以减少相位差
- 增加 TVS 二极管防护静电
软件层实现
STM32 定时器的编码器模式配置关键步骤:
- 配置 TIMx_SMCR 寄存器:
- SMS=3(编码器模式 3)
- TS=0(使用 TI1 和 TI2 作为输入源)
- 设置 CCMR1/CCMR2 寄存器:
- CC1S=01, CC2S=01(将 TI1/ 2 映射到 CC1/2)
- IC1F/IC2F 配置输入滤波器
// 寄存器配置示例
TIM1->SMCR |= TIM_SMCR_SMS_1 | TIM_SMCR_SMS_0; // 编码器模式 3
TIM1->CCMR1 |= TIM_CCMR1_CC1S_0 | TIM_CCMR1_CC2S_0; // CC1/ 2 输入模式
动态阈值消抖算法
创新性地采用状态机实现动态阈值调整:
stateDiagram
[*] --> Idle
Idle --> EdgeDetected: 信号边沿
EdgeDetected --> Confirm: 保持时间 > 阈值
Confirm --> Count: 确认有效边沿
Confirm --> Idle: 抖动忽略
Count --> Idle
代码实现
CubeMX 配置
- 定时器配置为 Encoder Mode
- 通道 1 / 2 设为 Input Capture
- 开启定时器中断
// 初始化代码(MISRA- C 兼容)void Encoder_Init(void)
{TIM_Encoder_InitTypeDef sConfig = {0};
sConfig.EncoderMode = TIM_ENCODERMODE_TI12;
sConfig.IC1Polarity = TIM_ICPOLARITY_RISING;
sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
sConfig.IC1Prescaler = TIM_ICPSC_DIV1;
sConfig.IC1Filter = 0x0F; // 适当滤波
// 类似配置 IC2...
HAL_TIM_Encoder_Init(&htim3, &sConfig);
HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_ALL);
}
// 读取计数值(四倍频)int32_t Get_Encoder_Count(void)
{return __HAL_TIM_GET_COUNTER(&htim3) * 4;
}
验证数据
| 转速 (RPM) | 原始误差率 | 优化后误差率 |
|---|---|---|
| 500 | 0.8% | 0.02% |
| 1500 | 2.1% | 0.03% |
| 3000 | 5.7% | 0.05% |
避坑指南
- GPIO 配置 :
- 禁用内部上拉电阻,避免信号边沿变缓
-
配置为浮空输入模式
-
相位差处理 :
- 使用等长电缆连接 AB 相
-
软件中增加±10°的相位容差
-
启停瞬态 :
- 检测到方向突变时启动软件滤波
- 设置速度变化率限制
延伸思考
- 无霍尔方案 :
- 使用滑模观测器估算转子位置
-
结合电流环数据进行补偿
-
Z 相信号应用 :
- 作为机械零点校准
- 实现多圈绝对位置记录
- 配合电池实现断电记忆
总结
通过硬件滤波 + 软件动态阈值的复合方案,我们在多个量产项目中实现了稳定可靠的编码器计数。关键点在于根据实际应用场景调整滤波参数和消抖算法,建议开发时先用示波器观察原始信号特性,再针对性优化。
正文完
