🌀 1. 前言

在永磁同步电机(PMSM)或无刷直流电机(BLDC)的高性能控制中,FOC(Field Oriented Control,磁场定向控制) 是最常用的算法之一。 为了获得更平滑的转矩、更快的动态响应和更好的稳态精度,我们通常会结合:

  • SVPWM(空间矢量脉宽调制) — 高效利用直流母线电压,输出三相电压;

  • 串级 PID 控制 — 外环控制位置或速度,内环精确调节转矩或电流。

下文结合实际代码,带你一步步理解这种控制结构的运行机制。


⚙️ 2. 控制系统结构

一个典型的 FOC + SVPWM + 串级 PID 系统结构如下👇:

           +-------------------+
target --->|  外环PID(位置)  |--- target_speed --->+------------------+
           +-------------------+                     | 内环PID(速度)  |----> Uq
                                                  +--+------------------+
                                                  |
                                                  v
                                              SVPWM模块
                                                  |
                                           三相PWM输出
                                                  |
                                             电机本体
                                                  |
                                           编码器 / 磁编码器反馈
  • 外环(位置 PID):计算当前位置与目标位置的误差,输出目标速度;

  • 内环(速度 PID):根据目标速度与实际速度误差,输出控制电压 UqU_qUq;

  • SVPWM:将 UqU_qUq 转换为三相 PWM,占空比输出;

  • 电机:响应 PWM 电压,旋转,编码器反馈闭环。


🧮 3. SVPWM 算法实现

SVPWM 核心就是根据期望的 UqU_qUq、UdU_dUd 和电角度 θ\thetaθ,计算三相 PWM 占空比。

void motor_setPhaseVoltage(motor_t *m, float Uq, float Ud)
{
    float angle_el;
    angle_el = m->elecAngle = normalizeAngle(
        (float)(motor_DIR * motor_PP) * m->as->rad - m->zeroAngle);
​
    // 处理负的Uq分量 - 将角度旋转180度
    if (Uq < 0)
        angle_el += _PI_;
    Uq = myabs(Uq);
​
    // 将角度规范化到[0, 2π)范围,并旋转90度
    angle_el = normalizeAngle(angle_el + _PI_2);
​
    // 确定电压矢量所在的扇区(1-6)
    int sector = floor(angle_el / _PI_3) + 1;
​
    // 计算基本电压矢量的作用时间
    float T1 = _SQRT3 * sin(sector * _PI_3 - angle_el) * Uq / POWER;
    float T2 = _SQRT3 * sin(angle_el - (sector - 1.0) * _PI_3) * Uq / POWER;
    float T0 = 1 - T1 - T2;
​
    // 三相PWM占空比
    float Ta, Tb, Tc;
    switch (sector) {
        case 1: Ta = T1 + T2 + T0/2; Tb = T2 + T0/2; Tc = T0/2; break;
        case 2: Ta = T1 + T0/2; Tb = T1 + T2 + T0/2; Tc = T0/2; break;
        case 3: Ta = T0/2; Tb = T1 + T2 + T0/2; Tc = T2 + T0/2; break;
        case 4: Ta = T0/2; Tb = T1 + T0/2; Tc = T1 + T2 + T0/2; break;
        case 5: Ta = T2 + T0/2; Tb = T0/2; Tc = T1 + T2 + T0/2; break;
        case 6: Ta = T1 + T2 + T0/2; Tb = T0/2; Tc = T1 + T0/2; break;
        default: Ta = Tb = Tc = 0;
    }
​
    // 转换为实际电压
    m->Ua = _constrain(Ta * POWER, 0, POWER);
    m->Ub = _constrain(Tb * POWER, 0, POWER);
    m->Uc = _constrain(Tc * POWER, 0, POWER);
​
    // 输出PWM
    setPwm(m);
}

📌 关键点说明

  • 这里用的是 反 Clarke + Park 变换之后的 SVPWM

  • 通过 sector 判断矢量所在扇区;

  • T1T_1T1、T2T_2T2、T0T_0T0 分别是作用时间;

  • Ta/Tb/Tc 经过限幅后输出给定时器 PWM 通道;

  • Uq 控制转矩,Ud 理论上设为 0,表示磁链方向电流最小损耗。


🧠 4. 串级 PID 控制器

代码中定义了两个 PID:

// 外环 PID(位置)
PID_Init(&pid1.pid1, 2.0f, 0.0f, 0.5f, 0.0f, POWER);
​
// 内环 PID(速度)
PID_Init(&pid1.pid2, 20.0f, 0.0f, 13.0f, 0.0f, POWER);
  • 外环增益较小,响应慢,主要用来给速度环设定目标;

  • 内环增益较大,响应快,保证电机能快速达到目标速度。

串级计算函数:

void PID_CascadeCalc(CascadePID *pid, float target, float feedBack1, float feedBack2)
{
    PID_SingleCalc(&pid->pid1, target, feedBack1);        // 位置环
    PID_SingleCalc(&pid->pid2, pid->pid1.output, feedBack2); // 速度环
    pid->output = pid->pid2.output;
}
  • feedBack1 是位置反馈(比如编码器角度);

  • feedBack2 是速度反馈(比如编码器测速);

  • pid1.output 是外环 PID 输出,作为内环目标速度;

  • 最终 pid->outputUq,直接送到 SVPWM。


🧭 5. 实际任务循环

结合前面所有部分,任务循环如下👇

CascadePID pid1;
PID_Init(&pid1.pid1, 2.0f ,0.0f,0.5f,0.0f,POWER);
PID_Init(&pid1.pid2, 20.0f ,0.0f,13.0f,0.0f,POWER);
​
motor_init(&m1);
motor_EN(&m1,1);
​
float targetPos = -0.9f;
​
for(;;)
{
    m1.as->speed = as5600_getSpeed(m1.as);
​
    // 串级 PID
    PID_CascadeCalc(&pid1, targetPos, m1.as->relativeRad, m1.as->speed);
​
    // FOC + SVPWM 输出
    motor_setPhaseVoltage(&m1, pid1.output, 0);
​
    vTaskDelay(pdMS_TO_TICKS(5));
}

🚀 执行过程

  1. 读取编码器角度和速度;

  2. 外环 PID 根据目标位置计算目标速度;

  3. 内环 PID 根据目标速度和实际速度计算 UqU_qUq;

  4. SVPWM 将 UqU_qUq 转换为三相 PWM;

  5. PWM 输出到驱动器 → 电机运动;

  6. 下一个周期重复。

📈 6. 时间响应曲线(仿真)

我使用 Python 简单仿真了这个控制结构,得到如下典型曲线👇

  • 蓝线:实际位置

  • 橙线:目标位置

特点:

  • 位置环响应平滑,没有大的振荡;

  • 速度环响应快,稳态误差小;

  • 内环电压输出随误差自动调节,实现稳定收敛。

🧰 7. 参数调节建议

环节 主要作用 调节原则
速度环 PID 决定响应速度和稳定性 先调这个,使电机能跟速稳定;P 大响应快,D 抑制超调
位置环 PID 决定运动轨迹和收敛性能 后调这个,P 决定轨迹跟踪速度;过大易震荡
SVPWM 提高电压利用率,抑制谐波 一般无需调参,逻辑固定
电压限幅 防止过冲/过流 建议设为母线电压或安全值

📝 8. 总结

通过以上内容,我们已经搭建了一个标准的:

FOC 矢量控制SVPWM 驱动逆变串级 PID 闭环调节

这样的控制框架广泛应用于:

  • 无刷电机定位与稳速系统

  • 机械臂关节伺服

  • 航模云台

  • 精密运动控制设备

相较于传统的单环控制,这种结构能:

  • 提高系统动态响应;

  • 降低位置环震荡;

  • 获得更高控制精度;

  • 提升电压利用率与电机效率。


📚 参考

  • Modern Control of Electric Machines

  • STMicroelectronics 应用笔记 AN4509 — “FOC of PMSM Motor”

  • STM32CubeMX / FreeRTOS 工程实践

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐