共计 1346 个字符,预计需要花费 4 分钟才能阅读完成。
认识编码器信号
第一次用示波器看编码器输出时,我盯着 AB 相的方波发了半天呆。后来发现这两个信号藏着大玄机——它们其实是相位差 90°的脉冲序列(专业叫法叫正交信号)。当电机正转时,A 相上升沿对应 B 相低电平;反转时则相反。这个特性让我们可以通过简单的逻辑判断实现方向检测。

更妙的是,利用 AB 相的四个边沿(上升下降各两次),可以实现 4 倍频计数。比如 1000 线的编码器,转一圈就能产生 4000 个计数脉冲,分辨率直接翻了 4 倍!
硬件设计:从防干扰到安全隔离
光电隔离电路
- 准备 PC817 光耦或者 6N137 高速光耦
- 编码器侧接限流电阻(通常 1 -2kΩ)
- MCU 侧上拉电阻建议 4.7kΩ
- 注意光耦传输延迟,高速场合选型要谨慎
布线抗干扰技巧
- 信号线一定要双绞!我的血泪教训:平行走线在电机启动时误计数暴增
- 接地采用单点星型连接,避免地环路干扰
- 电源端加 0.1μF 陶瓷电容滤波
STM32 软件实现
定时器配置(HAL 库版)
// TIM3 编码器模式初始化
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 = 6; // 适当滤波防抖动
// 类似配置 IC2 参数...
HAL_TIM_Encoder_Init(&htim3, &sConfig);
HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_ALL);
32 位计数器实现
定时器只有 16 位怎么办?用这个状态机:
- 开启定时器溢出中断
- 定义 int32_t 全局变量 totalCount
- 溢出中断里根据方向标志±65536
- 主程序读取 CNT 寄存器与 totalCount 求和
新手避坑指南
机械安装三要素
- 用百分表检查电机轴与编码器同心度(偏差 <0.1mm)
- 联轴器要用弹性材质缓冲振动
- 避免轴向受力,编码器不是轴承!
高速信号处理
测试发现 2000 线编码器在 3000RPM 时:
- 信号上升沿变缓导致计数丢失
- 解决方案:降低上拉电阻值(改 2.2kΩ)
- 必要时改用推挽输出的编码器
PID 闭环控制实战
CMSIS-DSP 版 PID
#include "arm_math.h"
arm_pid_instance_f32 pid;
void PID_Init(){
pid.Kp = 1.5f;
pid.Ki = 0.2f;
pid.Kd = 0.01f;
arm_pid_init_f32(&pid, 1);
}
float PID_Update(float error){return arm_pid_f32(&pid, error);
}
双环控制技巧
- 内环速度控制周期 1ms(PWM 频率)
- 外环位置控制周期 10ms
- 串口调试时先调 P,出现等幅振荡后加 D
进阶思考
最近在研究用 Z 相(每转一个脉冲)配合 EEPROM 实现多圈记忆。另外发现 SSI 总线编码器虽然接线简单,但响应速度比增量式慢,大家觉得在什么场景下必须用绝对值编码器呢?
(文中代码实测通过,完整工程文件可私信获取)
正文完
发表至: 未分类
近两天内
