空间矢量图
Step1 扇区判定
Step2 区域判定
Step3 矢量作用时间计算
调制时间波形
SVPWM代码
#define PI_1_3 1.0471975512
#define sqrt_3 1.7320508076
#define sqrt_3_p2 3.4641016151377545870548926830117
#define sqrt_3_1 0.577350269
#define PI_D_6 0.52359877559829887307710723054658
#define sqrt_3_d6 0.28867513459481288225457439025098
void svgendq_threelevel_calc(SVGENDQ_THREELEVEL *v,PWM_ABC_3_LEVEL *PWMOut)
{
//--------Input Variables--------
Uint16 N=0;
Uint16 n=0;
float theta;
float sine,cosine;
float m1,m2,m3;
float Zeta=0;
float Uref = 0;
float Ma = 0;
float x,y;
float Ta=0,Tb=0,Tc=0;//矢量作用时间
float T1,T2,T3; //矢量作用时间-按照先后排序
float D1,D2,D3; //占空比,未分相,由瘦到胖
float DNp1,DNp2,DNp3;
float DutyA1,DutyA2,DutyB1,DutyB2,DutyC1,DutyC2;//ABC 三相占空比
theta = v->theta*PI2;
//------------------Step 2---------------
if(theta >= 0 && theta < PI_1_3) N = 1;
else if(theta >= PI_1_3 && theta < PI_1_3 * 2) N = 2;
else if(theta >= PI_1_3*2 && theta < PI) N = 3;
else if(theta >= PI && theta < PI_1_3*4) N = 4;
else if(theta >= PI_1_3*4 && theta < PI_1_3*5) N = 5;
else if(theta >= PI_1_3*5 && theta < PI2) N = 6;
else N = 1;
//------------------Step 3---------------
Zeta = theta - PI_1_3*(N-1);
//------------------Step 4---------------
Uref = sqrt(v->Ualpha_In * v->Ualpha_In + v->Ubeta_In * v->Ubeta_In);
//------------------Step 5----------------
// sincos(Zeta,&sine,&cosine);
sine = sin(Zeta);
cosine= cos(Zeta);
x = Uref*cosine;
y = Uref*sine;
if(Zeta <= PI_D_6) //Region 1 3 5
{
if(y <= (-sqrt_3*x +sqrt_3_1*v->Udc_In))
{
n = 1;
}
else if(y <= (sqrt_3*x - sqrt_3_1*v->Udc_In))
{
n = 5;
}
else
{
n = 3;
}
}
else //Region 2 4 6
{
if(y <= (-sqrt_3*x +sqrt_3_1*v->Udc_In))
{
n = 2;
}
else if(y >= sqrt_3_d6*v->Udc_In)
{
n = 6;
}
else
{
n = 4;
}
}
Ma = sqrt_3_p2*Uref/v->Udc_In;
m3 = Ma * sine;
sine = sin(PI_1_3 - Zeta);
m1 = Ma*sine;
sine = sin(PI_1_3 + Zeta);
m2 = Ma*sine;
//------------------Step 6----------------
if(N == 1 || N==3 || N==5)
{
switch(n)
{
case 1:Ta = m1;Tb = 1 - m2;Tc = m3; break;
case 2:Ta = m1;Tb = 1 - m2;Tc = m3; break;
case 3:Ta = 1 - m3;Tb = m2 - 1;Tc = 1 - m1;break;
case 4:Ta = 1 - m3;Tb = m2 - 1;Tc = 1 - m1;break;
case 5:Ta = 2- m2;Tb = m3;Tc = m1 - 1;break;
case 6:Ta = m3 - 1;Tb = m1;Tc = 2- m2;break;
default:Ta = 0;Tb = 0;Tc = 0;break;
}
}
else
{
switch(n)
{
case 1:Ta = m3;Tb = 1 - m2;Tc = m1;break;
case 2:Ta = m3;Tb = 1 - m2;Tc = m1;break;
case 3:Ta = 1 - m1;Tb = m2 - 1;Tc = 1 - m3;break;
case 4:Ta = 1 - m1;Tb = m2 - 1;Tc = 1 - m3;break;
case 5:Ta = m1 - 1;Tb = m3;Tc = 2- m2;break;
case 6:Ta = 2- m2;Tb = m1;Tc = m3 - 1;break;
default:Ta = 0;Tb = 0;Tc = 0;break;
}
}
//------------------Step 7----------------
if((N == 1)||(N == 3)||(N == 5))
{
if((n == 1)||(n == 3)||(n == 5))
{
T1 = Ta;
T2 = Tc;
T3 = Tb;
}
else
{
T1 = Tc;
T2 = Tb;
T3 = Ta;
}
}
else
{
if((n == 1)||(n == 3)||(n == 5))
{
T1 = Tc;
T2 = Tb;
T3 = Ta;
}
else
{
T1 = Ta;
T2 = Tc;
T3 = Tb;
}
}
//------------------Step 8----------------
D1 = T1*0.5;
D2 = T1*0.5+T3;
D3 = T1*0.5+T3+T2;
//------------------Step 9----------------
if (v->NPFactor_In > (T1*0.8))
{
v->NPFactor_In = T1*0.8;
}
else if(v->NPFactor_In < (-T1*0.8))
{
v->NPFactor_In = -T1*0.8;
}
switch(N)
{
case 1: //N
if((n == 1)||(n == 3)||(n==5))
{
if(v->Ia_In >= 0)
{
DNp1 = D1 - v->NPFactor_In*0.5;
DNp2 = D2 - v->NPFactor_In*0.5;
DNp3 = D3 - v->NPFactor_In*0.5;
}
else
{
DNp1 = D1 + v->NPFactor_In*0.5;
DNp2 = D2 + v->NPFactor_In*0.5;
DNp3 = D3 + v->NPFactor_In*0.5;
}
}
else
{
if(v->Ic_In >= 0)
{
DNp1 = D1 + v->NPFactor_In*0.5;
DNp2 = D2 + v->NPFactor_In*0.5;
DNp3 = D3 + v->NPFactor_In*0.5;
}
else
{
DNp1 = D1 - v->NPFactor_In*0.5;
DNp2 = D2 - v->NPFactor_In*0.5;
DNp3 = D3 - v->NPFactor_In*0.5;
}
}
break;
case 2: //N
if((n == 1)||(n == 3)||(n==5))
{
if(v->Ic_In >= 0)
{
DNp1 = D1 + v->NPFactor_In*0.5;
DNp2 = D2 + v->NPFactor_In*0.5;
DNp3 = D3 + v->NPFactor_In*0.5;
}
else
{
DNp1 = D1 - v->NPFactor_In*0.5;
DNp2 = D2 - v->NPFactor_In*0.5;
DNp3 = D3 - v->NPFactor_In*0.5;
}
}
else
{
if(v->Ib_In >= 0)
{
DNp1 = D1 - v->NPFactor_In*0.5;
DNp2 = D2 - v->NPFactor_In*0.5;
DNp3 = D3 - v->NPFactor_In*0.5;
}
else
{
DNp1 = D1 + v->NPFactor_In*0.5;
DNp2 = D2 + v->NPFactor_In*0.5;
DNp3 = D3 + v->NPFactor_In*0.5;
}
}
break;
case 3: //N
if((n == 1)||(n == 3)||(n==5))
{
if(v->Ib_In >= 0)
{
DNp1 = D1 - v->NPFactor_In*0.5;
DNp2 = D2 - v->NPFactor_In*0.5;
DNp3 = D3 - v->NPFactor_In*0.5;
}
else
{
DNp1 = D1 + v->NPFactor_In*0.5;
DNp2 = D2 + v->NPFactor_In*0.5;
DNp3 = D3 + v->NPFactor_In*0.5;
}
}
else
{
if(v->Ia_In >= 0)
{
DNp1 = D1 + v->NPFactor_In*0.5;
DNp2 = D2 + v->NPFactor_In*0.5;
DNp3 = D3 + v->NPFactor_In*0.5;
}
else
{
DNp1 = D1 - v->NPFactor_In*0.5;
DNp2 = D2 - v->NPFactor_In*0.5;
DNp3 = D3 - v->NPFactor_In*0.5;
}
}
break;
case 4: //N
if((n == 1)||(n == 3)||(n==5))
{
if(v->Ia_In >= 0)
{
DNp1 = D1 + v->NPFactor_In*0.5;
DNp2 = D2 + v->NPFactor_In*0.5;
DNp3 = D3 + v->NPFactor_In*0.5;
}
else
{
DNp1 = D1 - v->NPFactor_In*0.5;
DNp2 = D2 - v->NPFactor_In*0.5;
DNp3 = D3 - v->NPFactor_In*0.5;
}
}
else
{
if(v->Ic_In >= 0)
{
DNp1 = D1 - v->NPFactor_In*0.5;
DNp2 = D2 - v->NPFactor_In*0.5;
DNp3 = D3 - v->NPFactor_In*0.5;
}
else
{
DNp1 = D1 + v->NPFactor_In*0.5;
DNp2 = D2 + v->NPFactor_In*0.5;
DNp3 = D3 + v->NPFactor_In*0.5;
}
}
break;
case 5: //N
if((n == 1)||(n == 3)||(n==5))
{
if(v->Ic_In >= 0)
{
DNp1 = D1 - v->NPFactor_In*0.5;
DNp2 = D2 - v->NPFactor_In*0.5;
DNp3 = D3 - v->NPFactor_In*0.5;
}
else
{
DNp1 = D1 + v->NPFactor_In*0.5;
DNp2 = D2 + v->NPFactor_In*0.5;
DNp3 = D3 + v->NPFactor_In*0.5;
}
}
else
{
if(v->Ib_In >= 0)
{
DNp1 = D1 + v->NPFactor_In*0.5;
DNp2 = D2 + v->NPFactor_In*0.5;
DNp3 = D3 + v->NPFactor_In*0.5;
}
else
{
DNp1 = D1 - v->NPFactor_In*0.5;
DNp2 = D2 - v->NPFactor_In*0.5;
DNp3 = D3 - v->NPFactor_In*0.5;
}
}
break;
case 6: //N
if((n == 1)||(n == 3)||(n==5))
{
if(v->Ib_In >= 0)
{
DNp1 = D1 + v->NPFactor_In*0.5;
DNp2 = D2 + v->NPFactor_In*0.5;
DNp3 = D3 + v->NPFactor_In*0.5;
}
else
{
DNp1 = D1 - v->NPFactor_In*0.5;
DNp2 = D2 - v->NPFactor_In*0.5;
DNp3 = D3 - v->NPFactor_In*0.5;
}
}
else
{
if(v->Ia_In >= 0)
{
DNp1 = D1 - v->NPFactor_In*0.5;
DNp2 = D2 - v->NPFactor_In*0.5;
DNp3 = D3 - v->NPFactor_In*0.5;
}
else
{
DNp1 = D1 + v->NPFactor_In*0.5;
DNp2 = D2 + v->NPFactor_In*0.5;
DNp3 = D3 + v->NPFactor_In*0.5;
}
}
break;
}
//------------------Step 10----------------
LIMIT(DNp1,v->pMaxDuty,v->pMinDuty);
LIMIT(DNp2,v->pMaxDuty,v->pMinDuty);
LIMIT(DNp3,v->pMaxDuty,v->pMinDuty);
//------------------Step 11----------------
switch(N)
{
case 1:
switch(n)
{
case 1:
DutyA1 = DNp1;
DutyA2 = 1;
DutyB1 = 0;
DutyB2 = DNp3;
DutyC1 = 0;
DutyC2 = DNp2;
break;
case 2:
DutyA1 = DNp2;
DutyA2 = 1;
DutyB1 = DNp1;
DutyB2 = 1;
DutyC1 = 0;
DutyC2 = DNp3;
break;
case 3:
DutyA1 = DNp2;
DutyA2 = 1;
DutyB1 = 0;
DutyB2 = DNp3;
DutyC1 = 0;
DutyC2 = DNp1;
break;
case 4:
DutyA1 = DNp3;
DutyA2 = 1;
DutyB1 = DNp1;
DutyB2 = 1;
DutyC1 = 0;
DutyC2 = DNp2;
break;
case 5:
DutyA1 = DNp3;
DutyA2 = 1;
DutyB1 = 0;
DutyB2 = DNp2;
DutyC1 = 0;
DutyC2 = DNp1;
break;
case 6:
DutyA1 = DNp3;
DutyA2 = 1;
DutyB1 = DNp2;
DutyB2 = 1;
DutyC1 = 0;
DutyC2 = DNp1;
break;
}
break;
case 2:
switch(n)
{
case 1:
DutyA1 = DNp1;
DutyA2 = 1;
DutyB1 = DNp2;
DutyB2 = 1;
DutyC1 = 0;
DutyC2 = DNp3;
break;
case 2:
DutyA1 = 0;
DutyA2 = DNp3;
DutyB1 = DNp1;
DutyB2 = 1;
DutyC1 = 0;
DutyC2 = DNp2;
break;
case 3:
DutyA1 = DNp1;
DutyA2 = 1;
DutyB1 = DNp3;
DutyB2 = 1;
DutyC1 = 0;
DutyC2 = DNp2;
break;
case 4:
DutyA1 = 0;
DutyA2 = DNp3;
DutyB1 = DNp2;
DutyB2 = 1;
DutyC1 = 0;
DutyC2 = DNp1;
break;
case 5:
DutyA1 = DNp2;
DutyA2 = 1;
DutyB1 = DNp3;
DutyB2 = 1;
DutyC1 = 0;
DutyC2 = DNp1;
break;
case 6:
DutyA1 = 0;
DutyA2 = DNp2;
DutyB1 = DNp3;
DutyB2 = 1;
DutyC1 = 0;
DutyC2 = DNp1;
break;
}
break;
case 3:
switch(n)
{
case 1:
DutyA1 = 0;
DutyA2 = DNp2;
DutyB1 = DNp1;
DutyB2 = 1;
DutyC1 = 0;
DutyC2 = DNp3;
break;
case 2:
DutyA1 = 0;
DutyA2 = DNp3;
DutyB1 = DNp2;
DutyB2 = 1;
DutyC1 = DNp1;
DutyC2 = 1;
break;
case 3:
DutyA1 = 0;
DutyA2 = DNp1;
DutyB1 = DNp2;
DutyB2 = 1;
DutyC1 = 0;
DutyC2 = DNp3;
break;
case 4:
DutyA1 = 0;
DutyA2 = DNp2;
DutyB1 = DNp3;
DutyB2 = 1;
DutyC1 = DNp1;
DutyC2 = 1;
break;
case 5:
DutyA1 = 0;
DutyA2 = DNp1;
DutyB1 = DNp3;
DutyB2 = 1;
DutyC1 = 0;
DutyC2 = DNp2;
break;
case 6:
DutyA1 = 0;
DutyA2 = DNp1;
DutyB1 = DNp3;
DutyB2 = 1;
DutyC1 = DNp2;
DutyC2 = 1;
break;
}
break;
case 4:
switch(n)
{
case 1:
DutyA1 = 0;
DutyA2 = DNp3;
DutyB1 = DNp1;
DutyB2 = 1;
DutyC1 = DNp2;
DutyC2 = 1;
break;
case 2:
DutyA1 = 0;
DutyA2 = DNp2;
DutyB1 = 0;
DutyB2 = DNp3;
DutyC1 = DNp1;
DutyC2 = 1;
break;
case 3:
DutyA1 = 0;
DutyA2 = DNp2;
DutyB1 = DNp1;
DutyB2 = 1;
DutyC1 = DNp3;
DutyC2 = 1;
break;
case 4:
DutyA1 = 0;
DutyA2 = DNp1;
DutyB1 = 0;
DutyB2 = DNp3;
DutyC1 = DNp2;
DutyC2 = 1;
break;
case 5:
DutyA1 = 0;
DutyA2 = DNp1;
DutyB1 = DNp2;
DutyB2 = 1;
DutyC1 = DNp3;
DutyC2 = 1;
break;
case 6:
DutyA1 = 0;
DutyA2 = DNp1;
DutyB1 = 0;
DutyB2 = DNp2;
DutyC1 = DNp3;
DutyC2 = 1;
break;
}
break;
case 5:
switch(n)
{
case 1:
DutyA1 = 0;
DutyA2 = DNp3;
DutyB1 = 0;
DutyB2 = DNp2;
DutyC1 = DNp1;
DutyC2 = 1;
break;
case 2:
DutyA1 = DNp1;
DutyA2 = 1;
DutyB1 = 0;
DutyB2 = DNp3;
DutyC1 = DNp2;
DutyC2 = 1;
break;
case 3:
DutyA1 = 0;
DutyA2 = DNp3;
DutyB1 = 0;
DutyB2 = DNp1;
DutyC1 = DNp2;
DutyC2 = 1;
break;
case 4:
DutyA1 = DNp1;
DutyA2 = 1;
DutyB1 = 0;
DutyB2 = DNp2;
DutyC1 = DNp3;
DutyC2 = 1;
break;
case 5:
DutyA1 = 0;
DutyA2 = DNp2;
DutyB1 = 0;
DutyB2 = DNp1;
DutyC1 = DNp3;
DutyC2 = 1;
break;
case 6:
DutyA1 = DNp2;
DutyA2 = 1;
DutyB1 = 0;
DutyB2 = DNp1;
DutyC1 = DNp3;
DutyC2 = 1;
break;
}
break;
case 6:
switch(n)
{
case 1:
DutyA1 = DNp2;
DutyA2 = 1;
DutyB1 = 0;
DutyB2 = DNp3;
DutyC1 = DNp1;
DutyC2 = 1;
break;
case 2:
DutyA1 = DNp1;
DutyA2 = 1;
DutyB1 = 0;
DutyB2 = DNp2;
DutyC1 = 0;
DutyC2 = DNp3;
break;
case 3:
DutyA1 = DNp3;
DutyA2 = 1;
DutyB1 = 0;
DutyB2 = DNp2;
DutyC1 = DNp1;
DutyC2 = 1;
break;
case 4:
DutyA1 = DNp2;
DutyA2 = 1;
DutyB1 = 0;
DutyB2 = DNp1;
DutyC1 = 0;
DutyC2 = DNp3;
break;
case 5:
DutyA1 = DNp3;
DutyA2 = 1;
DutyB1 = 0;
DutyB2 = DNp1;
DutyC1 = DNp2;
DutyC2 = 1;
break;
case 6:
DutyA1 = DNp3;
DutyA2 = 1;
DutyB1 = 0;
DutyB2 = DNp1;
DutyC1 = 0;
DutyC2 = DNp2;
break;
}
break;
}
//-----------Update Output-------------
PWMOut->Ta13 = DutyA1;
PWMOut->Ta24 = DutyA2;
PWMOut->Tb13 = DutyB1;
PWMOut->Tb24 = DutyB2;
PWMOut->Tc13 = DutyC1;
PWMOut->Tc24 = DutyC2;
}
应用示例
// 开环给定
Sp->SpsCtlInner.Pwm_Udq.dp = Sp->SpsCtlCfg.InvUdRef *Sp->SpsCtlInner.BaseValue.Ubase_1;
Sp->SpsCtlInner.Pwm_Udq.qp = 0;
Sp->SpsCtlInner.Pwm_Udc = Sp->SpsCtlCfg.InvUdcRef *Sp->SpsCtlInner.BaseValue.Udcbase_1;
// 自生成角度
genvf.Frequency = Sp->SpsCtlCfg.InvFreqRef*Sp->SpsCtlInner.BaseValue.Fbase_1;
genvf.dt = Sp->SpsCtlOutPort.SwiCalTime.CtlDt;
Sp->SpsCtlOutPort.Freqs_toRms = genvf.Frequency *Sp->SpsCtlInner.BaseValue.Fbase;
gen_vf_pll(&genvf);
ipark_calc(Sp->SpsCtlInner.Pwm_Udq.dp,
0,
genvf.SineTheta,
genvf.CoseTheta,
&Sp->SpsCtlInner.PwmAlphaBeta.alpha_p,
&Sp->SpsCtlInner.PwmAlphaBeta.beta_p);
//Svpwm 给定
Sp->SpsCtlInner.Svpwm_In.Ualpha_In = Sp->SpsCtlInner.PwmAlphaBeta.alpha_p;
Sp->SpsCtlInner.Svpwm_In.Ubeta_In = Sp->SpsCtlInner.PwmAlphaBeta.beta_p;
Sp->SpsCtlInner.Svpwm_In.Udc_In =Sp->SpsCtlInner.Pwm_Udc;
Sp->SpsCtlInner.Svpwm_In.theta =genvf.theta;
Sp->SpsCtlInner.Svpwm_In.NPFactor_In=0;
Sp->SpsCtlInner.Svpwm_In.Ia_In=0;
Sp->SpsCtlInner.Svpwm_In.Ib_In=0;
Sp->SpsCtlInner.Svpwm_In.Ic_In=0;
Sp->SpsCtlInner.Svpwm_In.pMinDuty=0;
Sp->SpsCtlInner.Svpwm_In.pMaxDuty=100;
svgendq_threelevel_calc(&(Sp->SpsCtlInner.Svpwm_In),&(Sp->SpsCtlOutPort.PwmOut3L));
LIMIT(Sp->SpsCtlOutPort.PwmOut3L.Ta13,1,0);
LIMIT(Sp->SpsCtlOutPort.PwmOut3L.Ta24,1,0);
LIMIT(Sp->SpsCtlOutPort.PwmOut3L.Tb13,1,0);
LIMIT(Sp->SpsCtlOutPort.PwmOut3L.Tb24,1,0);
LIMIT(Sp->SpsCtlOutPort.PwmOut3L.Tc13,1,0);
LIMIT(Sp->SpsCtlOutPort.PwmOut3L.Tc24,1,0);
RP3220 控制器 在 PLECS RTLAB仿真测试