1. STM32G431无感FOC驱动方案概述
无感FOC(Field Oriented Control)驱动是电机控制领域的一项重要技术,它通过算法估算转子位置,省去了传统编码器的硬件成本。STM32G431作为STMicroelectronics推出的高性能微控制器,其内置的高精度定时器和丰富的模拟外设,使其成为实现无感FOC的理想平台。
本方案采用滑模观测器(SMO)进行转子位置估算,配合三段式启动策略,实现了电机的平稳启动和高效运行。整套方案包含完整的硬件设计、软件实现和调试参数,特别适合需要快速开发无感FOC系统的工程师参考。
注意:无感FOC开发需要对电机控制理论有基本了解,建议先掌握Clark变换、Park变换等基本概念后再尝试本方案。
2. 滑模观测器的实现与优化
2.1 滑模观测器基本原理
滑模观测器是一种非线性状态观测器,它通过引入不连续的控制项(滑模项)来强迫系统状态沿着预设的滑模面运动。在无感FOC应用中,SMO主要用于估算反电动势,进而计算出转子位置。
滑模观测器的核心思想可以用一个简单的类比理解:就像在冰面上开车,即使方向盘有小幅摆动(系统扰动),车辆仍会沿着既定方向(滑模面)前进,因为任何偏离都会受到控制系统强烈的纠正。
2.2 SMO的C语言实现
本方案中的滑模观测器采用结构体封装,便于参数管理和模块化设计:
c复制typedef struct {
float alpha; // α轴反电动势
float beta; // β轴反电动势
float angle; // 估算转子角度
float speed; // 换算转速
float LPF_gain; // 低通滤波系数
float K_SMO; // 滑模增益
float I_alpha_est; // α轴电流估计值
float I_beta_est; // β轴电流估计值
float e_alpha; // α轴滑模误差
float e_beta; // β轴滑模误差
} SMO_TypeDef;
更新函数的关键实现如下:
c复制void SMO_Update(SMO_TypeDef* h, MotorState* motor) {
// 计算电流误差(滑模面)
float s_alpha = motor->I_alpha - h->I_alpha_est;
float s_beta = motor->I_beta - h->I_beta_est;
// 符号函数处理(简化计算)
h->e_alpha = h->K_SMO * (s_alpha > ? 1 : -1);
h->e_beta = h->K_SMO * (s_beta > ? 1 : -1);
// 低通滤波处理
h->alpha = h->alpha * (1-h->LPF_gain) + h->e_alpha * h->LPF_gain;
h->beta = h->beta * (1-h->LPF_gain) + h->e_beta * h->LPF_gain;
// 计算转子角度
h->angle = atan2f(h->beta, h->alpha);
// 更新速度估算(可选)
static float prev_angle = ;
h->speed = (h->angle - prev_angle) / CONTROL_PERIOD;
prev_angle = h->angle;
}
2.3 关键参数调试经验
-
滑模增益K_SMO:
- 初始值建议设为0.5
- 增大K_SMO可以提高系统鲁棒性,但过大会引入高频噪声
- 调试方法:从0.5开始,每次增加0.1,观察电机运行噪声
-
低通滤波系数LPF_gain:
- 典型值范围0.01-0.1
- 值越大滤波效果越好,但相位延迟也越大
- 调试技巧:先用0.05,如果观测角度抖动明显,适当减小;如果响应太慢,适当增大
-
符号函数替代饱和函数:
- 本方案使用符号函数sign()代替传统的饱和函数sat()
- 优点:计算量小,在STM32G431上效率提升约20%
- 缺点:可能引入更高频的抖振,需要配合适当的低通滤波
实测发现:对于极对数较多的电机(如8极以上),需要将LPF_gain减小到0.02左右,否则角度估算会出现明显滞后。
3. 三段式启动策略详解
3.1 启动流程概述
无感FOC的启动过程分为三个阶段:
- 拉直对齐(Align)
- 开环强拖(Open-loop)
- 闭环运行(Closed-loop)
这种分段启动方式可以有效解决无感FOC在零速或低速时观测器无法准确估算位置的问题。
3.2 拉直对齐阶段实现
拉直阶段的核心任务是让转子固定在已知位置,为后续开环启动做准备:
c复制#define ALIGN_TIME 800 // 拉直持续时间(ms)
#define ALIGN_CURRENT 5.0 // 拉直电流(A)
if(startup_stage == ALIGN) {
// 固定角度注入电流
FOC_CurrentSet(, ALIGN_CURRENT); // 0度对齐
// 计时判断
if(HAL_GetTick() - align_tick > ALIGN_TIME) {
startup_stage = OPENLOOP;
pull_speed = MIN_SPEED; // 初始拖动速度
}
}
关键点说明:
- 对齐角度选择0度而非90度,实测发现对齐效果更稳定
- 对齐时间800ms适用于大多数中小型电机,大惯性负载可能需要延长
- 对齐电流需要足够大以确保转子能克服静摩擦力
3.3 开环强拖阶段实现
开环强拖阶段通过逐步增加电气角度,强迫转子跟随旋转:
c复制#define SPEED_STEP 0.5f // 速度递增步长(rpm)
#define ELECTRICAL_ANGLE (2*PI*POLE_PAIRS/60.0f) // 电气角度转换系数
void SpeedRampUp(float* target, float step) {
static float current_speed = ;
if(current_speed < *target) {
current_speed += step;
}
*target = current_speed;
}
// 在速度环调用
SpeedRampUp(&pull_speed, SPEED_STEP);
FOC_AngleSet(pull_speed * ELECTRICAL_ANGLE * CONTROL_PERIOD, OPENLOOP_CURRENT);
调试技巧:
- SPEED_STEP取值要适中,太小会导致启动缓慢,太大会导致失步
- 对于风机类负载,需要增大OPENLOOP_CURRENT以克服风阻
- 极对数POLE_PAIRS必须正确设置,否则电气角度计算错误
3.4 闭环切换策略
从开环切换到闭环的时机判断至关重要:
c复制#define SWITCH_SPEED 300.0f // 切换速度(rpm)
#define SWITCH_COUNT 50 // 连续达标次数
if(fabsf(smo.speed) > SWITCH_SPEED) {
if(++switch_count > SWITCH_COUNT) {
startup_stage = CLOSEDLOOP;
PID_Clear(&speed_pid); // 清除PID积分项
}
} else {
switch_count = ; // 未达标则清零计数
}
经验分享:
- SWITCH_SPEED一般设为额定转速的10-20%
- SWITCH_COUNT提供滤波功能,防止误切换
- 切换前清除PID积分项可避免冲击
- 对于高惯性负载,建议增加SWITCH_COUNT到100以上
4. 人机交互设计
4.1 按键开关机实现
通过GPIO中断实现按键控制:
c复制// 按键中断回调函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
if(GPIO_Pin == POWER_KEY_Pin) {
static uint32_t last_tick = ;
if(HAL_GetTick() - last_tick > 50) { // 消抖处理
system_power = !system_power;
if(!system_power) {
Motor_Stop(); // 安全停机
}
}
last_tick = HAL_GetTick();
}
}
注意事项:
- 必须添加软件消抖,典型消抖时间50ms
- 关机时应先停止PWM输出再关闭电源
- 对于大功率电机,建议增加硬件RC滤波
4.2 电位器调速实现
ADC读取电位器电压并转换为目标转速:
c复制#define POT_MAX 3.3f // 电位器满量程电压
#define MAX_SPEED 3000.0f // 最大转速(rpm)
void GetTargetSpeed(void) {
HAL_ADC_Start(&hadc1);
float vol = HAL_ADC_GetValue(&hadc1) * POT_MAX / 4096.0f;
// 死区处理
if(vol < 0.1f) {
target_speed = ;
} else {
target_speed = vol * MAX_SPEED / POT_MAX;
}
}
调试要点:
- 用万用表实测开发板ADC参考电压,不同板卡可能不同
- 死区处理可避免零速附近的抖动
- 对于线性不好的电位器,可增加软件校准曲线
5. 系统移植与参数调整
5.1 硬件适配修改
移植到不同硬件平台时,需要检查以下配置:
motor.h中的极对数POLE_PAIRSfoc.c中的SQRT3定义(1.732或更精确值)pwm_timer的计数周期和死区时间- ADC通道与电位器的对应关系
5.2 电机参数调试步骤
新电机调试建议流程:
- 先设置正确的极对数
- 调整拉直电流和时间,确保转子能准确定位
- 调试开环强拖参数,使电机能平稳加速
- 优化SMO参数,确保角度估算准确
- 最后调整PID参数,优化闭环性能
5.3 常见问题排查
-
电机振动大:
- 检查SMO低通滤波参数
- 确认极对数设置正确
- 尝试减小电流环带宽
-
启动困难:
- 增加拉直电流和时间
- 调整开环强拖的初始速度和加速度
- 检查电源电压是否足够
-
高速失步:
- 确认反电动势估算是否准确
- 检查母线电压是否足够
- 尝试增大滑模增益K_SMO
6. 工程代码结构说明
完整工程包含以下关键文件:
code复制/Drivers
/STM32G4xx_HAL_Driver // HAL库驱动
/MDK-ARM
/Project.uvprojx // Keil工程文件
/Inc
motor.h // 电机参数定义
foc.h // FOC算法头文件
smo.h // 滑模观测器头文件
/Src
main.c // 主程序
foc.c // FOC实现
smo.c // 滑模观测器实现
stm32g4xx_it.c // 中断服务
/Hardware
/PCB // 原理图文件
/CubeMX // CubeMX配置文件
代码特点:
- 全中文注释,关键参数都有详细说明
- 模块化设计,方便移植到其他平台
- 宏定义开关控制功能选项
- 包含完整的CubeMX配置,可快速重建工程
在移植到新项目时,重点关注以下几个配置:
motor.h中的电机参数foc.c中的PWM定时器配置smo.c中的观测器参数- 主循环中的控制周期设置