1. FOC开环电压模式驱动永磁同步电机
任务目标
本案例实现永磁同步电机(PMSM)的FOC开环电压模式控制:给定目标电角速度,通过SVPWM生成三相电压,使电机按设定速度旋转。该案例用于验证FOC基本流程(坐标变换→SVPWM→逆变器驱动)的正确性,不依赖转子位置传感器,属于开环V/f控制策略。
核心原理与实现方案
开环FOC电压模式控制流程如下:
- 根据目标电角速度 ωref 积分得到电角度 θe;
- 给定 d 轴电压 Ud(通常为0)和 q 轴电压 Uq(恒定幅值),经Park逆变换得到 α-β 轴电压;
- 通过SVPWM将 Uα、Uβ 转换为逆变器三相占空比;
- 输出PWM驱动三相全桥逆变器供电给PMSM。
由于是开环控制,电角度由程序直接给定(而非编码器反馈),电机转子会跟随定子磁场同步旋转。负载不超过电机牵出转矩时,转子与给定电角度保持同步。
关键完整代码
// FOC开环电压模式驱动PMSM - 核心实现
// 依赖:STM32 HAL库 + TIM1高级定时器输出6路PWM(互补带死区)
#include "main.h"
#include "foc_openloop.h"
// 电机参数与控制常量
#define PWM_FREQ 20000.0f // PWM开关频率 20kHz
#define PWM_PERIOD 4200 // TIM1 ARR值(对应20kHz,取决于时钟配置)
#define VDC 24.0f // 母线电压 24V
#define SQRT3_2 0.8660254f
#define INV_SQRT3 0.5773503f
// 开环控制变量
static float theta_elec = 0.0f; // 当前电角度 [rad]
static float speed_ref = 0.0f; // 目标电角速度 [rad/s]
static float uq_ref = 0.0f; // q轴电压幅值 [V]
static float ud_ref = 0.0f; // d轴电压(开环通常为0)
// 定时器更新中断中调用(20kHz)
void FOC_OpenLoop_ISR(void)
{
float dt = 1.0f / PWM_FREQ;
float u_alpha, u_beta;
float t1, t2, t0;
float ta, tb, tc;
int sector;
// 1. 电角度积分(开环给定位置)
theta_elec += speed_ref * dt;
if (theta_elec > 2.0f * 3.14159265f)
theta_elec -= 2.0f * 3.14159265f;
// 2. Park逆变换:dq -> αβ
u_alpha = ud_ref * cosf(theta_elec) - uq_ref * sinf(theta_elec);
u_beta = ud_ref * sinf(theta_elec) + uq_ref * cosf(theta_elec);
// 3. SVPWM扇区判断
float vref1 = u_beta;
float vref2 = -0.5f * u_beta + SQRT3_2 * u_alpha;
float vref3 = -0.5f * u_beta - SQRT3_2 * u_alpha;
if (vref1 > 0) sector = 1; else sector = 4;
if (vref2 > 0) sector = (sector == 1) ? 5 : (sector == 4) ? 3 : sector;
if (vref3 > 0) sector = (sector == 5) ? 1 : (sector == 3) ? 2 : sector;
// 4. 计算相邻矢量作用时间
float vdc_inv = 1.0f / VDC;
float x = SQRT3_2 * vdc_inv * u_beta;
float y = vdc_inv * (1.5f * u_alpha + SQRT3_2 * u_beta);
float z = vdc_inv * (-1.5f * u_alpha + SQRT3_2 * u_beta);
switch (sector)
{
case 1: t1 = z; t2 = y; break;
case 2: t1 = y; t2 = -x; break;
case 3: t1 = -z; t2 = x; break;
case 4: t1 = -x; t2 = z; break;
case 5: t1 = x; t2 = -y; break;
case 6: t1 = -y; t2 = -z; break;
default: t1 = 0; t2 = 0; break;
}
// 5. 过调制处理
float t_sum = t1 + t2;
if (t_sum > 1.0f) {
float scale = 1.0f / t_sum;
t1 *= scale;
t2 *= scale;
t_sum = 1.0f;
}
t0 = 1.0f - t_sum;
// 6. 计算比较值(七段式SVPWM)
float t1_half = t1 * 0.5f;
float t2_half = t2 * 0.5f;
float t0_half = t0 * 0.25f;
switch (sector)
{
case 1: ta = t0_half + t1_half + t2_half; tb = t0_half + t2_half; tc = t0_half; break;
case 2: ta = t0_half + t1_half; tb = t0_half + t1_half + t2_half; tc = t0_half; break;
case 3: ta = t0_half; tb = t0_half + t1_half + t2_half; tc = t0_half + t2_half; break;
case 4: ta = t0_half; tb = t0_half + t1_half; tc = t0_half + t1_half + t2_half; break;
case 5: ta = t0_half + t2_half; tb = t0_half; tc = t0_half + t1_half + t2_half; break;
case 6: ta = t0_half + t1_half + t2_half; tb = t0_half; tc = t0_half + t1_half; break;
default: ta = 0; tb = 0; tc = 0; break;
}
// 7. 写入PWM比较寄存器(更新占空比)
TIM1->CCR1 = (uint16_t)(ta * PWM_PERIOD);
TIM1->CCR2 = (uint16_t)(tb * PWM_PERIOD);
TIM1->CCR3 = (uint16_t)(tc * PWM_PERIOD);
}
// 初始化开环控制参数
void FOC_OpenLoop_Init(float speed_rad_s, float uq_volts)
{
speed_ref = speed_rad_s;
uq_ref = uq_volts;
ud_ref = 0.0f;
theta_elec = 0.0f;
// 启动PWM输出(TIM1通道1-3,互补输出CH1N-CH3N)
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_3);
HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1);
HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_2);
HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_3);
}
// 主函数调用示例
// int main(void) {
// HAL_Init();
// SystemClock_Config();
// MX_GPIO_Init();
// MX_TIM1_Init(); // 20kHz PWM,互补输出,死区1us
//
// // 设置电角速度 50 rad/s(约8转/秒电频率),q轴电压 3V
// FOC_OpenLoop_Init(50.0f, 3.0f);
//
// while (1) {
// // 主循环可调整 speed_ref / uq_ref
// }
// }
运行与验证方法
硬件连接:STM32开发板(如F103/F407)TIM1的6路PWM输出经驱动芯片(如IR2104)连接三相全桥逆变器,逆变器输出接PMSM的U/V/W三相。母线电压24V,电流采样非必需(开环模式)。
参数设置:根据实际时钟配置调整PWM_PERIOD值,确保PWM频率为20kHz。Uq电压幅值从2V开始逐步增加,避免过流。
验证步骤:
- 将
speed_ref设为0,确认电机静止且无异常发热; - 设置
speed_ref = 50 rad/s(约477rpm电频率),uq_ref = 3V,观察电机是否平稳旋转; - 用示波器测量电机U相端电压,应为20kHz正弦PWM波形,调制波频率约8Hz(50/2π);
- 逐渐增加
uq_ref至5V,电机转速应基本不变(开环特性),但带载能力增强。
通过标准:电机能连续平稳旋转、无剧烈振动或失步;相电压调制波频率与设定电角速度一致(误差<5%);母线电流不超过驱动器额定值。
常见问题
- 电机不转:检查PWM是否正常输出(示波器测栅极驱动波形)、母线电压是否建立、Uq幅值是否足够(尝试提高至5V);
- 电机振动大:可能是电角度方向与电机实际旋转方向相反,交换任意两相相序;或Uq过大导致过调制;
- 转速不准确:开环模式下转速受负载影响,空载时转速略高于设定值属正常现象。