本文章更多的是,阅读别人的文章,再加上自己的理解和实践凑起来的


什么是FOC?


FOC(Field-Oriented Control),直译是磁场定向控制,也被称作矢量控制 (VC,Vector Control) ,是目前无刷直流电机(BLDC)和永磁同步电机(PMSM)高效控制的最优方法之一。FOC旨在通过精确地控制磁场大小与方向,使得电机的运动转矩平稳、噪声小、效率高,并且具有高速的动态响应。

简单来说就是,FOC是一种对无刷电机的驱动控制方法,它可以让我们对无刷电机进行 “像素级” 控制,实现很多传统电机控制方法所无法达到的效果。

因为所谓的“矢量控制”其实就是在做 解耦 ,把相互耦合的三相磁链解耦为容易控制的交轴 I q I_q Iq 和直轴 I d I_d Id 。整个过程就好比我们在做信号处理的时候,通过FFT把信号变换到频域进行处理之后再IFFT反变换回时域是一个道理。

FOC驱动器和无刷电调的区别


玩过航模的同学可能对无刷电机很熟悉,也应该知道航模中对于无刷电机的驱动使用的是 电子调速器(ESC) 也就是我们常说的电调,那么这个FOC驱动器和普通的电调有什么区别呢?


FOC的优势:

  1. 低转速下控制
    由于控制原理的区别,无刷电调只能控制电机工作在高转速下,低速下无法控制;而FOC控制器则完全没有这个限制,不论在什么转速下都可以实现精确控制。
  2. 电机换向
    同上面的理由,由于电调无法反馈转子位置,因此很难实现电机正反转的换向(当然有感电调可以实现);而FOC驱动器的换向性能极其优秀,最高转速下正反转切换可以非常顺畅;此外FOC还可以以能量回收的形式进行刹车控制。
  3. 力矩控制
    普通电调都只能控制电机转速,而FOC可以进行电流(力矩)、速度、位置三个闭环控制。
  4. 噪音
    FOC驱动器的噪音会比电调小很多,原因是普通电调采用方波驱动,而FOC是正弦波。

电调的优势:

  1. 兼容性
    电调驱动不同的BLDC不需要进行参数整定,而FOC需要。
  2. 算法复杂度
    电调的算法实现更简单,运算量少,很适合需要提高带宽的超高转速电机。
  3. 成本
    电调的成本比FOC低很多。

综上大家应该可以看出来,FOC驱动器在控制性能上是要比电调强大得多的,其优异的性能和 磁场定向控制 的原理是密不可分的。


电机原理概述


基本物理知识准备


左手定则

百度百科

左手定则常用于判断通电导体在磁场中受力方向,由英国电机学工程师弗莱明提出。

在这里插入图片描述

导体受力 F ( N ) F(N) F(N)
F = I L B \LARGE F=ILB F=ILB
式中, B B B 为磁通量密度 ( W b / m 2 ) (Wb/m^2) (Wb/m2) I I I 为电流 ( A ) (A) (A) L L L 为处于磁场中的导体的长度 ( m ) (m) (m)


弗莱明右手定则 (又称发电机定则)
  • 如右圖所示,右手三根手指互相垂直,大拇指的方向是 a / x / I \mathbf{a}/\mathbf{x}/\mathbf{I} a/x/I 的方向、食指的方向是 b / y / B \mathbf{b}/\mathbf{y}/\mathbf{B} b/y/B 的方向、中指的方向則為 c / z / F \mathbf{c}/\mathbf{z}/\mathbf{F} c/z/F 的方向。

在这里插入图片描述

右手定則可以用來找到力矩的方向。将右手掌张开,将四根手指从参考点朝着作用力的位置 r r r 指去,然后将大拇指伸开垂直于四根手指,再找到这四根手指与作用力 F F F 之间角度最小的夹角,将这四根手指弯扫过这夹角,则力矩矢量的方向是大拇指所指的方向。

  1. 拇指的方向是导体移动方向

  2. 食指的是磁场方向

  3. 中指的则为生成的电流方向

维基百科:中国教科书中的右手定则实为弗莱明右手定则的变体,而将这个定则叫做“右手螺旋定则”。

这个其实就是上面的 “左手定则” ,在国外可能是用“右手”表示。


右手定则

伸开右手,使大拇指跟其余四个手指垂直并且都跟手掌在一个平面内,把右手放入磁场中,让磁感线垂直穿入手心,大拇指指向导体运动方向,则其余四指指向感生电动势的方向。也就是切割磁感线的导体会产生反电动势,实际上通过反电动势定位转子位置也是普通无感电调工作的基础原理之一

在这里插入图片描述



右手螺旋定则 (又称安培定则)

百度百科

右手定则可以用于安培定律的两种互补应用方法:

  1. 螺线管载有的电流,会产生磁场。使用右手定则,可以判断磁场方向。将右手握住螺线管,四根手指朝着电流方向指去,然后将大拇指沿着螺线管的中心轴伸直,则磁场的方向即为大拇指所指的方向。
    在这里插入图片描述

  2. 右手定则也可以用来辨明一条电线四周磁场的方向。对于这用法,右手定则称为“安培右手定则”,或“安培定则”。如右图所示,假若将右手的大拇指朝着电线的电流方向指去,再将其它四根手指握紧电线,则四根手指弯曲的方向为磁场的方向。
    在这里插入图片描述


有刷、无刷电机

直流有刷电机简介

直流有刷电机通过换向器来改变电流方向,进而改变绕组的受力方向。由于其是机械换向,因此就带来一系列缺点,例如摩擦大,发热大,效率低等缺点

直流无刷电机简介

在这里插入图片描述

直流无刷电机通过使用电子器件代替机械换向,解决了直流有刷电机的缺点。为了便于分析我们将直流无刷电机抽象出上图模式,定子由三个线圈组成,转子由一对磁极组成。通过改变ABC三者电流方向来改变定子产生的磁场方向,从而使磁铁转动起来。

在这里插入图片描述



FOC控制原理

有感FOC步骤框图:

在这里插入图片描述

概括一下,FOC控制的整个过程是这样的:

  1. 对电机三相电流进行采样得到 I a , I b , I c I_{a}, I_{b}, I_{c} Ia,Ib,Ic
  2. I a , I b , I c I_{a}, I_{b}, I_{c} Ia,Ib,Ic 经过Clark变换得到 I α , I β I_{\alpha}, I_{\beta} Iα,Iβ
  3. I α , I β I_{\alpha}, I_{\beta} Iα,Iβ 经过Park变换得到 I q , I d I_{q}, I_{d} Iq,Id
  4. 计算 I q , I d I_{q}, I_{d} Iq,Id 和其设定值 I q − r e f , I d − r e f I_{q_{-}} r e f, I_{d_{-}} r e f Iqref,Idref 的误差
  5. 将上述误差输入两个PID(只用到PI)控制器,得到输出的控制电压 U q , U d U_q,U_d Uq,Ud
  6. U q , U d U_q,U_d Uq,Ud 进行反Park变换得到 U α , U β U_{\alpha}, U_{\beta} Uα,Uβ
  7. U α , U β U_{\alpha}, U_{\beta} Uα,Uβ 合成电压空间矢量,输入SVPWM模块进行调制,输出该时刻三个半桥的状态编码值(前文有提到)
  8. 按照前面输出的编码值控制三相逆变器的 MOS 管开关,驱动电机
  9. 循环上述步骤



变换


Clarke变换

clark变换:将 a b c \large abc abc 变换到 静止 α β \large \alpha \beta αβ 坐标系下。

在这里插入图片描述

在这里插入图片描述

三相对称正弦电流的大小可以这样表示:

{ I a = I m cos ⁡ ( ω t ) I b = I m cos ⁡ ( ω t − 2 π 3 ) I c = I m cos ⁡ ( ω t + 2 π 3 ) (2-1) \large \left\{\begin{matrix} I_a =& I_m \cos( \omega t) \tag{2-1}\\ I_b =& I_m \cos( \omega t - \frac{2\pi}{3}) \\ I_c =& I_m \cos( \omega t + \frac{2\pi}{3}) \\ \end{matrix}\right. Ia=Ib=Ic=Imcos(ωt)Imcos(ωt32π)Imcos(ωt+32π)(2-1)

其中, I m \large I_m Im 标识赋值; ω = 2 π f \large \omega = 2\pi f ω=2πf 标识角速度,三项电流在空间上互差120° 。

三相电流的矢量表达和合成矢量可以这样表达:
{ I a → = I a ⋅ e 0 I b → = I b ⋅ e − j 2 π 3 I c → = I c ⋅ e j 2 π 3 I s → = I a → + I b → + I c → \large \begin{align} \left\{\begin{matrix} \overrightarrow{I_a} =& I_a \cdot e^0 \\ \overrightarrow{I_b} =& I_b \cdot e^{-j \frac{2\pi}{3}} \\ \overrightarrow{I_c} =& I_c \cdot e^{j \frac{2\pi}{3}} \\ \tag{2-2} \end{matrix}\right. \end{align} \\\\ \large \begin{align} \overrightarrow{I_s} = \overrightarrow{I_a} + \overrightarrow{I_b} + \overrightarrow{I_c} \tag{2-3} \end{align} Ia =Ib =Ic =Iae0Ibej32πIcej32π(2-2)Is =Ia +Ib +Ic (2-3)

所以 I s → \large \overrightarrow{I_s} Is 就等于
I s → = I m cos ⁡ ( ω t ) + I m cos ⁡ ( ω t − 2 π 3 ) ⋅ e − j 2 π 3 + I m cos ⁡ ( ω t + 2 π 3 ) ⋅ e j 2 π 3 (2-4) \large \overrightarrow{I_s} = I_m \cos( \omega t) + I_m \cos( \omega t - \frac{2\pi}{3}) \cdot e^{-j \frac{2\pi}{3}} + I_m \cos( \omega t + \frac{2\pi}{3}) \cdot e^{j \frac{2\pi}{3}} \tag{2-4} Is =Imcos(ωt)+Imcos(ωt32π)ej32π+Imcos(ωt+32π)ej32π(2-4)
根据 欧拉公式 e j x = cos ⁡ x + j sin ⁡ x \large e^{jx} = \cos x+j\sin x ejx=cosx+jsinx ,可以推出:
I s → = I m cos ⁡ ( ω t ) + I m cos ⁡ ( ω t − 2 π 3 ) ( cos ⁡ ( 2 π 3 ) + j sin ⁡ ( 2 π 3 ) ) + I m cos ⁡ ( ω t + 2 π 3 ) ( cos ⁡ ( 2 π 3 ) − j sin ⁡ ( 2 π 3 ) ) (2-5) \large \begin{array}{rc} \overrightarrow{I_{s}}=\quad & I_{m} \cos (\omega t)+\\ & I_{m} \cos \left(\omega t-\frac{2 \pi}{3}\right)\left(\cos \left(\frac{2 \pi}{3}\right)+j \sin \left(\frac{2 \pi}{3}\right)\right)+\\ & I_{m} \cos \left(\omega t+\frac{2 \pi}{3}\right)\left(\cos \left(\frac{2 \pi}{3}\right)-j \sin \left(\frac{2 \pi}{3}\right)\right) \tag{2-5} \end{array} Is =Imcos(ωt)+Imcos(ωt32π)(cos(32π)+jsin(32π))+Imcos(ωt+32π)(cos(32π)jsin(32π))(2-5)
进一步化简可得:
I s → = I m cos ⁡ ( ω t ) + I m [ cos ⁡ ( ω t ) cos ⁡ ( 2 π 3 ) + sin ⁡ ( ω t ) sin ⁡ ( 2 π 3 ) ] ( − 1 2 + j 3 2 ) + I m [ cos ⁡ ( ω t ) cos ⁡ ( 2 π 3 ) − sin ⁡ ( ω t ) sin ⁡ ( 2 π 3 ) ] ( − 1 2 − j 3 2 ) (2-6) \large \begin{array}{rc} \overrightarrow{I_{s}}= & I_{m} \cos (\omega t)+ \\ & I_{m}\left[\cos (\omega t) \cos \left(\frac{2 \pi}{3}\right)+\sin (\omega t) \sin \left(\frac{2 \pi}{3}\right)\right]\left(-\frac{1}{2}+j \frac{\sqrt{3}}{2}\right)+ \\ & I_{m}\left[\cos (\omega t) \cos \left(\frac{2 \pi}{3}\right)-\sin (\omega t) \sin \left(\frac{2 \pi}{3}\right)\right]\left(-\frac{1}{2}-j \frac{\sqrt{3}}{2}\right) \tag{2-6} \end{array} Is =Imcos(ωt)+Im[cos(ωt)cos(32π)+sin(ωt)sin(32π)](21+j23 )+Im[cos(ωt)cos(32π)sin(ωt)sin(32π)](21j23 )(2-6)
代入三角函数值可得:
I s → = I m cos ⁡ ( ω t ) + I m [ − 1 2 cos ⁡ ( ω t ) + 3 2 sin ⁡ ( ω t ) ] ( − 1 2 + j 3 2 ) + I m [ − 1 2 cos ⁡ ( ω t ) − 3 2 sin ⁡ ( ω t ) ] ( − 1 2 − j 3 2 ) (2-7) \large \begin{array}{rc} \overrightarrow{I_{s}}= & I_{m} \cos (\omega t)+ \\ & I_{m}\left[-\frac{1}{2} \cos (\omega t)+\frac{\sqrt{3}}{2} \sin (\omega t)\right]\left(-\frac{1}{2}+j \frac{\sqrt{3}}{2}\right)+ \\ & I_{m}\left[-\frac{1}{2} \cos (\omega t)-\frac{\sqrt{3}}{2} \sin (\omega t)\right]\left(-\frac{1}{2}-j \frac{\sqrt{3}}{2}\right) \tag{2-7} \end{array} Is =Imcos(ωt)+Im[21cos(ωt)+23 sin(ωt)](21+j23 )+Im[21cos(ωt)23 sin(ωt)](21j23 )(2-7)
最后化简得到:
I s → = 3 2 I m cos ⁡ ( ω t ) + j 3 2 I m sin ⁡ ( ω t ) (2-8) \large \overrightarrow{I_s} = \frac{3}{2}I_m\cos(\omega t ) + j\frac{3}{2}I_m \sin(\omega t) \tag{2-8} Is =23Imcos(ωt)+j23Imsin(ωt)(2-8)
既:
I s → = 3 2 I m e − j ω t (2-9) \large \overrightarrow{I_s} = \frac{3}{2}I_m e^{-j \omega t} \tag{2-9} Is =23Imet(2-9)
可以看出,三相对称正弦电流的合成矢量的一个角速度为 ω \large \omega ω ,绕中心点旋转的矢量,因此能形成旋转磁场。它的幅值为单相幅值的 3 2 \large \frac{3}{2} 23 倍。

在这里插入图片描述


进一步,我们将 a b c abc abc 变换到 静止 α − β \large \alpha - \beta αβ 坐标系下,我们可以得到

在这里插入图片描述

{ I α = I a − I b cos ⁡ π 3 − I c cos ⁡ π 3 I β = I b cos ⁡ π 6 − I c cos ⁡ π 6 (2-10) \large \left\{\begin{array}{rc} I_{\alpha}= & I_{a}-I_{b} \cos \frac{\pi}{3}-I_{c} \cos \frac{\pi}{3} \\ I_{\beta} = & I_{b} \cos \frac{\pi}{6}-I_{c} \cos \frac{\pi}{6} \tag{2-10} \end{array}\right. {Iα=Iβ=IaIbcos3πIccos3πIbcos6πIccos6π(2-10)

将上式写为矩阵形式:
[ I α I β ] = k [ 1 − 1 2 − 1 2 0 3 2 − 3 2 ] [ I a I b I c ] (2-11) \large \begin{bmatrix} I_{\alpha }\\ I_{\beta } \end{bmatrix} =k\begin{bmatrix} 1 &-\frac{1}{2} &-\frac{1}{2} \\ 0&\frac{\sqrt{3}}{2} &-\frac{\sqrt{3}}{2} \end{bmatrix} \begin{bmatrix} I_{a}\\ I_{b}\\ I_{c} \tag{2-11} \end{bmatrix} [IαIβ]=k[102123 2123 ] IaIbIc (2-11)

  • k = 2 3 \large k=\sqrt\frac{2}{3} k=32 ,变换前后,功率不变。又称为: Concordia变换

  • k = 2 3 \large k=\frac{2}{3} k=32 ,变换前后,幅值不变,(既合成矢量的大小和方向相等)。

⭐️根据基尔霍夫电流定律 I a + I b + I c = 0 \large I_a + I_b + I_c = 0 Ia+Ib+Ic=0 ,然后为了保证幅值不变 k = 2 3 \large k=\frac{2}{3} k=32 带入,上述式子继续化简,最后可以得到
{ I α = k I a − 1 2 k I b − 1 2 k I c = 3 2 k I a I β = 3 2 k I b − 3 2 k I c = 3 2 I a + 3 I b (2-12) \large \left\{\begin{matrix} I_{\alpha } &=& kI_a - \frac{1}{2}kI_b - \frac{1}{2}kI_c &=& \frac{3}{2}kI_a \\ I_{\beta } &=& \frac{\sqrt{3}}{2}kI_b - \frac{\sqrt{3}}{2}kI_c &=& \frac{\sqrt{3}}{2}I_a + \sqrt{3}I_b \tag{2-12} \end{matrix}\right. {IαIβ==kIa21kIb21kIc23 kIb23 kIc==23kIa23 Ia+3 Ib(2-12)

k = 2 3 \large k=\frac{2}{3} k=32 带入

{ I α = 2 3 I a − 1 3 I b − 1 3 I c = I a I β = 1 3 I b − 1 3 I c = 1 3 I a + 2 3 I b (2-13) \large \left\{\begin{matrix} I_{\alpha } &=& \frac{2}{3}I_a - \frac{1}{3}I_b - \frac{1}{3}I_c &=& I_a \\ I_{\beta } &=& \frac{1}{\sqrt{3}}I_b - \frac{1}{\sqrt{3}}I_c &=& \frac{1}{\sqrt{3}}I_a + \frac{2}{\sqrt{3}}I_b \tag{2-13} \end{matrix}\right. {IαIβ==32Ia31Ib31Ic3 1Ib3 1Ic==Ia3 1Ia+3 2Ib(2-13)

上述式子(2-13)可以看到 I α = I a \large I_{\alpha } = I_a Iα=Ia 也就是 变换 前后 幅值不变

然后我们再来看看 功率不变 情况,也就是 k = 2 3 \large k=\sqrt\frac{2}{3} k=32 时:
{ I α = 2 3 I a − 1 6 I b − 1 6 I c I β = 1 2 I b − 1 2 I c (2-14) \large \left\{\begin{matrix} I_{\alpha } &=& \sqrt{\frac{2}{3}}I_a - \frac{1}{\sqrt{6}}I_b - \frac{1}{\sqrt{6}}I_c \\ I_{\beta } &=& \frac{1}{\sqrt{2}}I_b - \frac{1}{\sqrt{2}}I_c \tag{2-14} \end{matrix}\right. IαIβ==32 Ia6 1Ib6 1Ic2 1Ib2 1Ic(2-14)

假设变换前的功率为 P 0 = I a U a + I b U b + I c U c \large P_0 = I_aU_a +I_bU_b + I_cU_c P0=IaUa+IbUb+IcUc ,变换后的功率为 P 1 = I α U α + I β U β \large P_1 = I_{\alpha }U_{\alpha } + I_{\beta }U_{\beta } P1=IαUα+IβUβ ,那么有:

P 1 = I α U α + I β U β = 2 3 I a U a − 1 3 I a U b − 1 3 I a U c − 1 3 I b U a + 1 6 I b U b + 1 6 I b U c − 1 3 I c U a + 1 6 I c U b + 1 6 I c U c + 1 2 I b U b − 1 2 I b U c − 1 2 I c U b + 1 2 I c U c = 2 3 I a U a − 1 3 I a U b − 1 3 I a U c − 1 3 I b U a + 2 3 I b U b − 1 3 I b U c − 1 3 I c U a − 1 3 I c U b + 2 3 I c U c  因为  U a + U b + U c = 0 = ( 2 3 P 0 ) + ( 1 3 P 0 ) = P 0 (2-15) \large \begin{array}{l} P_{1} = \quad I_{\alpha} U_{\alpha}+I_{\beta} U_{\beta}\\ =\quad \frac{2}{3} I_{a} U a-\frac{1}{3} I_{a} U b-\frac{1}{3} I_{a} U c\\ \tag{2-15} -\frac{1}{3} I_{b} U a+\frac{1}{6} I_{b} U b+\frac{1}{6} I_{b} U c\\ -\frac{1}{3} I_{c} U a+\frac{1}{6} I_{c} U b+\frac{1}{6} I_{c} U c\\ +\frac{1}{2} I_{b} U_{b}-\frac{1}{2} I_{b} U_{c}-\frac{1}{2} I_{c} U_{b}+\frac{1}{2} I_{c} U_{c}\\ =\quad \frac{2}{3} I_{a} U a-\frac{1}{3} I_{a} U b-\frac{1}{3} I_{a} U c\\ -\frac{1}{3} I_{b} U a+\frac{2}{3} I_{b} U b-\frac{1}{3} I_{b} U c\\ -\frac{1}{3} I_{c} U a-\frac{1}{3} I_{c} U b+\frac{2}{3} I_{c} U c\\ \text { 因为 } U_{a}+U_{b}+U_{c}=0\\ =\quad\left(\frac{2}{3} P_{0}\right)+\left(\frac{1}{3} P_{0}\right)=P_{0} \end{array} P1=IαUα+IβUβ=32IaUa31IaUb31IaUc31IbUa+61IbUb+61IbUc31IcUa+61IcUb+61IcUc+21IbUb21IbUc21IcUb+21IcUc=32IaUa31IaUb31IaUc31IbUa+32IbUb31IbUc31IcUa31IcUb+32IcUc 因为 Ua+Ub+Uc=0=(32P0)+(31P0)=P0(2-15)

上述式子(2-15)可以看到 P 0 = P 1 \large P_0 = P_1 P0=P1 也就是 变换 前后 功率不变

或者也可以通过下面这种方式算出 功率不变 情况:

根据式子(2-12), I α = 3 2 k I a \large I_{\alpha } =\frac{3}{2}kI_a Iα=23kIa
P 0 = U m × I m × 3 P 1 = 3 2 k U m × 3 2 k I m × 2 (2-16) \large \begin{array}{rlc} P_{0} & = U_{m} \times I_{m} \times 3 \\ P_{1} & =\frac{3}{2} k U_{m} \times \frac{3}{2} k I_{m} \times 2 \tag{2-16} \end{array} P0P1=Um×Im×3=23kUm×23kIm×2(2-16)
k = 2 3 \large k=\sqrt\frac{2}{3} k=32 时, P 0 = P 1 \large P_0 = P_1 P0=P1 ,也就是功率不变

在这里插入图片描述

关于恒功率变换和恒幅值变换可以参考:交流电机Clark变换中的功率不变约束与幅值不变约束_SmartFish.liu的博客-CSDN博客_clark变换的幅值不变和功率不变


Park变换

这一步中我们接着Clark变换 α − β \large \alpha - \beta αβ 坐标系旋转 θ 度,其中 θ 是转子当前的角度,如下图:

在这里插入图片描述

变换公式如下:
{ I d = I α cos ⁡ ( θ ) + I β sin ⁡ ( θ ) I q = − I α sin ⁡ ( θ ) + I β cos ⁡ ( θ ) (3-1) \large \left\{\begin{array}{l} I_{d}=I_{\alpha} \cos (\theta)+I_{\beta} \sin (\theta) \\ \tag{3-1} I_{q}=-I_{\alpha} \sin (\theta)+I_{\beta} \cos (\theta) \end{array}\right. {Id=Iαcos(θ)+Iβsin(θ)Iq=Iαsin(θ)+Iβcos(θ)(3-1)
⭐️也很简单,就是作用了一个旋转矩阵 ,写成矩阵形式:
[ I d I q ] = [ cos ⁡ θ sin ⁡ θ − sin ⁡ θ cos ⁡ θ ] [ I α I β ] (3-2) \large \left[\begin{array}{c} I_{d} \\ I_{q} \end{array}\right]=\left[\begin{array}{cc} \tag{3-2} \cos \theta & \sin \theta \\ -\sin \theta & \cos \theta \end{array}\right]\left[\begin{array}{c} I_{\alpha} \\ I_{\beta} \end{array}\right] [IdIq]=[cosθsinθsinθcosθ][IαIβ](3-2)
也就是说,这个 d − q d-q dq 坐标系是始终跟着转子旋转的!

  • d d d 轴方向与转子磁链方向重合,又叫直轴
  • q q q 轴方向与转子磁链方向垂直,又叫交轴

在这里插入图片描述

这个操作是可行的,因为我们会通过编码器输入转子的实时旋转角度,所以这个角度始终是一个已知数。经过这一步的变换,我们会发现,一个匀速旋转向量在这个坐标系下变成了一个定值!(显然的嘛,因为参考系相对于该向量静止了),这个坐标系下两个控制变量都被线性化了!

在这里插入图片描述

接下来如果我们以 I q , I d I_q, I_d Iq,Id 这两个值作为反馈控制的对象,那么显然就可以使用一些线性控制器来进行控制了,比如PID(是的,尽管学术界有很多炫酷的高级控制方法, 但是工业界还是偏爱PID)。

至此我们已经理解完上面FOC控制过程9个步骤的前3步了。


Clarke Park 变换测试

上位机用的是 “VOFA+”

模拟三相电流(红色绿色蓝色

在这里插入图片描述

经过 Clarke变换 的波形(紫色橙色

在这里插入图片描述

经过 Park 变换 的波形(粉色黄色

在这里插入图片描述


说明

特别说明一下其中的 I q , I d , I q _ r e f , I d _ r e f \LARGE I_q,I_d, I_{q\_ref}, I_{d\_ref} Iq,Id,Iq_ref,Id_ref ,前两者大家知道是通过Clark变换Park变换得到的,而后两者是我们预期希望前两者达到的值,这个值具体代表了什么物理量呢?参考一下下图:

在这里插入图片描述

也就是说我们一通操作将转子磁链进行了解耦,分解为了转子旋转的径向切向这两个方向的变量:

  • 其中 I q \LARGE I_q Iq 是我们需要的,代表了期望的力矩输出
  • I d \LARGE I_d Id 是我们不需要的,一般我们希望尽可能把它控制为0

在这里插入图片描述

FOC的控制目标通过PID控制器使用上述输入(电流采样值、编码器位置)和输出(MOS管开关状态)完成对电机电流的闭环控制。

代码

clark

/*-----------------------------------------------------------------------------
    CLARKE 变换 宏
-----------------------------------------------------------------------------*/
#define CLARKE_DEFAULTS \
    { 0, 0, 0, 0, 0 }

#define CLARK_ONEbySQRT3 0.57735026918963f /* 1/sqrt(3) */
#define CLARK_ONEbyTHREE 0.33333333333333f /* 1/3 */

/* 为1的话是虚假的三电流输入,本质上还是两电流,为0的话是不用电流相加为0这个公式来计算clark */
#define CLARK_3_current 1

/*-----------------------------------------------------------------------------
    CLARKE 变换 结构体
-----------------------------------------------------------------------------*/
typedef struct {
    fp32 As;     //!< Input: phase-a stator variable
    fp32 Bs;     //!< Input: phase-b stator variable
    fp32 Cs;     //!< Input: phase-c stator variable
    fp32 Alpha;  //!< Output: stationary d-axis stator variable
    fp32 Beta;   //!< Output: stationary q-axis stator variable
} clarke_t;

/*------------------------------------------------------------------------------
    CLARKE 变换 变量
------------------------------------------------------------------------------*/
static const fp32 _onebysqrt3 = (CLARK_ONEbySQRT3);
static const fp32 _onebythree = (CLARK_ONEbyTHREE);

/*------------------------------------------------------------------------------
    CLARKE 变换 函数实体
------------------------------------------------------------------------------*/
/**
 * @brief       clarke变换
 * @param[in]   *v: clarke_t结构体
 * @param[in]   _A: ABC坐标系下的电流a
 * @param[in]   _B: ABC坐标系下的电流b
 * @param[out]  v->Alpha: Alpha Beta坐标系下的电流Alpha
 *              v->Beta: Alpha Beta坐标系下的电流Beta
 * @retval      none
 * @attention   输入两电流
 */
static inline void clarke_calc_2(clarke_t* v, fp32 _A, fp32 _B) {
    v->As = _A;
    v->Bs = _B;

    v->Alpha = v->As;
    v->Beta = (v->As + (v->Bs * 2.0f)) * _onebysqrt3;
}

/**
 * @brief       clarke变换
 * @param[in]   *v: clarke_t结构体
 * @param[in]   _A: ABC坐标系下的电流a
 * @param[in]   _B: ABC坐标系下的电流b
 * @param[in]   _C: ABC坐标系下的电流c
 * @param[out]  v->Alpha: Alpha Beta坐标系下的电流Alpha
 *              v->Beta: Alpha Beta坐标系下的电流Beta
 * @retval      none
 * @attention   输入三电流
 */
static inline void clarke_calc_3(clarke_t* v, fp32 _A, fp32 _B, fp32 _C) {
    v->As = _A;
    v->Bs = _B;
    v->Cs = _C;

#if (CLARK_3_current == 1)
    v->Alpha = v->As;
    v->Beta = (v->Bs - v->Cs) * _onebysqrt3;
#elif (CLARK_3_current == 0)
    v->Alpha = (2 * v->As - v->Bs - v->Cs) * _onebythree;
    v->Beta = (v->Bs - v->Cs) * _onebysqrt3;
#endif
}

park

/*-----------------------------------------------------------------------------
    PARK 变换 宏
-----------------------------------------------------------------------------*/
#define PARK_DEFAULTS \
    { 0, 0, 0, 0, 0, 0, 0, }

/*-----------------------------------------------------------------------------
    PARK 变换 结构体
-----------------------------------------------------------------------------*/
typedef struct {
    fp32 Alpha;  //!< Input: stationary d-axis stator variable
    fp32 Beta;   //!< Input: stationary q-axis stator variable
    fp32 Angle;  //!< Input: rotating angle (pu)
    fp32 Ds;     //!< Output: rotating d-axis stator variable
    fp32 Qs;     //!< Output: rotating q-axis stator variable

    fp32 Sine;    //!< Input: Sine term
    fp32 Cosine;  //!< Input: Cosine term
} park_t;

/*------------------------------------------------------------------------------
    PARK 变换 函数实体
------------------------------------------------------------------------------*/
/**
 * @brief       park变换
 * @param[in]   *v: park_t结构体
 * @param[in]   _Alpha: Alpha Beta坐标系下的电流Alpha
 * @param[in]   _Beta: Alpha Beta坐标系下的电流Beta
 * @param[out]  v->Ds: dq坐标系下的电流d
 *              v->Qs: dq坐标系下的电流q
 * @retval      none
 */
static inline void park_calc(park_t* v, fp32 _Alpha, fp32 _Beta, fp32 _Angle) {
    fp32 cosTh, sinTh;

    v->Alpha = _Alpha;
    v->Beta = _Beta;
    v->Angle = _Angle;

    sinTh = falst_sin(v->Angle);
    cosTh = falst_cos(v->Angle);

    v->Ds = (v->Alpha * cosTh) + (v->Beta * sinTh);
    v->Qs = (v->Beta * cosTh) - (v->Alpha * sinTh);
}

ipark

/*-----------------------------------------------------------------------------
    IPARK 变换 宏
-----------------------------------------------------------------------------*/
#define IPARK_DEFAULTS \
    { 0, 0, 0, 0, 0, 0, 0, }

/*------------------------------------------------------------------------------
    IPARK 变换 结构体
------------------------------------------------------------------------------*/
typedef struct {
    fp32 Alpha;  //!< Output: stationary d-axis stator variable
    fp32 Beta;   //!< Output: stationary q-axis stator variable
    fp32 Angle;  //!< Input: rotating angle (pu)
    fp32 Ds;     //!< Input: rotating d-axis stator variable
    fp32 Qs;     //!< Input: rotating q-axis stator variable

    fp32 Sine;    //!< Input: Sine term
    fp32 Cosine;  //!< Input: Cosine term
} ipark_t;

/*------------------------------------------------------------------------------
    IPARK 变换 函数实体
------------------------------------------------------------------------------*/
/**
 * @brief       ipark变换
 * @param[in]   *v: ipark_t结构体
 * @param[in]   _Ds: dq坐标系下的电流d
 * @param[in]   _Qs: dq坐标系下的电流q
 * @param[out]  v->Alpha: Alpha Beta坐标系下的电流Alpha
 *              v->Beta: Alpha Beta坐标系下的电流Beta
 * @retval      none
 */
static inline void ipark_calc(ipark_t* v, fp32 _Ds, fp32 _Qs, fp32 _Angle) {
    fp32 Cosine, Sine;

    v->Ds = _Ds;
    v->Qs = _Qs;
    v->Angle = _Angle;

    Sine = falst_sin(v->Angle);
    Cosine = falst_cos(v->Angle);

    v->Alpha = (v->Ds * Cosine) - (v->Qs * Sine);
    v->Beta = (v->Qs * Cosine) + (v->Ds * Sine);
}

参考、引用

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐