目录
很多人可能实现过有感foc后,看到这个系列是关于无感FOC滑模,就直接跳到了这个系列,准备开始认真学习。在这里我想先泼一下冷水,无感很难,无法一蹴而就,如果没有之前几个系列的理论基础,你就会迷失在各种没听过的概念之间,最终浑浑噩噩地对着敲一遍代码,依然不知道其中原理。
本系列文章需要具备前文基础: 永磁同步电机无感FOC思路建立。该系列文章讲述了无感观测器的思路产生。无感FOC理论推导难度较大,需要做好基础准备。
无感FOC的反电动势观测方法有很多种,本系列讲述其中最常用的一种:滑模观测器。
推导
按照这个思路去推导:只要估计电流和采样电流接近了,就说明估计反电动势和真实反电动势接近了。所以推导的目标是建立估计电流偏差方程。(可能会有人问:为啥不是建立估计反电动势偏差方程?因为真实反电动势只有上帝知道,而真实电流可以采样得到。)
偏差方程
把永磁同步电机数学模型中的电压方程放这里。为了书写简单,只写 α \alpha α轴, β \beta β轴的推导过程同理。
u α = R s i α + L s d i α d t + e α u_\alpha = R_s i_\alpha + L_s \frac{di_\alpha}{dt} + e_\alpha uα=Rsiα+Lsdtdiα+eα
其中 e α = − ω ψ f sin θ e_\alpha=-\omega\psi_f\sin\theta eα=−ωψfsinθ,是反电动势。
把电流的导数移到方程左边(电流导数噪音大,避免直接计算导数):
d i α d t = 1 L s ( u α − R s i α − e α ) \frac{di_\alpha}{dt} = \frac{1}{L_s}(u_\alpha - R_s i_\alpha - e_\alpha) dtdiα=Ls1(uα−Rsiα−eα)
这里反电动势 e α e_\alpha eα是不知道的,我们只能估计出来,这里先新建一个符号 z α z_\alpha zα用于表示估计反电动势。由于代入了估计反电动势,因此电流也不是真实电流,变为了估计电流,加个帽子表示估计电流 i α ^ \hat{i_\alpha} iα^。于是代入估计值后的方程变为了:
d i α ^ d t = 1 L s ( u α − R s i α ^ − z α ) \frac{d\hat{i_\alpha}}{dt} = \frac{1}{L_s}(u_\alpha - R_s \hat{i_\alpha} - z_\alpha) dtdiα^=Ls1(uα−Rsiα^−zα)
此时可以自然而然想到,如果采样到的电流 i α i_\alpha iα和算出来的估计电流 i α ^ \hat{i_\alpha} iα^有偏差,那我就修改估计反电动势 z α z_\alpha zα,使得估计的电流不断逼近采样到的电流,当算出来的估计电流接近采样到的电流时(偏差接近0),就说明估计反电动势接近真实反电动势了,也就说明得到反电动势的值了。这是很关键的一个灵感指引 ,但是滑模观测器的精髓并不仅于此,而是在于简单粗暴地修改 z α z_\alpha zα。
先把偏差方程写出来,即两个方程相减一下, i ~ α \tilde{i}\alpha i~α表示偏差值。
d i α d t − d i α ^ d t = d i ~ α d t = − R s L s i ~ α + 1 L s ( z α − e α ) \begin{aligned}\frac{di\alpha}{dt}-\frac{d\hat{i_\alpha}}{dt}&=\\\frac{d\tilde{i}\alpha}{dt} &= -\frac{R_s}{L_s}\tilde{i}\alpha + \frac{1}{L_s}(z_\alpha-e_\alpha)\end{aligned} dtdiα−dtdiα^dtdi~α==−LsRsi~α+Ls1(zα−eα)
观察偏差方程,怎么调节 z α z_\alpha zα才能让偏差值 i ~ α \tilde{i}\alpha i~α不断接近0呢?可以想到, i ~ α > 0 \tilde{i}\alpha>0 i~α>0时,如果能保证 d i ~ α d t < 0 \frac{d\tilde{i}\alpha}{dt}<0 dtdi~α<0 就太好了,因为**如果此时导数小于零, i ~ α \tilde{i}\alpha i~α的趋势就是从正数趋向负数** 。同理 i ~ α < 0 \tilde{i}\alpha<0 i~α<0时,如果能保证 d i ~ α d t > 0 \frac{d\tilde{i}\alpha}{dt}>0 dtdi~α>0, i ~ α \tilde{i}\alpha i~α的趋势就是从负数趋向正数。如果能够做到这两点,那么**偏差值 i ~ α \tilde{i}\alpha i~α就会很形象地"不断滑动到0"** 。
怎么调节 z α z_\alpha zα才能做到这两点?i ~ α < 0 \tilde{i}\alpha<0 i~α<0时,如果让 z α > e α z\alpha>e_\alpha zα>eα,就可以保证 d i ~ α d t > 0 \frac{d\tilde{i}_\alpha}{dt}>0 dtdi~α>0 ,反之同理。此时一个简单的想法就是,直接让 z α z_\alpha zα等于一个大于 e α e_\alpha eα的数就可以了,这就是经典滑模控制的思想。滑模控制和pid控制不一样,不会随着误差越大,就输出越大,它很简单粗暴,当 i ~ α < 0 \tilde{i}\alpha<0 i~α<0时,就让 z α z\alpha zα等于一个足够大的数K,K一定要大于可能出现的 e α e_\alpha eα,保证 d i ~ α d t > 0 \frac{d\tilde{i}\alpha}{dt}>0 dtdi~α>0,就能让 i ~ α \tilde{i}\alpha i~α趋向0;同理,当 i ~ α > 0 \tilde{i}\alpha>0 i~α>0时,就让 z α z\alpha zα等于-K。即:
z α = − K ⋅ sign ( i ~ α ) z_\alpha = -K \cdot \text{sign}(\tilde{i}_\alpha) zα=−K⋅sign(i~α)
这样就可以保证 i ~ α \tilde{i}_\alpha i~α"不断滑动到0"。
以上两段话很重要 ,是滑模观测器的核心精髓,如果没有看懂,先暂停下来,反复看懂理解后再继续往下。
这里有几个问题:
- K应该设置为多少?
- i ~ α \tilde{i}_\alpha i~α怎么计算?
- z α z_\alpha zα是估计反电动势,是模拟量,怎么能设置为定值K?
K应该设置为多少?
K要大于可能出现的 e α e_\alpha eα,要能覆盖住。因为 e α = − ω ∗ ψ f sin θ e_\alpha=-\omega*\psi_f\sin\theta eα=−ω∗ψfsinθ,由此可知 e α e_\alpha eα最大值为 最高转速 ∗ ψ f 最高转速*\psi_f 最高转速∗ψf。或者外部拖动一下电机,实际测一下电机在最高转速下的反电动势峰值。
i ~ α \tilde{i}_\alpha i~α怎么计算?
偏差值 i ~ α = i ^ α − i α \tilde{i}\alpha = \hat{i}\alpha - i_\alpha i~α=i^α−iα。
其中 i α i_\alpha iα 是真实采样电流,是单片机通过 ADC 采样电机相电流后,经过 Clark 变换直接得到的,这是已知量。 i ^ α \hat{i}_\alpha i^α 是估计电流,是算出来的,现在要搞明白怎么算,这才是关注的点。
我们之前得到了下式,可以对这个式进行积分得到 i ^ α \hat{i}\alpha i^α,在编程上是离散累加。
d i α ^ d t = 1 L s ( u α − R s i α ^ − z α ) \begin{equation}\frac{d\hat{i\alpha}}{dt} = \frac{1}{L_s}(u_\alpha - R_s \hat{i_\alpha} - z_\alpha)\end{equation} dtdiα^=Ls1(uα−Rsiα^−zα)
对于上式的积分,很有讲究,以下的积分内容难度有点高,可以不用详细理解:
离散积分有很多种,最简单直观的一种如下:
离散积分方法一:前向欧拉
把上式离散化一下:
d i ^ α d t = 近似 Δ i ^ α Δ t = i ^ α 新 − i ^ α 旧 T s = 1 L s ( u α − R s i ^ α 旧 − z α ) ⏟ \frac{d\hat{i}\alpha}{dt} \overset{近似}{=} \frac{\Delta \hat{i}\alpha}{\Delta t} = \underbrace{\frac{\hat{i}\alpha^新 - \hat{i}\alpha^旧}{T_s}=\frac{1}{L_s}(u_\alpha - R_s \hat{i}\alpha^旧 - z\alpha)} dtdi^α=近似ΔtΔi^α= Tsi^α新−i^α旧=Ls1(uα−Rsi^α旧−zα)
其中 T s T_s Ts是单片机中计算这个积分的周期,可以认为定时器的周期。
通过上式就能得到 i ^ α \hat{i}\alpha i^α了:
i ^ α = i ^ α 新 = i ^ α 旧 + T s L s ( u α − R s i ^ α 旧 − z α ) \hat{i}\alpha=\hat{i}\alpha^新 = \hat{i}\alpha^旧 + \frac{T_s}{L_s} (u_\alpha - R_s \hat{i}\alpha^旧 - z\alpha) i^α=i^α新=i^α旧+LsTs(uα−Rsi^α旧−zα)
上式等号右边都是已知数。 i ^ α 旧 \hat{i}\alpha^旧 i^α旧是上一轮算出来的,初始值可以设为0; T s T_s Ts是单片机FOC计算周期(通常是ADC中断周期); L s L_s Ls是绕组电感; u α u\alpha uα是给定的经过PWM占空比换算比例后的 α \alpha α轴电压; R s R_s Rs是绕组电阻; z α = K ⋅ sign ( i ~ α ) z_\alpha = K \cdot \text{sign}(\tilde{i}_\alpha) zα=K⋅sign(i~α)。
这个积分方式很简答直观,这个叫做前向欧拉法。但是比较挑电机和单片机性能,把上式右边的上一轮 i ^ α \hat{i}\alpha i^α提取出来,可以看到:
i ^ α 新 = i ^ α 旧 ( 1 − T s R s L s ) + T s L s ( u α − z α ) \hat{i}\alpha^新 = \hat{i}\alpha^旧(1-\frac{T_sR_s}{L_s}) + \frac{T_s}{L_s} (u\alpha - z_\alpha) i^α新=i^α旧(1−LsTsRs)+LsTs(uα−zα)
在自动控制原理中,系数 ( 1 − T s R s L s ) (1-\frac{T_sR_s}{L_s}) (1−LsTsRs)要在0到1之间,否则 i ^ α \hat{i}_\alpha i^α会发散震荡(极点相关内容,可以不用深究)。也就是说要求 T s < 2 L s R s T_s<\frac{2L_s}{R_s} Ts<Rs2Ls,并且越小越好。对于大阻值电机来说,对 T s T_s Ts的要求就很高,即单片机计算一轮无感FOC的周期要求更短。
还有其他积分方法,对计算能力要求不高,而且更精确:
离散积分方法二:精确离散化
说白了式(1)就是一个微分方程,求解微分方程就完事了:
d i ^ α d t + R s L s i ^ α = 1 L s ( u α − z α ) \frac{d\hat{i}\alpha}{dt} + \frac{R_s}{L_s}\hat{i}\alpha = \frac{1}{L_s}(u_\alpha-z_\alpha) dtdi^α+LsRsi^α=Ls1(uα−zα)
看作一个微分方程 d i d t + a i = b \frac{di}{dt}+ai=b dtdi+ai=b,其解是:
i ( t ) = C e − a t + b a \begin{equation}i(t) = C e^{-at} + \frac{b}{a}\end{equation} i(t)=Ce−at+ab
因为 a = R s L s , b = 1 L s ( u α − z α ) a=\frac{R_s}{L_s},b=\frac{1}{L_s}(u_\alpha-z_\alpha) a=LsRs,b=Ls1(uα−zα),所以 b a = u α − z α R s \frac{b}{a} = \frac{u_\alpha-z_\alpha}{R_s} ab=Rsuα−zα。
带入 t = 0 t=0 t=0算一下 C C C, i ( 0 ) = C + b a i(0) = C + \frac{b}{a} i(0)=C+ab,于是 C = i ( 0 ) − b a C=i(0) - \frac{b}{a} C=i(0)−ab。
将当前时刻视为 k k k(对应 t = 0 t=0 t=0),下一轮FOC计算视为 k + 1 k+1 k+1(对应 t = T s t=T_s t=Ts),式(2)用离散形式写出来:
i α ^ [ k + 1 ] = i α ^ [ k ] e − R s T s L s + u α [ k ] − z α [ k ] R s ( 1 − e − R s T s L s ) \hat{i_\alpha}[k+1] = \hat{i_\alpha}[k] e^{-\frac{R_sT_s}{L_s}} + \frac{u_\alpha[k] - z_\alpha[k]}{R_s} \left( 1 - e^{-\frac{R_sT_s}{L_s}} \right) iα^[k+1]=iα^[k]e−LsRsTs+Rsuα[k]−zα[k](1−e−LsRsTs)
因为方法二是直接解的微分方程并离散化,所以准确性会高很多。
在代码编写上可以将常数 e − R s T s L s e^{-\frac{R_sT_s}{L_s}} e−LsRsTs和 1 R s ( 1 − e − R s T s L s ) \frac{1}{R_s} (1 - e^{-\frac{R_sT_s}{L_s}}) Rs1(1−e−LsRsTs)提前计算好,这样计算负担就和前向欧拉法一样了。
经过以上离散积分后,得到了 i ^ α \hat{i}\alpha i^α,于是 i ~ α \tilde{i}\alpha i~α就有了:
i ~ α = i α − i ^ α \tilde{i}\alpha=i\alpha-\hat{i}_\alpha i~α=iα−i^α
z α z_\alpha zα是估计反电动势,是模拟量,怎么能设置为定值K?
我们一开始把 z α z_\alpha zα定义为估计反电动势,但是随着推导,我们将其设置为了K或者-K,变成了开关量,而估计反电动势显然是一个模拟量,这出现了概念冲突。
在习惯上,通常会给估计值符号加个帽子,比如 i ^ α \hat{i}\alpha i^α。 z α z\alpha zα一开始不写成 e α ^ \hat{e_\alpha} eα^,就是因为它是推导过程中"临时"代表估计反电动势。
高频开关量怎么变成模拟量?其实在FOC中已经遇到过,我们给绕组输入高频PWM波,最终体现为绕组电压,这是因为绕组电感是天然的滤波器。高频开关量经过滤波器后就能变成模拟量,可以将 z α z_\alpha zα输入到软件低通滤波函数,输出值就是最终的估计反电动势 e α ^ \hat{e_\alpha} eα^。
sign函数优化
sign函数的表达式如下:
sign ( x ) = { 1 , x > 0 0 , x = 0 − 1 , x < 0 \text{sign}(x) = \begin{cases} 1, & x > 0 \\ 0, & x = 0 \\ -1, & x < 0 \end{cases} sign(x)=⎩ ⎨ ⎧1,0,−1,x>0x=0x<0
sign函数的跳动变化很大,工程上常用饱和函数(sat)或偏移后的sigmoid代替。
sat饱和函数:
sat ( x ) = { 1 , x > a x a , ∣ x ∣ ≤ a − 1 , x < − a \text{sat}(x) = \begin{cases} 1, & x > a \\ \frac{x}{a}, & |x| \le a \\ -1, & x < -a \end{cases} sat(x)=⎩ ⎨ ⎧1,ax,−1,x>a∣x∣≤ax<−a
其中a越小,越接近sign函数。
偏移后的sigmoid函数:
s c a l e d _ s i g m o i d ( x ) = 2 1 + e − x − 1 scaled\_sigmoid(x) = \frac{2}{1 + e^{-x}}-1 scaled_sigmoid(x)=1+e−x2−1
用于计算量优化的线性近似sigmoid:
a p p r o x _ s i g m o i d = x 1 + ∣ x ∣ approx\_sigmoid = \frac{x}{1 + |x|} approx_sigmoid=1+∣x∣x
将函数同时画出来,可以看到sat或者sigmoid在轻微偏差的时候不会产生很大的反应:

过程总结
目前为止,我们得到了比较接近真实反电动势的估计反电动势,转子估计角度就呼之欲出了。来总结一下过程,设置 i ^ α \hat{i}\alpha i^α初值为0, i α i\alpha iα是ADC采样得到的。
1.计算 i ~ α = i α − i ^ α \tilde{i}\alpha = i\alpha-\hat{i}_\alpha i~α=iα−i^α
2.计算 z α = − K ⋅ sat ( i ~ α ) z_\alpha = -K \cdot \text{sat}(\tilde{i}_\alpha) zα=−K⋅sat(i~α)
3.计算 i ^ α = i ^ α 旧 + T s L s ( u α − R s i ^ α 旧 − z α ) \hat{i}\alpha = \hat{i}\alpha^旧 + \frac{T_s}{L_s} (u_\alpha - R_s \hat{i}\alpha^旧 - z\alpha) i^α=i^α旧+LsTs(uα−Rsi^α旧−zα)或者精确离散化(后文代码实践中将使用精确离散化)
4.将 z α z_\alpha zα输入低通滤波得到并更新 e α ^ \hat{e_\alpha} eα^
循环以上步骤。
本节为了书写简洁,只以 α \alpha α轴推导为例, β \beta β轴同理。
可以看到我们推导了一大堆,成果结晶就是以上几个式子,虽然推导过程复杂,但是最终拿来使用的式子还是简单的。