共计 2746 个字符,预计需要花费 7 分钟才能阅读完成。
背景痛点
在工业自动化中,520 电机编码器常用于精确控制电机转速和位置。然而,在实际应用中,开发者常常会遇到以下问题:

- 信号丢失 :电机高速旋转时,编码器输出脉冲频率可能超过 MCU 的捕获能力,导致脉冲丢失
- 累计误差 :长时间运行后,增量式编码器的小误差会逐渐累积,影响定位精度
- 安装偏差 :机械安装时的微小偏心会导致输出波形畸变,产生周期性误差
- 环境干扰 :工业现场电磁环境复杂,容易引入噪声干扰信号质量
技术选型
编码器主要分为光电式和磁电式两大类,各有优缺点:
光电式编码器
- 优点 :
- 分辨率高,最高可达 5000PPR 以上
- 信号质量好,波形规整
- 温度稳定性好
- 缺点 :
- 对灰尘和油污敏感
- 机械结构复杂,抗震性较差
- 价格较高
磁电式编码器
- 优点 :
- 抗污染能力强
- 结构简单,抗震性好
- 成本较低
- 缺点 :
- 分辨率相对较低
- 温度变化会影响磁特性
- 信号易受外部磁场干扰
对于 520 电机,在清洁环境下追求高精度可选择光电式;在恶劣环境或成本敏感场合推荐磁电式。
硬件设计
带滤波的编码器接口电路
[编码器] ----> 100Ω 电阻 ----> 10nF 电容 ----> [MCU]
| |
V V
GND GND
- 100Ω 电阻限制输入电流
- 10nF 电容滤除高频干扰
- 建议使用差分输入提高抗干扰能力
4 倍频计数原理
通过检测 A、B 两相信号的上升沿和下降沿,可以将原始分辨率提高 4 倍:
- A 相上升沿:计数 +1
- B 相上升沿:计数 +1
- A 相下降沿:计数 +1
- B 相下降沿:计数 +1
这样 500PPR 的编码器可实现 2000 个计数 / 转。
代码实现
STM32 HAL 库配置
// 编码器模式定时器初始化
TIM_Encoder_InitTypeDef sEncoderConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
// 使用 TIM3,通道 1 和 2 接编码器 A、B 相
htim3.Instance = TIM3;
htim3.Init.Prescaler = 0;
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = 0xFFFF; // 16 位最大值
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
// 编码器接口配置
sEncoderConfig.EncoderMode = TIM_ENCODERMODE_TI12; // 双通道计数模式
sEncoderConfig.IC1Polarity = TIM_ICPOLARITY_RISING;
sEncoderConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
sEncoderConfig.IC1Prescaler = TIM_ICPSC_DIV1;
sEncoderConfig.IC1Filter = 6; // 适当滤波
// 通道 2 配置相同
sEncoderConfig.IC2Polarity = TIM_ICPOLARITY_RISING;
sEncoderConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
sEncoderConfig.IC2Prescaler = TIM_ICPSC_DIV1;
sEncoderConfig.IC2Filter = 6;
// 应用配置
HAL_TIM_Encoder_Init(&htim3, &sEncoderConfig);
// 启动编码器接口
HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_ALL);
带滤波的转速计算
#define ENCODER_PPR 500 // 编码器每转脉冲数
#define SAMPLE_CNT 5 // 滑动平均样本数
int32_t speed_buf[SAMPLE_CNT] = {0};
uint8_t buf_idx = 0;
// 获取滤波后的转速 (RPM)
int32_t get_filtered_speed(void) {
static int32_t last_cnt = 0;
int32_t current_cnt = __HAL_TIM_GET_COUNTER(&htim3);
int32_t delta = current_cnt - last_cnt;
// 处理计数器溢出
if(delta < -0x7FFF) delta += 0xFFFF;
else if(delta > 0x7FFF) delta -= 0xFFFF;
// 计算瞬时转速 (RPM = delta_cnt * 60 / (PPR*4 * sample_time))
int32_t inst_speed = delta * 60 * 1000 / (ENCODER_PPR * 4 * MEASURE_PERIOD_MS);
// 滑动平均滤波
speed_buf[buf_idx++ % SAMPLE_CNT] = inst_speed;
int32_t sum = 0;
for(int i=0; i<SAMPLE_CNT; i++) {sum += speed_buf[i];
}
last_cnt = current_cnt;
return sum / SAMPLE_CNT;
}
生产考量
线数选择与中断响应
- 低线数 (500PPR 以下):适合低速应用,中断压力小
- 高线数 (1000PPR 以上):需要评估 MCU 中断处理能力
计算公式:
最大中断频率 = (编码器 PPR × 4 × 最大转速 RPM) / 60
例如 1000PPR 编码器在 3000RPM 时:
(1000×4×3000)/60 = 200kHz
确保 MCU 能够处理这个中断频率。
EMC 防护布局建议
- 编码器信号线远离电源线和电机线
- 使用双绞线或屏蔽线传输信号
- 在 PCB 上信号线旁铺设地线
- 连接器处放置 TVS 二极管防护
- 电源入口加装共模电感
避坑指南
安装偏心问题
症状:转速波动呈现周期性变化
解决方案:
- 使用千分表检查轴向和径向跳动
- 采用柔性联轴器补偿微小偏差
- 安装时用示波器观察波形对称性
Z 相信号消累计误差
每转一圈的 Z 相脉冲可复位计数器,消除长期累计误差。实现方法:
- 将 Z 相接外部中断引脚
- 中断服务函数中读取编码器值
- 计算与理论位置的偏差进行补偿
// Z 相中断服务函数示例
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {if(GPIO_Pin == Z_PIN_Pin) {int32_t curr_pos = __HAL_TIM_GET_COUNTER(&htim3);
position_offset = (curr_pos - EXPECTED_Z_POS) % (ENCODER_PPR*4);
}
}
思考题
如何实现 0.1°角度分辨率?
提示:
1. 考虑编码器线数与机械减速比的关系
2. 研究插值算法提高分辨率
3. 评估系统对微小振动的敏感度
4. 温度补偿对精度的影响
正文完
