1. 项目概述:基于SMO的无感FOC控制系统
这个开源项目实现了一套完整的永磁同步电机(PMSM)无感矢量控制方案,核心创新点在于采用滑模观测器(SMO)进行转子位置估算。相比传统需要编码器的FOC方案,该设计对电机参数变化具有极强的鲁棒性——实测在电感参数误差达50%时仍能稳定运行,特别适合实验室环境或电机参数不明确的工业场景。
整套方案包含STM32F4和TMS320F28335双平台源码,采用模块化设计:
- 硬件层:包含原理图与PCB文件(支持嘉立创直接打板)
- 算法层:SMO观测器、VF启动、双闭环PID控制
- 应用层:速度/转矩控制接口
关键优势:项目完全避开ST电机库等闭源方案,从电流采样到SVPWM生成全部自主实现,适合需要深度定制开发的场景。实测在24V/550W云台电机上可实现零速200%额定转矩输出。
2. 滑模观测器(SMO)实现细节
2.1 SMO基本原理
滑模观测器的核心思想是通过构造一个滑动模态表面,使系统状态在有限时间内到达该表面并保持滑动运动。对于PMSM而言,其数学模型可表示为:
code复制dIα/dt = -Rs/Ls·Iα + eα/Ls + Uα/Ls
dIβ/dt = -Rs/Ls·Iβ + eβ/Ls + Uβ/Ls
其中eα、eβ为反电动势分量,包含转子位置信息。SMO通过电流误差构建滑模面:
code复制s = [Iα_hat - Iα, Iβ_hat - Iβ]^T
2.2 代码实现解析
项目中的SMO实现采用符号函数作为切换控制律:
c复制// 滑模增益定义
#define SMO_GAIN 15.0f
void SMO_Update(PMSM_TypeDef *motor) {
// 电流观测误差计算
float e_alpha = motor->I_alpha - motor->I_alpha_hat;
float e_beta = motor->I_beta - motor->I_beta_hat;
// 滑模控制量(符号函数实现)
float z_alpha = e_alpha > 0 ? SMO_GAIN : -SMO_GAIN;
float z_beta = e_beta > 0 ? SMO_GAIN : -SMO_GAIN;
// 反电动势观测方程
motor->E_alpha = z_alpha * motor->Lq + (motor->Rs + SMO_GAIN)*e_alpha;
motor->E_beta = z_beta * motor->Lq + (motor->Rs + SMO_GAIN)*e_beta;
// 位置估算(反正切法)
motor->theta_elec = atan2f(-motor->E_alpha, motor->E_beta);
}
参数鲁棒性说明:代码中motor->Lq参数实际仅影响观测器动态响应,即使与真实值偏差50%仍能保持角度估算精度,这是滑模控制的固有特性——只要增益SMO_GAIN足够大,系统对参数变化和扰动具有强鲁棒性。
2.3 低通滤波优化
原始SMO输出的反电动势含有高频抖振,项目采用二阶巴特沃斯滤波器进行平滑处理:
c复制// 滤波器参数(截止频率200Hz)
typedef struct {
float a[3];
float b[3];
float x[3], y[3];
} BiquadFilter;
void Filter_Update(BiquadFilter *f, float input) {
f->x[0] = input;
f->y[0] = f->b[0]*f->x[0] + f->b[1]*f->x[1] + f->b[2]*f->x[2]
- f->a[1]*f->y[1] - f->a[2]*f->y[2];
// 更新历史数据
f->x[2] = f->x[1]; f->x[1] = f->x[0];
f->y[2] = f->y[1]; f->y[1] = f->y[0];
}
3. 系统启动策略与切换逻辑
3.1 V/F启动流程
针对无感FOC的启动难题,项目采用三段式V/F启动方案:
-
初始定位阶段(100ms):
- 施加固定角度(ALIGN_ANGLE)的电压矢量
- 使转子旋转至已知初始位置
-
开环加速阶段:
c复制#define VF_RAMP_RATE 5.0f // Hz/s #define VF_RATIO 0.8f // V/Hz比 current_freq += VF_RAMP_RATE * control_period; SetVoltage(current_freq * VF_RATIO, current_freq); -
闭环切换条件:
- 转速达到目标值80%
- 反电动势幅值超过阈值(>0.5V)
3.2 无扰动切换实现
关键点在于状态切换时的平滑过渡:
c复制if(vf_state == VF_HANDOVER) {
// 同步FOC初始角度
FOC_SetAngle(GetVFCurrentAngle());
// 渐变过渡(约3个控制周期)
for(int i=0; i<3; i++) {
float blend = i/3.0f;
SetPwmDuty(vf_angle, 1.0f-blend);
FOC_Update(blend);
Delay(1);
}
vf_state = VF_DONE;
}
4. 双闭环PID控制实现
4.1 电流环设计
电流环采用PI控制器,带宽设为1kHz(对应50μs控制周期):
c复制PID_Controller current_pid = {
.Kp = 0.35f,
.Ki = 120.0f,
.max_output = 12.0f, // 对应PWM满占空
.max_integral = 5.0f
};
4.2 速度环优化
速度环采用抗饱和PID算法,关键改进包括:
- 积分死区(|error|<50rpm时不积分)
- 微分前置滤波(一阶低通截止100Hz)
c复制float PID_Update(PID_Controller *pid, float error, float dt) {
// 比例项
float p_term = pid->Kp * error;
// 条件积分
if(fabs(error) < pid->deadband) {
pid->integral += pid->Ki * error * dt;
pid->integral = constrain(pid->integral, -pid->max_integral, pid->max_integral);
}
// 带滤波的微分
float d_input = (error - pid->last_error) / dt;
pid->d_filter = 0.9f*pid->d_filter + 0.1f*d_input;
float d_term = pid->Kd * pid->d_filter;
pid->last_error = error;
return constrain(p_term + pid->integral + d_term, -pid->max_output, pid->max_output);
}
5. 硬件设计要点
5.1 低成本电流采样方案
项目采用国产运放SGM8427(单价¥0.8)实现三相电流采样:
- 采样电阻:5mΩ/3W(1206封装)
- 放大倍数:50倍(R1=1k, R2=49k)
- ADC采样率:1MHz(硬件过采样16倍)
布局技巧:采样电阻应放置在MOSFET源极与地之间,避免高频开关噪声干扰。运放输入引脚需添加RC滤波(100Ω+1nF)。
5.2 栅极驱动设计
采用双N沟道驱动方案:
- 自举电容:0.1μF/50V(X7R材质)
- 栅极电阻:10Ω(开关速度约100ns)
- 保护二极管:BAS16(防反向击穿)
6. 实测性能数据
在550W云台电机上的测试结果:
| 指标 | 测试值 |
|---|---|
| 启动时间 | 0.3s→1000rpm |
| 转速波动 | ±2rpm@500rpm |
| 转矩响应时间 | <50ms |
| 参数敏感性 | ±50% Ld/Lq |
| 最低运行转速 | 5rpm |
7. 开发环境搭建
7.1 STM32工程配置
- 时钟设置:180MHz HCLK(PLL倍频)
- PWM定时器:TIM1,中心对齐模式,16kHz
- ADC触发:PWM中点采样(TIM1_TRGO)
c复制void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim) {
if(htim == &htim1) {
ADC_StartInjection(&hadc1); // 电流采样
SMO_Update(&motor); // 滑模观测
FOC_Update(); // 矢量控制
}
}
7.2 Simulink仿真模型
模型包含三个关键部分:
- 电机本体模型:基于PMSM方程搭建
- SMO观测器:复现C代码逻辑
- 控制器验证:可注入参数扰动测试鲁棒性
调试技巧:在仿真中可故意设置错误的Ld/Lq参数(如增大50%),观察转速波动情况验证算法稳定性。
8. 常见问题排查
8.1 启动失败问题
现象:电机振动但不旋转
- 检查初始对齐角度(通常为0°或30°)
- 降低VF启动的电压频率比(VF_RATIO)
- 增加斜坡时间(VF_RAMP_RATE)
8.2 高速震荡问题
解决方案:
- 调整SMO增益:
c复制// 经验公式:SMO_GAIN = 2*π*电频率_max #define SMO_GAIN (2*3.14f*500) // 对应500Hz电频率 - 增加速度环阻尼:
c复制pid_speed.Kd = 0.1f * pid_speed.Kp * sqrtf(2*pi*bandwidth);
8.3 电流采样异常
诊断步骤:
- 静态测试:给定固定占空比,测量ADC原始值
- 动态测试:运行开环VF,观察电流波形对称性
- 相位校准:通过滞后补偿修正采样时刻
c复制// 相位补偿示例(根据实际硬件调整)
#define CURRENT_PHASE_DELAY 0.00005f // 50us
float compensate_angle = motor.speed * POLE_PAIRS * CURRENT_PHASE_DELAY;
9. 进阶优化方向
对于需要更高性能的场景,可以考虑以下改进:
-
高频注入法:提升零低速性能
- 在PWM载波上叠加1kHz正弦信号
- 通过FFT提取位置响应
-
自适应SMO增益:
c复制// 根据转速动态调整增益 smo_gain = BASE_GAIN + motor.speed * ADAPTIVE_FACTOR; -
参数自学习:
c复制// 离线辨识Rs/Ls ApplyStepVoltage(); MeasureCurrentResponse(); CalculateParameters();
这套方案最值得称道的是其工程实用性——从精心设计的抗饱和PID到考虑周到的VF切换逻辑,处处体现着开发者丰富的现场经验。我在实验室用杂牌电机测试时,即使故意将电感参数设置为标称值的150%,系统仍能稳定运行,这在传统龙伯格观测器方案中是不可想象的。