1. 从零开始构建有刷电机闭环控制系统
十年前我第一次接触电机控制时,被这个看似简单却暗藏玄机的领域深深吸引。有刷电机作为最基础的执行机构,其闭环控制是自动化领域的必修课。今天我要分享的这个项目,采用强磁阻AB编码器实现速度和位置双闭环控制,包含了可直接量产的硬件设计和经过实战检验的软件方案。
这个系统特别适合需要精确运动控制的场景,比如智能机器人关节驱动、精密仪器定位等。相比开环控制,闭环系统能实现±0.5%的速度控制精度和±2个脉冲的位置误差,这对于大多数工业应用已经足够。下面我将从硬件选型到软件实现,完整拆解这个项目的技术细节。
2. 硬件架构设计与关键元件选型
2.1 电机与编码器匹配方案
我们选用的是JGB37-520有刷直流电机,额定电压12V,空载转速300RPM。这种电机价格亲民(约50元/台),扭矩适中(0.5kgf·cm),非常适合教学和原型开发。与之配套的是AS5045强磁阻编码器,分辨率1024PPR,通过径向磁铁安装于电机轴端。
关键提示:磁阻编码器安装时需保持磁铁与传感器间距在1-2mm范围内,距离过大会导致信号衰减,过小则可能损坏传感器。
编码器信号处理电路采用SN74LVC2G34双缓冲器进行信号整形,配合10kΩ上拉电阻和0.1μF去耦电容,能有效抑制电机PWM干扰。实测表明,这种配置在电机全速运行时仍能稳定采集信号。
2.2 驱动电路设计要点
驱动部分采用经典的H桥架构,核心元件包括:
- IR2104 MOSFET驱动器
- IRF540N功率MOSFET(Vds=100V, Rds(on)=44mΩ)
- 快恢复二极管FR107
电路设计中几个关键参数计算:
-
栅极电阻选择:
Rg = Vcc/(Qg×fsw) = 12V/(63nC×20kHz) ≈ 10Ω
实际选用10Ω/0.5W电阻 -
死区时间设置:
tdead = Rg×Ciss = 10Ω×1200pF = 12ns
通过IR2104的DT引脚配置为200ns(留有充足余量) -
电流采样电阻:
Rsense = Vref/(Ipeak×Gain) = 3.3V/(5A×20) = 0.033Ω
选用0.03Ω/5W的锰铜电阻
PCB布局时特别注意:
- 功率走线线宽≥2mm(1oz铜厚)
- 栅极驱动回路面积<1cm²
- 编码器信号线与功率线正交布置
3. 软件控制算法实现细节
3.1 编码器信号处理优化
采用STM32F103的TIM2定时器编码器接口模式,配置为:
c复制TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI12,
TIM_ICPolarity_Rising,
TIM_ICPolarity_Rising);
速度计算采用M法测速,在1ms定时中断中:
c复制void TIM3_IRQHandler() {
static int32_t last_count = 0;
int32_t current_count = TIM_GetCounter(TIM2);
speed_rpm = (current_count - last_count)*60000/(1024*采样周期ms);
last_count = current_count;
}
实测技巧:加入数字滤波可显著提高低速稳定性
speed_filtered = 0.2speed_raw + 0.8speed_filtered;
3.2 改进型PID控制器实现
传统PID在电机启停时容易超调,我们采用串级PID结构:
- 外环:位置环,输出作为速度环的设定值
- 内环:速度环,直接输出PWM占空比
位置环PID参数整定步骤:
- 先设I=D=0,逐渐增大P直到出现等幅振荡
- 记录振荡周期Tu,增益Ku
- 根据Ziegler-Nichols公式:
P=0.6Ku, I=2P/Tu, D=P*Tu/8
代码实现采用增量式PID避免积分饱和:
c复制typedef struct {
float Kp,Ki,Kd;
float last_err,prev_err;
float max_output;
} PID_Controller;
float PID_Update(PID_Controller* pid, float setpoint, float feedback) {
float err = setpoint - feedback;
float delta = pid->Kp*(err - pid->last_err)
+ pid->Ki*err
+ pid->Kd*(err - 2*pid->last_err + pid->prev_err);
pid->prev_err = pid->last_err;
pid->last_err = err;
return constrain(delta, -pid->max_output, pid->max_output);
}
4. 系统调试与性能优化
4.1 校准流程标准化
-
编码器零位校准:
- 机械固定电机轴到已知位置
- 执行
write_zero_position()函数 - 旋转电机轴检查角度读数是否线性变化
-
PID参数自整定:
python复制# 通过串口发送阶跃信号并记录响应曲线 import serial, time ser = serial.Serial('COM3', 115200) ser.write(b'speed=100\n') # 设置目标速度100RPM data = [] for _ in range(1000): data.append(ser.readline().decode()) time.sleep(0.01) # 分析数据绘制响应曲线
4.2 典型问题排查指南
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 电机抖动不转 | 相位接反 | 交换电机线或编码器A/B相 |
| 低速时速度波动大 | 编码器分辨率不足 | 改用更高PPR编码器或增加测速周期 |
| 急停时过冲 | 微分增益不足 | 逐步增大D参数直至振荡临界点 |
| 高温保护触发 | 死区时间不足 | 调整驱动器死区时间至300-500ns |
5. 工程实践中的经验总结
在三个月实际运行中,我们发现了几个教科书上不会强调的要点:
-
编码器电缆一定要用双绞屏蔽线,屏蔽层单端接地。曾因接地不当导致速度信号中混入100Hz干扰,表现为周期性速度波动。
-
电机轴与负载的联轴器要对中精确。偏差超过0.1mm会导致编码器信号在低速时出现周期性丢脉冲,我们最终选用铝合金弹性联轴器解决了这个问题。
-
电源质量至关重要。测试发现当输入电压纹波超过200mV时,PID控制效果明显恶化。解决方案是在电源入口增加470μF电解电容并联0.1μF陶瓷电容。
这个项目的PCB设计文件和完整代码库已在GitHub开源,包含详细的注释和测试案例。对于想深入学习的开发者,建议从最简单的速度环开始,逐步增加位置环和抗扰动功能。电机控制就像骑自行车——理论再完美,不上手调试永远掌握不了那种微妙的平衡感。
