学习SVPWM过后总有一种似乎学了,又好像没学的感觉,感觉懂了又好像没懂。怎么办呢,那最好的办法就是一五一十的撸一遍原理,用代码实现一下它。为了方便理解,就用与公式原理完全一一对应的代码去实现,先不管这个代码的效率了,理解了再优化。走起。
simulink的library搜索sine,Ualpha和Ubeta的设置如下,设定频率为50Hz,幅值为300。Ualpha要超前Ubeta一个90°的相位,因此设置的区别在于Ubeta的相位初始值为 -pi/2。


写算法前看看输入信号的效果,好嘞是我想要的效果,幅值频率都对,下一步就开始写算法了。

步骤一原理:
依据输入的Ualpha与Ubeta来判断此时的电压矢量处于哪个扇区,其判断逻辑如下图所示,通过设立 Uref1 、Uref2 、Uref3 三个判断变量,来决定ABC值的大小,并通过公式 N =4A+2B+C得到扇区号。

这里必须明确一个非常重要的点:扇区号N 与 扇区I II等是两个概念,我们后面的逻辑判断全都是用的扇区号N,而非从0-360°依次以60°区分的扇区。

步骤一代码:
- Uref1 = Ubeta;
- Uref2 = sqrt(3)*Ualpha/2 - Ubeta/2;
- Uref3 = -sqrt(3)*Ualpha/2 - Ubeta/2;
-
- if Uref1>0
- A = 1;
- else
- A = 0;
- end
- if Uref2>0
- B = 1;
- else
- B = 0;
- end
- if Uref3>0
- C = 1;
- else
- C = 0;
- end
-
- N = 4*C + 2*B + A;
这一步也看看效果:效果就是N出来是3-1-5-4-6-2,对应0-360的旋转。

步骤二原理:
算出XYZ三个基本矢量的作用时间,然后根据扇区号N对其进行分配,其分配的表格如下图所示。

步骤二代码:
- X = sqrt(3)*Ts*Ubeta/Udc;
- Y = sqrt(3)*Ts/Udc*(sqrt(3)*Ualpha/2+Ubeta/2);
- Z = sqrt(3)*Ts/Udc*(-sqrt(3)*Ualpha/2+Ubeta/2);
-
- switch(N)
- 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
步骤二的代码不太好验证效果,直接进入步骤三吧。
步骤三原理:
在计算到了基本矢量的作用时间后,也就是得到了下图公式的T4和T6之后,就需要对ABC三相进行切换点的计算,并分配到ABC三相上去。 这里需要搞清楚的一个地方记录一下:切换点是什么的问题?首先问这个切换是针对的是什么?,这个切换点是针对abc三路脉冲电平由低切换到高的点。再问生成的脉冲电平用来干什么?我们熟知的三相逆变器有6个管子,三个桥臂,驱动桥臂开关管的其实就是PWM脉冲,PWM脉冲有高有低,这个切换点实际上就是PWM高低切换的点。如果我们把这个点算出来了,那么PWM就算出来了,三相逆变器也被按照我们所想的驱动了。
步骤三代码:
- Ta = (Ts - T1 - T2)/4;
- Tb = Ta + T1/2;
- Tc = Tb + T2/2;
- switch(N)
- case 1
- Tcm1 = Tb;
- Tcm2 = Ta;
- Tcm3 = Tc;
-
- case 2
- Tcm1 = Ta;
- Tcm2 = Tc;
- Tcm3 = Tb;
-
- case 3
- Tcm1 = Ta;
- Tcm2 = Tb;
- Tcm3 = Tc;
-
- case 4
- Tcm1 = Tc;
- Tcm2 = Tb;
- Tcm3 = Ta;
-
- case 5
- Tcm1 = Tc;
- Tcm2 = Ta;
- Tcm3 = Tb;
-
- case 6
- Tcm1 = Tb;
- Tcm2 = Tc;
- Tcm3 = Ta;
-
- end
到这里配置一个接口输出量(matlab的function模块输出信号不允许直接放在判断逻辑里面,否则会报错),所以最后加一小段代码。
- Tc1 = Tcm1;
- Tc2 = Tcm2;
- Tc3 = Tcm3;
输出效果如下图所示:是不是非常美丽的马鞍波,并且其频率也是输入的50Hz。
如果有兴趣的小伙伴,想要学习这个地方的,可以按照以上步骤搭建一下,搭建的仿真框图如下图所示:

为了方便使用,其中function部分的全代码放在下面了,大家直接复制粘贴就可以了,去试试效果吧,有深入探究的同学可以试着优化一下,我这个代码太过。。。。额。。。初级了,但是好处是便于理解。有优化好的同学可以评论区留言分享一下。
- function [N,N_Sector1,Tc1,Tc2,Tc3] = fcn(Ualpha,Ubeta)
- %#codegen
- persistent Uref1 Uref2 Uref3 A B C X Y Z T1 T2 Ta Tb Tc N_Sector Udc Ts Tcm1 Tcm2 Tcm3;
- if isempty(Uref1)
- U1 = 0; U2 = 0; U3 = 0;
- A = 0; B = 0; C = 0;
- X = 0; Y = 0; Z = 0;
- T1 = 0; T2 = 0;
- Ta = 0; Tb = 0; Tc = 0;
- Tcm1 = 0; Tcm2 = 0; Tcm3 = 0;
- Ts = 1/5000;
- m = sqrt(3)/540*Ts;
- N_Sector=0;
- Udc =540;
- end
-
- Uref1 = Ubeta;
- Uref2 = sqrt(3)*Ualpha/2 - Ubeta/2;
- Uref3 = -sqrt(3)*Ualpha/2 - Ubeta/2;
-
- if Uref1>0
- A = 1;
- else
- A = 0;
- end
- if Uref2>0
- B = 1;
- else
- B = 0;
- end
- if Uref3>0
- C = 1;
- else
- C = 0;
- end
-
- N = 4*C + 2*B + A;
-
- switch(N)
- case 1
- N_Sector=2;
- case 2
- N_Sector=6;
- case 3
- N_Sector=1;
- case 4
- N_Sector=4;
- case 5
- N_Sector=3;
- case 6
- N_Sector=5;
- end
- N_Sector1 = N_Sector;
-
- X = sqrt(3)*Ts*Ubeta/Udc;
- Y = sqrt(3)*Ts/Udc*(sqrt(3)*Ualpha/2+Ubeta/2);
- Z = sqrt(3)*Ts/Udc*(-sqrt(3)*Ualpha/2+Ubeta/2);
-
- switch(N)
- 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
-
- Ta = (Ts - T1 - T2)/4;
- Tb = Ta + T1/2;
- Tc = Tb + T2/2;
- switch(N)
- case 1
- Tcm1 = Tb;
- Tcm2 = Ta;
- Tcm3 = Tc;
-
- case 2
- Tcm1 = Ta;
- Tcm2 = Tc;
- Tcm3 = Tb;
-
- case 3
- Tcm1 = Ta;
- Tcm2 = Tb;
- Tcm3 = Tc;
-
- case 4
- Tcm1 = Tc;
- Tcm2 = Tb;
- Tcm3 = Ta;
-
- case 5
- Tcm1 = Tc;
- Tcm2 = Ta;
- Tcm3 = Tb;
-
- case 6
- Tcm1 = Tb;
- Tcm2 = Tc;
- Tcm3 = Ta;
-
- end
- Tc1 = Tcm1;
- Tc2 = Tcm2;
- Tc3 = Tcm3;
-
-