# FOC电机控制之SVPWM原理与实现

3 篇文章 64 订阅

## 一、SVPWM原理

SVPWM(Space Vector Pulse Width Modulation)，即空间矢量脉宽调制。SVPWM的理论基础是平均值等效原理，即在一个开关周期Ts内，对基本矢量电压加以组合，使其平均值与给定电压矢量相等。通过控制基本矢量电压的作用时间，使合成的目标矢量电压在空间位置按照接近圆形轨迹旋转，所产生的实际磁通去逼近一个理想的磁通圆。模型如下图所示，采样点数越多，就越逼近理想磁通圆，理论上采样点数无穷多时就是理想磁通圆了。

U A ( t ) = U m cos ⁡ θ U B ( t ) = U m cos ⁡ ( θ − 2 3 π ) U C ( t ) = U m cos ⁡ ( θ − 4 3 π ) = U m cos ⁡ ( θ + 2 3 π ) \begin{array}{l} {U_A}(t) = {U_m}\cos \theta \\ {U_B}(t) = {U_m}\cos (\theta - \frac{2}{3}\pi )\\ {U_C}(t) = {U_m}\cos (\theta - \frac{4}{3}\pi ) = {U_m}\cos (\theta + \frac{2}{3}\pi ) \end{array}

u A ( t ) = U A ( t ) ⋅ e j 0 = U m cos ⁡ θ ⋅ e j 0 u B ( t ) = U B ( t ) ⋅ e j 2 3 π = U m cos ⁡ ( θ − 2 3 π ) ⋅ e j 2 3 π u C ( t ) = U C ( t ) ⋅ e j 4 3 π = U m cos ⁡ ( θ + 2 3 π ) ⋅ e j 4 3 π \begin{array}{l} {\boldsymbol{u}_A}(t) = {U_A}(t) \cdot {e^{j0}} = {U_m}\cos \theta \cdot {e^{j0}}\\ {\boldsymbol{u}_B}(t) = {U_B}(t) \cdot {e^{j\frac{2}{3}\pi }} = {U_m}\cos (\theta - \frac{2}{3}\pi ) \cdot {e^{j\frac{2}{3}\pi }}\\ {\boldsymbol{u}_C}(t) = {U_C}(t) \cdot {e^{j\frac{4}{3}\pi }} = {U_m}\cos (\theta + \frac{2}{3}\pi ) \cdot {e^{j\frac{4}{3}\pi }} \end{array}

cos ⁡ ( α + β ) = cos ⁡ α cos ⁡ β − sin ⁡ α sin ⁡ β cos ⁡ ( α − β ) = cos ⁡ α cos ⁡ β + sin ⁡ α sin ⁡ β \begin{array}{l} \cos (\alpha + \beta ) = \cos \alpha \cos \beta - \sin \alpha \sin \beta \\ \cos (\alpha - \beta ) = \cos \alpha \cos \beta + \sin \alpha \sin \beta \end{array}

## 二、SVPWM实现方法

### 1. 基本矢量电压：

ABC三个开关函数的状态(S(A),S(B),S©)共有8种组合，分别是{(0,0,0),(0,0,1),(0,1,0),(0,1,1),(1,0,0),(1,0,1),(1,1,0),(1,1,1),}，分别对应8个矢量电压，其中2个零矢量电压是 U 0 ( 0 , 0 , 0 ) {U_0}(0,0,0) U 7 ( 1 , 1 , 1 ) {U_7}(1,1,1) ，6个非零矢量电压分别是 U 1 ( 0 , 0 , 1 ) , U 2 ( 0 , 1 , 0 ) , U 3 ( 0 , 1 , 1 ) , U 4 ( 1 , 0 , 0 ) , U 5 ( 1 , 0 , 1 ) , U 6 ( 1 , 1 , 0 ) {U_1}(0,0,1),{U_2}(0,1,0),{U_3}(0,1,1),{U_4}(1,0,0),{U_5}(1,0,1),{U_6}(1,1,0) ，它们在空间位置上相邻间隔60°，将平面等分为6个扇区。

[ U α U β ] = 2 3 [ 1 − 1 2 − 1 2 0 3 2 − 3 2 ] ⋅ [ U a U b U c ] = [ − 1 3 U d c − 3 3 U d c ] \left[ {\begin{matrix} {{U_\alpha }}\\ {{U_\beta }} \end{matrix}} \right] = \frac{2}{3}\left[ {\begin{matrix} 1{ - \frac{1}{2}}{ - \frac{1}{2}}\\ 0{\frac{{\sqrt 3 }}{2}}{ - \frac{{\sqrt 3 }}{2}} \end{matrix}} \right] \cdot \left[ {\begin{matrix} {{U_a}}\\ {{U_b}}\\ {{U_c}} \end{matrix}} \right] = \left[ {\begin{matrix} { - \frac{1}{3}{U_{dc}}}\\ { - \frac{{\sqrt 3 }}{3}{U_{dc}}} \end{matrix}} \right] ，合成在两相坐标系下的基本矢量电压U1的幅值为 U α 2 + U β 2 = 2 3 U d c \sqrt {U_\alpha ^2 + U_\beta ^2} = \frac{2}{3}{U_{dc}} ，方向不变。因为我们判断扇区和PID计算的输出目标矢量电压都是在两相坐标系下进行的，故计算SVPWM也在两相坐标系下进行。

### 2.扇区判断：

{ U 1 = U β U 2 = 1 2 ( − U β + 3 U α ) U 3 = 1 2 ( − U β − 3 U α ) \begin{cases} {{U_1} = {U_\beta }}\\ {{U_2} = \frac{1}{2}( - {U_\beta } + \sqrt 3 {U_\alpha })}\\ {{U_3} = \frac{1}{2}( - {U_\beta } - \sqrt 3 {U_\alpha })} \end{cases} 【这里有点类似Clarke逆变换，但不是哦】

(A,B,C) =000时：

(A,B,C) =111时：

### 3. 计算相邻两个基本矢量电压的作用时间

T x + T y > T s {T_x} + {T_y}> {T_s} 时需要进行等比例缩小处理，处理方式如下：
T x = T x T x + T y , T y = T y T x + T y {T_x} = \frac{{{T_x}}}{{{T_x} + {T_y}}},{T_y} = \frac{{{T_y}}}{{{T_x} + {T_y}}}
T x + T y < T s {T_x} + {T_y} < {T_s} 时，需要引入零矢量电压：
T 0 = T 7 = 1 2 ( T s − T x − T y ) {T_0} = {T_7} = \frac{1}{2}({T_s} - {T_x} - {T_y})

### 4 .三路PWM占空比计算

U 0 ( 000 ) → U 4 ( 100 ) → U 6 ( 110 ) → U 7 ( 111 ) → U 6 ( 110 ) → U 4 ( 100 ) → U 0 ( 000 ) {U_0}(000) \to {U_4}(100) \to {U_6}(110) \to {U_7}(111) \to {U_6}(110) \to {U_4}(100) \to {U_0}(000)

S(C）=1的时间为 T c = T 7 = 1 2 ( T s − T 4 − T 6 ) {T_c} = {T_7} = \frac{1}{2}({T_s} - {T_4} - {T_6})
S(B)=1的时间为 T b = T 7 + T 6 = T c + T 6 {T_b} = {T_7} + {T_6} = {T_c} + {T_6}
S(A)=1的时间为 T a = T 7 + T 6 + T 4 = T b + T 4 {T_a} = {T_7} + {T_6} + {T_4} = {T_b} + {T_4}

U r e f _ max ⁡ = 1 {U_{ref\_\max }} = 1 把目标矢量电压标幺值化，再令Ts=1，就可以把非零电压作用的时间转化为标幺值。

## 算法流程

### step1：扇区判断

C语言代码示例：

    v.U1 = v.Ubeta;                                         \
v.U2 = ( v.Ualpha*0.8660254) - (v.Ubeta*0.5);           \
v.U3 = (-v.Ualpha*0.8660254) - (v.Ubeta*0.5);           \
v.Sector = 0;                                           \
if(v.U1 > 0)    v.Sector += 1;                          \
if(v.U2 > 0)    v.Sector += 2;                          \
if(v.U3 > 0)    v.Sector += 4;                          \


### step2:计算基本矢量电压作用时间（占空比）

C语言代码示例：

    v.Tx = v.Ubeta;                                         \
v.Ty = ( v.Ualpha*0.8660254) + (v.Ubeta*0.5);           \
v.Tz = (-v.Ualpha*0.8660254) + (v.Ubeta*0.5);           \
switch(v.Sector)                                        \
{                                                       \
case 1:{                                            \
v.t1=v.Tz; v.t2=v.Ty;                           \
if((v.t1+v.t2)>1){                              \
v.t1 = v.t1/(v.t1+v.t2);                    \
v.t2 = v.t2/(v.t1+v.t2);                    \
}                                               \
v.Tb = 0.5*(1-v.t1-v.t2);                       \
v.Ta = v.Tb + v.t1;                             \
v.Tc = v.Ta + v.t2;}break;                      \
case 2:{                                            \
v.t1=v.Ty; v.t2=-v.Tx;                          \
if((v.t1+v.t2)>1){                              \
v.t1 = v.t1/(v.t1+v.t2);                    \
v.t2 = v.t2/(v.t1+v.t2);                    \
}                                               \
v.Ta = 0.5*(1-v.t1-v.t2);                       \
v.Tc = v.Ta + v.t1;                             \
v.Tb = v.Tc + v.t2;}break;                      \
case 3:{                                            \
v.t1=-v.Tz; v.t2=v.Tx;                          \
if((v.t1+v.t2)>1){                              \
v.t1 = v.t1/(v.t1+v.t2);                    \
v.t2 = v.t2/(v.t1+v.t2);                    \
}                                               \
v.Ta = 0.5*(1-v.t1-v.t2);                       \
v.Tb = v.Ta + v.t1;                             \
v.Tc = v.Tb + v.t2;}break;                      \
case 4:{                                            \
v.t1=-v.Tx; v.t2=v.Tz;                          \
if((v.t1+v.t2)>1){                              \
v.t1 = v.t1/(v.t1+v.t2);                    \
v.t2 = v.t2/(v.t1+v.t2);                    \
}                                               \
v.Tc = 0.5*(1-v.t1-v.t2);                       \
v.Tb = v.Tc + v.t1;                             \
v.Ta = v.Tb + v.t2;}break;                      \
case 5:{                                            \
v.t1=v.Tx; v.t2=-v.Ty;                          \
if((v.t1+v.t2)>1){                              \
v.t1 = v.t1/(v.t1+v.t2);                    \
v.t2 = v.t2/(v.t1+v.t2);                    \
}                                               \
v.Tb = 0.5*(1-v.t1-v.t2);                       \
v.Tc = v.Tb + v.t1;                             \
v.Ta = v.Tc + v.t2;}break;                      \
case 6:{                                            \
v.t1=-v.Ty; v.t2=-v.Tz;                         \
if((v.t1+v.t2)>1){                              \
v.t1 = v.t1/(v.t1+v.t2);                    \
v.t2 = v.t2/(v.t1+v.t2);                    \
}                                               \
v.Tc = 0.5*(1-v.t1-v.t2);                       \
v.Ta = v.Tc + v.t1;                             \
v.Tb = v.Ta + v.t2;}break;                      \


### step3：计算PWM定时器比较寄存器值

C语言代码如下：

EPwm1Regs.CMPA.half.CMPA = (int16)(MPeriod * Svpwm1.Ta);
EPwm2Regs.CMPA.half.CMPA = (int16)(MPeriod * Svpwm1.Tb);
EPwm3Regs.CMPA.half.CMPA = (int16)(MPeriod * Svpwm1.Tc);


tips:由于这篇文章用到的公式有点多，而公众号的文章编辑器又不支持插入公式，无奈我只能插入图片了，所以看起来排版不是很协调。感兴趣的可以留言或私信，分享PDF源文档哦。

• 90
点赞
• 682
收藏
觉得还不错? 一键收藏
• 12
评论
05-02 1445
06-11 1万+
05-09 2022
06-13 1万+
05-31 7681
07-18 9368
08-26 11万+
05-31 1013

1.余额是钱包充值的虚拟货币，按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载，可以购买VIP、付费专栏及课程。