赞
踩
【电机控制】FOC无刷电机控制(FOC算法篇)-带电流环
【电机控制】SimpleFOC-无刷电机控制(SimpleFOC_studio上位机篇)
B站视频展示:
【电机控制】SimpleFOC无刷电机速度环位置环
提示:以下是本篇文章正文内容,下面案例可供参考
FOC整体框架
三闭环嵌套,电流环在内,然后依次为速度、位置环
关于BLCD的FOC控制,先看电流环,最内环
关于FOC解耦部分,主要根据SimpleFOC代码进行解释
原本的电流环-FOC控制框图是这样的:
三项逆变电路
步骤是这样的:
1.对电机三相电流进行采样得到 Ia,Ib,Ic。
2.将 Ia,Ib,Ic 经过Clark变换得到 I_alpha I_beta。
3.将 I_alpha I_beta 经过Park变换得到 Id,Iq。
4.计算 Id,Iq 和其设定值 Id_ref 和Iq_ref 的误差
5.将上述误差输入两个PID(只用到PI)控制器,得到输出的控制电压Ud、Uq。
6.将 Ud、Uq 进行反Park变换得到 U_alpha U_beta。
7.用 U_alpha U_beta 合成电压空间矢量,输入SVPWM模块进行调制,输出该时刻三个半桥的状态编码值(前文有提到)
8.按照前面输出的编码值控制三相逆变器的MOS管开关,驱动电机
循环上述步骤
但是我们实际电路设计时不会使用三个采样器,只需要两个就够了。因为由基尔霍夫电流定律(KCL),在任一时刻,流入节点的电流之和等于流出节点的电流之和,也就是说
其矩阵形式:
简化为:
if(!current.c)
{
// if only two measured currents
i_alpha = current.a;
i_beta = _1_SQRT3 * current.a + _2_SQRT3 * current.b;
}
else
{
// signal filtering using identity a + b + c = 0. Assumes measurement error is normally distributed.
float mid = (1.f/3) * (current.a + current.b + current.c);
float a = current.a - mid;
float b = current.b - mid;
i_alpha = a;
i_beta = _1_SQRT3 * a + _2_SQRT3 * b;//公式在这里
}
其矩阵形式:
简化为:
// calculate park transform
ct = _cos(angle_el);
st = _sin(angle_el);
ret.d = i_alpha * ct + i_beta * st;
ret.q = i_beta * ct - i_alpha * st;
表贴式PMSM时,ID=0,只作用IQ、UQ
首先在模式选择中,选择foc_current,用电流环
因此需要用电流环PID
case Type_foc_current:
// read dq currents
current = getFOCCurrents(electrical_angle);
// filter values
current.q = LPFoperator(&LPF_current_q,current.q);
current.d = LPFoperator(&LPF_current_d,current.d);
// calculate the phase voltages
voltage.q = PIDoperator(&PID_current_q,(current_sp - current.q));
voltage.d = PIDoperator(&PID_current_d, -current.d);
break;
将电流环的输出值设置为新目标值
case Type_torque:
if(torque_controller==Type_voltage)voltage.q = new_target; // if voltage torque control
else
current_sp = new_target; // if current/foc_current torque control
break;
首先,设定值给到速度设定,那么输出值就需要经过PID算法,
输出值在这里即为设定速度-实际测量速度,然后经过PID算法给到电流环
在这里,由于我们没有用电流采集,因此将输出值给到电压Uq
case Type_velocity:
// velocity set point
shaft_velocity_sp = new_target;
// calculate the torque command
current_sp = PID_velocity(shaft_velocity_sp - shaft_velocity); // if current/foc_current torque control
// if torque controlled through voltage control
if(torque_controller == Type_voltage)
{
voltage.q = current_sp; // use voltage if phase-resistance not provided
voltage.d = 0;
}
break;
首先,设定值给到位置设定,那么位置环输出值需要PID算法,
位置环输出值在这里即为设定位置-实际测量位置,然后经过PID算法给到速度环
其次,输出给到速度设定,那么速度环输出值也需要PID算法,
速度环输出值在这里即为速度设定-实际测量速度,然后经过PID算法给到电流环,
最后,由于我们没有用电流采集,因此将输出值给到电压Uq
case Type_angle:
// angle set point
shaft_angle_sp = new_target;
// calculate velocity set point
shaft_velocity_sp = PID_angle( shaft_angle_sp - shaft_angle );
// calculate the torque command
current_sp = PID_velocity(shaft_velocity_sp - shaft_velocity); // if voltage torque control
// if torque controlled through voltage
if(torque_controller == Type_voltage)
{
voltage.q = current_sp;
voltage.d = 0;
}
break;
将park变换逆变换即可:
FOC最终的执行部分,接收FOC传来的Uα 和Uβ,然后通过上面的过程转换成开关管的控制信号,控制定子绕组产生旋转磁场。
从上图可知,我们可以通过互差120度,大小随着时间按正弦规律变化的3个分矢量来合成一个大小不变旋转的总矢量。于是问题又变成了:如何得到大小随着时间按正弦规律变化的3个分矢量呢?我们先回到电机上,其实这3个分矢量就对应了电机的3个绕组,3个绕组就是互差120度的,只要再控制绕组上的电压大小按照正弦规律变化,是不是就可以得到大小不变旋转的总矢量呢?看下面电机定子的坐标系图:
我们用公式来表示一下:定义这三个电压空间矢量为UA(t)、UB(t)、UC(t),他们方向始终在各自的轴线上,而大小随时间按正弦规律变化,时间相位上互差120度。假设Um为相电压的有效值(相电压呈正弦变化),f为电源频率,则有:
K为常数,可取不同值,在这里取2/3
当开关Sa=1时,UA(t)=Udc(A相相线通过上桥臂直通母线Udc);当开关Sb=1时,UB(t)=Udc;当开关Sc=1时,UC(t)=Udc。
当开关Sa=0时,UA(t)=0(A相相线通过下桥臂直通GND);当开关Sb=0时,UB(t)=0;当开关Sc=0时,UC(t)=0。
这样,合成矢量的关系式就变成了桥臂的开关函数,因此上式可以写成:
这里是三项电压,可是输入给我们的只有两项电压,因此,需要转换。
同理可求得Uref在其它扇区中各矢量的作用时间,结果如表2-4所示。表中两个非零矢量作用时间的比例系数为K =√3Ts/Udc 。
当两个零电压矢量作用时间为0时,一个PWM周期内非零电压矢量的作用时间最长,此时的合成空间电压矢量幅值最大,由下图2-12可知其幅值最大不会超过图中所示的正六边形边界。而当合成矢量落在该边界之外时,将发生过调制,逆变器输出电压波形将发生失真。
在SVPWM调制模式下,逆变器能够输出的最大不失真圆形旋转电压矢量为图2-12所示虚线正六边形的内切圆,
其幅值为:
(√3/ 2)x(2Udc/ 3) =√3Udc/3 。
即逆变器输出的不失真最大正弦相电压幅值为√3Udc /3 ,
因此voltage_limit的设置即为12*1.7/3=6.9,最大值需要小于6.9
voltage_limit=4; //V,最大值需小于12/1.732=6.9
voltage_power_supply的设置,驱动供电,驱动芯片我的设置12V
Udc值设置为:
voltage_power_supply=12; //V
代码Uout的设置,,前文提到,我们只用Uq,因此就看else后面的就可以了,
if(Ud) // only if Ud and Uq set
{// _sqrt is an approx of sqrt (3-4% error)
Uout = _sqrt(Ud*Ud + Uq*Uq) / voltage_power_supply;
// angle normalisation in between 0 and 2pi
// only necessary if using _sin and _cos - approximation functions
angle_el = _normalizeAngle(angle_el + atan2(Uq, Ud));
}
else
{// only Uq available - no need for atan2 and sqrt
Uout = Uq / voltage_power_supply;
// angle normalisation in between 0 and 2pi
// only necessary if using _sin and _cos - approximation functions
angle_el = _normalizeAngle(angle_el + _PI_2);
}
空间矢量调制的第一步是判断由Uα 和Uβ所决定的空间电压矢量所处的扇区。
假定合成的电压矢量落在第 I 扇区,
可知其等价条件如下:
0<arctan(Uβ/ Uα) <60
落在第 I 扇区的充分必要条件为:
Uα > 0 ,Uβ > 0 且Uβ/Uα <√3。
同理可得到合成的电压矢量落在其它扇区的等价条件,得出:
Uref落在第Ⅱ扇区的充要条件为:Uβ>0 且Uβ/ Ua>√3;
Uref落在第Ⅲ扇区的充要条件为:Ua<0 ,Uβ> 0 且-Uβ/Ua <√3;
Uref落在第Ⅳ扇区的充要条件为:Ua<0 ,Uβ < 0 且Uβ/Ua <√3;
Uref落在第Ⅴ扇区的充要条件为:Uβ<0 且 -Uβ/Ua>√3;
Uref落在第Ⅵ扇区的充要条件为:Ua>0 ,Uβ<0且-Uβ/Ua <√3;
再定义,
若U1 > 0 ,则 A=1,否则 A=0;
若U2 > 0 ,则B=1,否则 B=0;
若U3 > 0 ,则 C=1,否则 C=0。
可以看出 A,B,C 之间共有八种组合,但由判断扇区的公式可知 A,B,C 不会同时为 1 或同时为 0,所以实际的组合是六种,A,B,C 组合取不同的值对应着不同的扇区,并且是一一对应的,因此完全可以由 A,B,C 的组合判断所在的扇区。为区别六种状态,令
N=4*C+2*B+A,
代码:通过角度计算当前扇区:
sector = (angle_el / _PI_3) + 1;
则可以通过下表计算参考电压矢量Uref所在的扇区。
对照矢量图,可总结
Udc表示电源电压(在代码中是voltage_limit),Uref表示设置的力矩大小(在代码中是target_voltage),Ts表示PWM周期(代码中没有把Ts体现出来,代码中的T1、T2是周期的百分比)。
代码Udc的设置
代码:将T1(Tx)、T2(Ty)、T0的值表示出来
T1 = _SQRT3*_sin(sector*_PI_3 - angle_el) * Uout;
T2 = _SQRT3*_sin(angle_el - (sector-1.0)*_PI_3) * Uout;
T0 = 1 - T1 - T2;
至此,PWM波周期的百分比就找出来了
————————————————————————————————
如图当合成电压矢量端点落在正六边形与外接圆之间时,已发生过调制,输出电压将发生失真,必须采取过调制处理,这里采用一种比例缩小算法。
在每一个扇区,选择相邻两个电压矢量以及零矢量,按照伏秒平衡原则来合成每个扇区内的任意电压矢量,即:
定义每个扇区中先发生的矢量用为Tx,后发生的矢量为 Ty。
当 Tx+Ty≤TS时,矢量端点在正六边形之内,不发生过调制;当Tx+Ty>TS时,矢量端点超出正六边形,发生过调制。输出的波形会出现严重的失真,需采取以下措施:
设将电压矢量端点轨迹端点拉回至正六边形内切圆内时两非零矢量作用时间分别为 Tx’,Ty’,则有比例关系:
使用上面的简单比例关系,把两个非零矢量作用时间矫正好。
代码:找到扇区后,再代入到每个扇区的公式:
switch(sector)
{
case 1:
Ta = T1 + T2 + T0/2;
Tb = T2 + T0/2;
Tc = T0/2;
break;
case 2:
Ta = T1 + T0/2;
Tb = T1 + T2 + T0/2;
Tc = T0/2;
break;
case 3:
Ta = T0/2;
Tb = T1 + T2 + T0/2;
Tc = T2 + T0/2;
break;
case 4:
Ta = T0/2;
Tb = T1+ T0/2;
Tc = T1 + T2 + T0/2;
break;
case 5:
Ta = T2 + T0/2;
Tb = T0/2;
Tc = T1 + T2 + T0/2;
break;
case 6:
Ta = T1 + T2 + T0/2;
Tb = T0/2;
Tc = T1 + T0/2;
break;
default: // possible error state
Ta = 0;
Tb = 0;
Tc = 0;
}
TIM_SetCompare1(TIM2,Ta*PWM_Period);
TIM_SetCompare2(TIM2,Tb*PWM_Period);
TIM_SetCompare3(TIM2,Tc*PWM_Period);
FOC之SVPWM学习笔记-CSDN博客
深入浅出讲解FOC算法与SVPWM技术-稚晖君
SVPWM分析、各个扇区详细计算以及Matlab仿真-CSDN博客
SimpleFOC(八)—— 理论+实践 深度分析SVPWM
SVPWM算法原理及详解
SimpleFOC、ODrive和VESC 教程链接汇总
本文仅仅简单介绍了FOC无刷电机控制(FOC算法篇)方面,评论区欢迎讨论。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。