第二节 PMSM矢量控制建模:Clark变换与Park变换、电流环PI控制器、SVPWM调制

好,咱们直接进入正题。这一节要干的事,说白了就是把电机控制里最核心的三个模块给搭出来。Clark变换、Park变换、电流环PI、还有SVPWM。这几个东西你要是能在Simulink里玩明白,那离自动代码生成就不远了。

我个人习惯,建模之前先想清楚物理意义。别一上来就拖模块,那样容易翻车。

2.1 Clark变换与Park变换建模

先说说坐标变换。为什么要变?因为三相交流电那玩意儿控制起来太麻烦。你想想看,三个电流互相耦合,你调一个另外两个也跟着动。所以我们要把它转到两相旋转坐标系下,让控制变得像调直流电机一样简单。

2.1.1 Clark变换(3s/2s)

Clark变换就是把三相静止坐标系(ABC)转到两相静止坐标系(αβ)。公式很简单:

Iα = Ia
Iβ = (Ia + 2*Ib) / √3

嗯,这里要注意,我用的等幅值变换。有些教材用等功率变换,系数不一样。我个人习惯用等幅值,因为后面算SVPWM时方便。

在Simulink里建模,我建议直接用Fcn模块或者MATLAB Function。别用一堆加减乘除搭,看着乱。

核心要点:

  • 输入:三相电流Ia, Ib, Ic(Ic = -Ia - Ib,可以省一路)
  • 输出:Iα, Iβ
  • 系数:等幅值变换,α轴与A轴对齐

我的小技巧: 我在项目中遇到过,有些工程师把Ic也算进去,其实没必要。三相平衡系统下,Ic = -(Ia+Ib),省一个传感器还能省钱。

2.1.2 Park变换(2s/2r)

Park变换是把αβ转到dq旋转坐标系。这里需要电角度θ。公式:

Id = Iα*cosθ + Iβ*sinθ
Iq = -Iα*sinθ + Iβ*cosθ

为什么要有这个变换?因为转到dq坐标系后,Id控制励磁,Iq控制转矩,两者解耦了。你想想看,这不就跟直流电机一样了吗?

建模时,θ从哪里来?通常来自编码器或者观测器。我这里先假设θ已经给出来了,后面章节会讲怎么获取。

避坑指南: 我曾经在项目里吃过亏——Park变换的θ和反Park变换的θ必须严格同步。差一个采样周期,电流环就抖得不行。所以建议用同一个信号源,别复制一份。

2.2 电流环PI控制器设计

电流环是矢量控制的内环,响应速度要快。说白了,就是让实际电流快速跟上给定值。

2.2.1 PI参数整定

PI控制器的传递函数:

G(s) = Kp + Ki/s

参数怎么定?我一般用工程整定法。先算电机电气时间常数τ = L/R,然后:

参数 计算公式 说明
Kp L * ωc ωc是电流环带宽,一般取1000-3000 rad/s
Ki R * ωc 保证零极点对消

嗯,这里要注意,实际项目中还要考虑数字实现的离散化。我习惯用后向差分法,简单稳定。

离散化后的PI算法:

// 位置式PI
error = ref - feedback;
integral += Ki * error * Ts;
output = Kp * error + integral;

// 限幅处理
if(output > max) output = max;
if(output < min) output = min;

2.2.2 Simulink建模要点

在Simulink里搭PI控制器,我建议用离散模块。别用连续模块,因为最终代码生成出来是离散的。

  • 使用Discrete PI Controller模块(Simulink自带)
  • 或者自己搭:Gain + Discrete Integrator + Sum
  • 别忘了输出限幅!我见过有人没加限幅,积分饱和导致系统发散

我的经验: 电流环的采样频率建议设到10kHz以上。太低的话,电流纹波大,电机噪音也大。我之前有个项目,采样频率从5kHz提到12kHz,噪音直接降了8dB。

2.3 SVPWM调制模块搭建

SVPWM,空间矢量脉宽调制。这玩意儿比SPWM好,电压利用率高,谐波小。说白了,就是让逆变器输出一个旋转的电压矢量。

2.3.1 基本原理

SVPWM的核心思想:用八个基本电压矢量(六个非零矢量+两个零矢量)来合成任意方向的电压矢量。

步骤其实就三步:

  1. 扇区判断: 根据Uα, Uβ判断当前电压矢量在哪个扇区
  2. 作用时间计算: 计算相邻两个基本矢量的作用时间T1, T2
  3. 占空比分配: 根据扇区计算三相占空比Ta, Tb, Tc

2.3.2 Simulink实现

我建议用MATLAB Function来实现SVPWM,代码清晰,调试方便。下面给个核心代码片段:

function [Ta, Tb, Tc] = svpwm(Ualpha, Ubeta, Vdc, Ts)
    % 扇区判断
    Vref1 = Ubeta;
    Vref2 = (sqrt(3)/2)*Ualpha - 0.5*Ubeta;
    Vref3 = -(sqrt(3)/2)*Ualpha - 0.5*Ubeta;
    
    if Vref1 > 0, sector = 1; else sector = 4; end
    if Vref2 > 0, sector = bitxor(sector, 2); end
    if Vref3 > 0, sector = bitxor(sector, 1); end
    
    % 计算X, Y, Z
    X = sqrt(3)*Ubeta*Ts/Vdc;
    Y = (sqrt(3)/2*Ubeta + 3/2*Ualpha)*Ts/Vdc;
    Z = (sqrt(3)/2*Ubeta - 3/2*Ualpha)*Ts/Vdc;
    
    % 根据扇区计算T1, T2
    switch sector
        case 1, T1 = Z; T2 = Y;
        case 2, T1 = Y; T2 = -X;
        case 3, T1 = -Z; T2 = X;
        case 4, T1 = -X; T2 = Z;
        case 5, T1 = X; T2 = -Y;
        case 6, T1 = -Y; T2 = -Z;
    end
    
    % 过调制处理
    if(T1 + T2 > Ts)
        T1 = T1/(T1+T2)*Ts;
        T2 = T2/(T1+T2)*Ts;
    end
    
    % 计算占空比
    T0 = Ts - T1 - T2;
    Ta = (T0/2 + T1 + T2)/Ts;
    Tb = (T0/2 + T2)/Ts;
    Tc = (T0/2)/Ts;
end

重要提醒: 过调制处理一定要做!我曾经在测试时忘了加,结果T1+T2超过Ts,占空比算出来大于1,逆变器直接炸了。嗯,那次教训挺深刻的。

2.3.3 模块封装建议

我建议把SVPWM封装成一个子系统,输入是Uα, Uβ, Vdc, Ts,输出是三相占空比。这样上层调用时特别清爽。

封装好后,记得把采样时间设成Ts。不然代码生成时会有警告。

最终效果: 把Clark、Park、PI、SVPWM串起来,你就得到了一个完整的电流环。输入是Id_ref, Iq_ref和电角度θ,输出是六路PWM波。这就是矢量控制的内核。

好了,这一节的内容就到这。下一节我们讲速度环和位置环的建模,还有怎么把整个系统跑起来。到时候我会分享一些调试技巧,保证让你少走弯路。