需要底层基础知识:
- 固定已有线圈,产生的磁场与电流呈线性正相关
- 线圈是感抗器件,不允许电流突变,故:固定频率输入下,流经的电流与有效电压有关,即与PWM的占空比有关,且呈正相关
- 熟练应用力的合成与分解,即坐标转换
前言:以一对极永磁同步电机为例,不考虑转子位置,静态控制三个定子线圈产生任意角度。俯视电机,电机的有效部分看作一个圆盘,三个定子线圈两两之间成120°夹角围绕转子形成一个圆。控制三个磁场的电流可以合成任意角度的磁场。电机的三个线圈用Y型接法,故引出三根线,命名为U、V、W三相,给这三相供不同的电流可以合成任意角度磁场。
1、SVPWM理论
SVPWM的输入是直角坐标系下正交的两个电压值,这里令U轴电流方向是直角坐标系的横坐标命名为α轴,电流流向电机为正,纵坐标正交于横坐标且过电机的轴心命名为β轴,这样就把这个圆分成了六个区域,括号内的是UVW的电压(UVW),1是给电压,0是接地。
当输入U给电压V和W接地,即(100),定子的磁场方向的α轴重合,磁场角度为0°;
当输入U和V给电压W接地,即(110),电机定子励磁的磁场方向为60°依此类推。
其中(000)和(111)同等含义,模长都为0,因此方向没有意义。
2、磁场合成
上图所示U1-U6都是固定磁场,且磁场强度都是最大值,U4是0°,U6是60°,U2是120°,U3是180°,U1是240°,U5是300°,要想任意磁场角度和强度,需要对磁场进行合成。
以合成磁场30°为例,需要对U4和U6同时供等强度的电,这样才能合成。至于怎么供等强度的电,上文说过感性负载不能电流突变,但是供给电压是有人为控制的可突变,利用这个特性先给U4供电,然后突然变成U6供电,快速不停的切换U4和U6,并保证U4和U6同等的时间和电压,这样U4和U6即同时产生相同强度的磁场,磁场合成就有了30°。
以磁场强度缩减,也以30°的磁场为例。在合成磁场的基础上,同时缩减U4和U6的供电强度,就能做到把30°的合成磁场强度缩减。怎么缩减U4和U6的磁场,上文说过,有两个零矢量(000)(111),把这两个零矢量添加到U4和U6的电压里面就可以缩减U4和U6的磁场强度。T0是零向量(000)的占用时间,T7是零向量(111)的占用时间,T4是U4(100)向量的供电占用时间,T6是U6(110)向量的供电时间,Ts是整个周期时间。如下图
改变T4和T6的比例可以改变磁场方向(0-60°),如30°,T4:T6=1;改变(T4+T6):(Ts)的比例可以改变磁场强度。
3、代码部分
//FOC的准备工作,首先需要三角函数计算,由于函数库计算太慢
//这里先把0~360度的三角函数全算了,用的时候直接查表
void FOCsin10000K(short *Dsin,short *Dcos)
{
short jki;
for(jki=0;jki<360;jki++)
{
if(jki<=90)
Dsin[jki]=sin(jki*3.1415926/180)*10000+0.5;//放大10000倍
else if((jki>90)&(jki<=180))
Dsin[jki]=Dsin[180-jki];
else if((jki>180)&(jki<=270))
Dsin[jki]=-Dsin[jki-180];
else
Dsin[jki]=-Dsin[360-jki];
if(jki>=90)
Dcos[jki-90]=Dsin[jki];
else
Dcos[jki+270]=Dsin[jki];
}
for(jki=0;jki<360;jki++)
{
if(jki==90)
Dtan[90] = 10000;
else if(jki==270)
Dtan[270] = -10000;
else
Dtan[jki] = tan(jki*3.1415926/180)*100+0.5;//放大100倍
}
Dtan[360]= Dtan[0];
}
//SVPWM
unsigned char FOCpwmDrive(long va,long vb,long Vdc,unsigned short Tpwm) //OK va-A_alpha_Voltage,vb-B_beta_Voltage
{
long tanh;//A_B_include_angle_tan_Value = vb/va
long Vx,Vy;//include_angle_60_double_value
long Tx,Ty,Ts,T0;//include_angle_60_double_time
unsigned char sn=0;
//防止计算tan值时,出现分母为0情况
if(va==0)
{
if(vb >= 0)
tanh=173210;
else
tanh = -173210;
}
else//计算tan值
tanh=vb*10000/va;
//先判断象限,然后根据tan值再判断区间
if(vb>=0)//第一二象限
{
if((va>=0)&(tanh<17321))//1区 0 --- 60
{
sn=1;//section 1~6 this section is not rotor and alpha include angle, this aim and alpha include angle
Vx=(1500*va-866*vb)/1000;//3/2*va-sqrt(3)/2*vb; //V1
Vy=1732*vb/1000;//sqrt(3)*vb; //V2
Tx=Vx*Tpwm/Vdc;
Ty=Vy*Tpwm/Vdc;
if(Tx+Ty > Tpwm)
{
Ts=Tx*Tpwm/(Tx+Ty);
Ty=Ty*Tpwm/(Tx+Ty);
Tx=Ts;
}
T0=(Tpwm-Tx-Ty)/2;
SVPWMtabc.ta = T0;
SVPWMtabc.tb = T0+Tx;
SVPWMtabc.tc = T0+Tx+Ty;
}
else if((va<0) & (tanh>=-17321))//3区 120 --- 180
{
sn=3;
Vx=1732*vb/1000;//sqrt(3)*vb; //V3
Vy=(-1500*va-866*vb)/1000;//-3/2*va-sqrt(3)/2*vb; //V4
Tx=Vx*Tpwm/Vdc;
Ty=Vy*Tpwm/Vdc;
if(Tx+Ty > Tpwm)
{
Ts=Tx*Tpwm/(Tx+Ty);
Ty=Ty*Tpwm/(Tx+Ty);
Tx=Ts;
}
T0=(Tpwm-Tx-Ty)/2;
SVPWMtabc.ta = T0+Tx+Ty;
SVPWMtabc.tb = T0;
SVPWMtabc.tc = T0+Tx;
}
else//第二区 60 --- 120
{
//2
sn=2;
Vy=(1500*va+866*vb)/1000;//3/2*va+sqrt(3)/2*vb; //V2
Vx=(866*vb-1500*va)/1000;//sqrt(3)/2*vb-3/2*va; //V3
Tx=Vx*Tpwm/Vdc;
Ty=Vy*Tpwm/Vdc;
if(Tx+Ty > Tpwm)
{
Ts=Tx*Tpwm/(Tx+Ty);
Ty=Ty*Tpwm/(Tx+Ty);
Tx=Ts;
}
T0=(Tpwm-Tx-Ty)/2;
SVPWMtabc.ta = T0+Tx;
SVPWMtabc.tb = T0;
SVPWMtabc.tc = T0+Tx+Ty;
}
}
else//第三四象限。对应4,5,6区间
{
if((va<=0)&(tanh<=17321)&(tanh>=0))//第四区间180 --- 240
{
//4
sn=4;
Vy=(866*vb-1500*va)/1000;//sqrt(3)/2*vb-3/2*va; //V4
Vx=-1732*vb/1000;//-sqrt(3)*vb; //V5
Tx=Vx*Tpwm/Vdc;
Ty=Vy*Tpwm/Vdc;
if(Tx+Ty > Tpwm)
{
Ts=Tx*Tpwm/(Tx+Ty);
Ty=Ty*Tpwm/(Tx+Ty);
Tx=Ts;
}
T0=(Tpwm-Tx-Ty)/2;
SVPWMtabc.ta = T0+Tx+Ty;
SVPWMtabc.tb = T0+Tx;
SVPWMtabc.tc = T0;
}
else if((va>0)&(tanh >= -17321))//第六区 300 -- 360
{
//6
sn=6;
Vy=-1732*vb/1000;//-sqrt(3)*vb; //V6
Vx=(1500*va+866*vb)/1000;//3/2*va+sqrt(3)/2*vb; //V1
Tx=Vx*Tpwm/Vdc;
Ty=Vy*Tpwm/Vdc;
if(Tx+Ty > Tpwm)
{
Ts=Tx*Tpwm/(Tx+Ty);
Ty=Ty*Tpwm/(Tx+Ty);
Tx=Ts;
}
T0=(Tpwm-Tx-Ty)/2;
SVPWMtabc.ta = T0;
SVPWMtabc.tb = T0+Tx+Ty;
SVPWMtabc.tc = T0+Tx;
}
else//第5区 240 --- 300
{
sn=5;
Vx=(-866*vb-1500*va)/1000;//-sqrt(3)/2*vb-3/2*va; //V5
Vy=(1500*va-866*vb)/1000;//3/2*va-sqrt(3)/2*vb; //V6
Tx=Vx*Tpwm/Vdc;
Ty=Vy*Tpwm/Vdc;
if(Tx+Ty > Tpwm)
{
Ts=Tx*Tpwm/(Tx+Ty);
Ty=Ty*Tpwm/(Tx+Ty);
Tx=Ts;
}
T0=(Tpwm-Tx-Ty)/2;
SVPWMtabc.ta = T0+Tx;
SVPWMtabc.tb = T0+Tx+Ty;
SVPWMtabc.tc = T0;
}
}
SVPWMtabc.sn = sn;
if((Vx>=0)&(Vy>=0))
return 1;
else
return 0;//出错
}