ST Motor FOC库-Circle Limitation功能理解
功能介绍
源代码位于MC_FOC_DRIVE.c,处于PID环节之后;
个人理解,由于PID对于Vd,Vq的输出是相对独立的,因此很有可能会出现矢量过调制的现象,需要对输出的Vd,Vq进行处理,使其始终保持在单位矢量圆内部(单位矢量圆指调制比达到100%时构成的电压矢量圆),就是合成电压矢量在圆内的,保持原值,超出限制圆的,一律按照限制圆半径处理(所有的处理都是为了保持Vd,Vq合成的电压矢量保持在限制圆内部)。
同时由于死区时间,PWM开关频率的影响,通常会限制的更深一点,即处理后的电压矢量要控制在比单位圆半径更小一点的圆中。
算法介绍
假设令所能允许的矢量圆半径为
M
A
X
_
M
O
D
U
L
E
MAX\_MODULE
MAX_MODULE,PID输出为
V
q
p
i
d
Vq_{pid}
Vqpid,
V
d
p
i
d
Vd_{pid}
Vdpid,经过Circle Limitation后的输出为
V
q
o
u
t
Vq_{out}
Vqout,
V
d
o
u
t
Vd_{out}
Vdout,则显然有:
V
q
p
i
d
V
q
o
u
t
=
V
q
p
i
d
2
+
V
d
p
i
d
2
M
A
X
_
M
O
D
U
L
E
2
\frac{Vq_{pid}}{Vq_{out}}=\sqrt{\frac{Vq_{pid}^2+Vd_{pid}^2}{MAX\_MODULE^2}}
VqoutVqpid=MAX_MODULE2Vqpid2+Vdpid2
V
d
p
i
d
V
d
o
u
t
=
V
q
p
i
d
2
+
V
d
p
i
d
2
M
A
X
_
M
O
D
U
L
E
2
\frac{Vd_{pid}}{Vd_{out}}=\sqrt{\frac{Vq_{pid}^2+Vd_{pid}^2}{MAX\_MODULE^2}}
VdoutVdpid=MAX_MODULE2Vqpid2+Vdpid2
这里取等式右边为 1 S c o f \frac1{S_{cof}} Scof1,于是上式可变形为
V q o u t = V q p i d ∗ S c o f Vq_{out}=Vq_{pid}*S_{cof} Vqout=Vqpid∗Scof
V d o u t = V d p i d ∗ S c o f Vd_{out}=Vd_{pid}*S_{cof} Vdout=Vdpid∗Scof
这里的系数 S c o f S_{cof} Scof计算是重点,由于涉及平方根求取,ST采用了查表法来计算。
S c o f = M A X _ M O D U L E 2 V q p i d 2 + V d p i d 2 S_{cof}=\sqrt{\frac{MAX\_MODULE^2}{Vq_{pid}^2+Vd_{pid}^2}} Scof=Vqpid2+Vdpid2MAX_MODULE2
因为 V q p i d Vq_{pid} Vqpid 和 V d p i d Vd_{pid} Vdpid的输出范围是已知的,则 S c o f S_{cof} Scof的范围也是可以确定的,那么是否可以提前将 S c o f S_{cof} Scof划分,然后根据 V q p i d 2 + V d p i d 2 Vq_{pid}^2+Vd_{pid}^2 Vqpid2+Vdpid2来查表呢。
个人猜测ST源代码里提供了一种巧妙的思路,先假定ST的单位矢量圆半径是32768,即当Vq,Vd的合成矢量满足满调制比时,合成矢量的大小为32768,由此可得出从PID环节输出来的Vq_pid和Vd_pid能够合成的电压矢量范围为0— V q p i d 2 + V d p i d 2 = 2 ∗ 3276 8 2 \sqrt{{Vq_{pid}^2+Vd_{pid}^2}}=\sqrt{2*32768^2} Vqpid2+Vdpid2=2∗327682,注意,这个范围远远超出了电压调制范围,因此需要在内部加一个限制,以此为基础有:
- 将0— 2 ∗ 3276 8 2 {2*32768^2} 2∗327682划分成128等分;
- 设定最大调制比为0.98,则得出满足调制的最大电压矢量 M A X _ M O D U L E MAX\_MODULE MAX_MODULE(约为32111),当 V q p i d Vq_{pid} Vqpid, V d p i d Vd_{pid} Vdpid达到可以合成的最大电压矢量时,即满足 V q p i d 2 + V d p i d 2 = M A X _ M O D U L E 2 Vq_{pid}^2+Vd_{pid}^2=MAX\_MODULE^2 Vqpid2+Vdpid2=MAX_MODULE2,此时在128等分中为第61个,即这128等分的前61个电压矢量是可以被利用的。
- 因为只有当合成矢量大于限制圆时,才需要限制,即处于128等分的后67等分里才需要处理,所以只需要对后67个等分对应的S_cof列表即可。
- ST代码中先计算PID环节出来后电压矢量所处的等分点区间,然后减去限制圆内的等分点个数,得到在67个等分点范围内的节点号,再去查表得到 S _ c o f S\_cof S_cof,然后重新计算 V q o u t Vq_{out} Vqout, V d o u t Vd_{out} Vdout;
void RevPark_Circle_Limitation(Volt_Components Stat_Volt_q_d)
{
s32 temp;
temp = Stat_Volt_q_d.qV_Component1 * Stat_Volt_q_d.qV_Component1
+ Stat_Volt_q_d.qV_Component2 * Stat_Volt_q_d.qV_Component2;
// min value 0, max value 2*32767^2
if( temp > (u32)(( MAX_MODULE * MAX_MODULE) ) ) // (Vd^2+Vq^2) > MAX_MODULE^2
{
u16 index;
temp /= (u32)(512*32768);
//temp = temp * 128 / (2 * 32768^2)算出所处的等分节点
temp -= START_INDEX ; // min value 0, max value 127 - START_INDEX
//只需要用到超出限制圆的节点坐标值(剩下的67个点),做这一步方便索引
index = circle_limit_table[(u8)temp];
//取值
temp = (s16)Stat_Volt_q_d.qV_Component1 * (u16)(index);
//对应上面的公式,但需要注意的是,按道理sqrt之后的值是一个0-1的小数,
//因此这里索引值放大了32768,这也是为什么后面要除以32768的原因。
Stat_Volt_q_d.qV_Component1 = (s16)(temp/32768);
temp = (s16)Stat_Volt_q_d.qV_Component2 * (u16)(index);
Stat_Volt_q_d.qV_Component2 = (s16)(temp/32768);
}
}