共计 2330 个字符,预计需要花费 6 分钟才能阅读完成。
背景痛点
在电机控制系统中,精准测速是实现闭环控制的关键。但在使用 51 编码器进行电机测速时,开发者常常会遇到以下三大挑战:

- 脉冲边缘抖动 :由于机械振动或电气噪声,编码器输出的脉冲信号边缘可能出现抖动,导致计数不准确。
- 低速采样误差 :在低速运行时,脉冲间隔较长,传统的定时采样方法容易遗漏脉冲,导致测速精度下降。
- 高速脉冲丢失 :高速运行时,脉冲频率较高,软件计数可能无法及时响应,导致脉冲丢失。
为了解决这些问题,我们对比了软件计数和硬件捕获方案的优缺点:
- 软件计数 :实现简单,但受限于 CPU 的中断响应速度和软件处理能力,容易在高速或高负载情况下丢失脉冲。
- 硬件捕获 :利用 STM32 的定时器硬件编码器接口,能够自动捕获脉冲信号,大大减轻 CPU 负担,提高测速精度和可靠性。
技术方案
1. STM32 硬件编码器接口配置
STM32 的定时器(TIM)模块支持硬件编码器接口,可以自动识别编码器的 A / B 相脉冲信号,并实现四倍频计数。以下是关键参数配置:
- ARR(自动重装载值):设置为编码器线数的 4 倍(四倍频计数)。
- CCR(捕获 / 比较寄存器):用于捕获脉冲边沿时间。
配置示例(以 TIM2 为例):
TIM_Encoder_InitTypeDef encoderConfig;
encoderConfig.EncoderMode = TIM_ENCODERMODE_TI12; // 使用 A / B 相四倍频
encoderConfig.IC1Polarity = TIM_ICPOLARITY_RISING;
encoderConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
encoderConfig.IC1Prescaler = TIM_ICPSC_DIV1;
encoderConfig.IC1Filter = 6; // 设置滤波器,抑制噪声
encoderConfig.IC2Polarity = TIM_ICPOLARITY_RISING;
encoderConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
encoderConfig.IC2Prescaler = TIM_ICPSC_DIV1;
encoderConfig.IC2Filter = 6;
HAL_TIM_Encoder_Init(&htim2, &encoderConfig);
HAL_TIM_Encoder_Start(&htim2, TIM_CHANNEL_ALL);
2. 四倍频计数原理
四倍频计数通过对 A / B 相脉冲的上升沿和下降沿进行捕获,将原始编码器线数乘以 4,从而提高测速分辨率。例如,500 线的编码器在四倍频后等效于 2000 线。
3. 滑动平均滤波算法
为了进一步抑制噪声,可以采用滑动平均滤波算法。窗口大小的选择需要权衡响应速度和滤波效果:
- 小窗口(如 5 -10):响应快,但滤波效果有限。
- 大窗口(如 20-30):滤波效果好,但会引入延迟。
实现示例:
#define FILTER_WINDOW_SIZE 10
uint32_t filterBuffer[FILTER_WINDOW_SIZE];
uint32_t filterIndex = 0;
uint32_t filterSum = 0;
uint32_t slidingFilter(uint32_t newValue) {filterSum -= filterBuffer[filterIndex];
filterBuffer[filterIndex] = newValue;
filterSum += newValue;
filterIndex = (filterIndex + 1) % FILTER_WINDOW_SIZE;
return filterSum / FILTER_WINDOW_SIZE;
}
代码实现
1. 速度计算公式
电机转速(RPM)的计算公式如下:
RPM = (脉冲数 × 60) / (编码线数 × 采样周期)
其中,脉冲数为四倍频后的计数值,编码线数为编码器的物理线数,采样周期为测速的时间间隔(单位:秒)。
2. 中断服务程序中的临界区保护
在中断服务程序中,为了避免竞态条件,需要对关键数据进行保护。例如:
void TIM2_IRQHandler(void) {if (__HAL_TIM_GET_FLAG(&htim2, TIM_FLAG_UPDATE) != RESET) {__HAL_TIM_CLEAR_FLAG(&htim2, TIM_FLAG_UPDATE);
uint32_t count = TIM2->CNT; // 读取当前计数值
__disable_irq(); // 进入临界区
pulseCount = count;
__enable_irq(); // 退出临界区}
}
性能优化
1. 不同 PWM 频率下的测速误差
以下是不同 PWM 频率下的测速误差对比表:
| PWM 频率 (kHz) | 测速误差 (RPM) |
|---|---|
| 1 | ±0.5 |
| 5 | ±0.2 |
| 10 | ±0.1 |
| 20 | ±0.1 |
2. 电源噪声抑制的 PCB 布局建议
- 电源去耦 :在编码器电源引脚附近放置 0.1μF 和 10μF 的电容。
- 信号走线 :尽量缩短编码器信号线的长度,避免与高频信号线平行走线。
- 接地 :使用星型接地或单点接地,减少地环路干扰。
避坑指南
1. 常见配置错误
- GPIO 模式设置不当 :编码器接口的 GPIO 应配置为复用推挽输出模式,而非普通输入模式。
- 中断优先级冲突 :确保编码器中断的优先级高于其他可能阻塞的中断。
2. 过零检测的软件补偿
在低速运行时,编码器可能出现过零现象(计数值从 ARR 跳变到 0 或反之)。为了避免误判,可以在软件中检测计数值的跳变,并进行补偿。
思考题
- 如何扩展方案实现双向测速?
- 在无硬件编码器接口的 MCU 上如何实现类似功能?
希望这篇实战指南能帮助你在电机控制项目中实现高精度测速。如果有任何问题或建议,欢迎在评论区交流!
正文完
