简介
本文重点内容
本文重点关注SOGI的数字离散化方法,并对常用的数字离散化进行分析,并进行仿真验证,同时提供相对应的C代码(可直接仿真验证和TI 的demo 代码)。
相关链接
有关SOGI的相关内容,可以进入
[本人微信公众号]( https://mp.weixin.qq.com/s?__biz=Mzg4MDgwODMyNA==&mid=2247483678&idx=1&sn=354b122f91054affc7d1e34cbb6cfc13&chksm=cf6ed9f5f81950e32452cf0fa6720e7312e7c39f6b3967c4199fb2af98b98771f063bcb18870&token=2017180163&lang=zh_CN#rd )
或者 [CSDN 博客]( https://blog.csdn.net/qq_31251431/article/details/110466237?spm=1001.2014.3001.5501)
进行查看和阅读。
数字离散化方法介绍
常用的数字离散化方法有前向差分,后向差分,双线性变换,零阶保持器,零极点匹配法,有关这几种方法的详细介绍如下:
1.前向差分(Forward Euler method)
前向差分的离散化序列表达式为 y ( n ) = y ( n − 1 ) + T s u ( n − 1 ) y(n)=y(n-1)+T_su(n-1) y(n)=y(n−1)+Tsu(n−1),所以采用前向差分方法,积分环节 1 s \frac{1}{s} s1可以近似为 1 s = T s z − 1 1 − z − 1 \frac{1}{s}=T_s\frac{z^{−1}}{1−z^{−1}} s1=Ts1−z−1z−1 即 s = 1 − z − 1 T s z − 1 s=\frac{1−z^{−1}}{T_s z^{−1}} s=Tsz−11−z−1
2.后向差分(Backward Euler method)
后向差分的离散化序列表达式为 y ( n ) = y ( n − 1 ) + T s u ( n ) y(n)=y(n-1)+T_su(n) y(n)=y(n−1)+Tsu(n) ,所以采用后向差分方法,积分环节 1 s \frac{1}{s} s1可以近似为 1 s = T s 1 1 − z − 1 \frac{1}{s} = T_s \frac{1}{1−z^{−1}} s1=Ts1−z−11 即 s = 1 − z − 1 T s s=\frac{1−z^{−1}}{T_s} s=Ts1−z−1
3.双线性变换(Tustin Method)
双线性变换的离散化序列表达式为 y ( n ) = y ( n − 1 ) + T s [ u ( n ) + u ( n − 1 ) ] y(n)=y(n-1)+T_s[u(n)+u(n-1)] y(n)=y(n−1)+Ts[u(n)+u(n−1)],所以采用双线性变换方法,积分环节 1 s \frac{1}{s} s1可以近似为 1 s = T s 2 1 + z − 1 1 − z − 1 \frac{1}{s}=\frac{T_s}{2}\frac{1+z^{−1}}{1−z^{−1}} s1=2Ts1−z−11+z−1 即 s = 2 T s 1 − z − 1 1 + z − 1 s=\frac{2}{T_s}\frac{1−z^{−1}}{1+z^{−1}} s=Ts21+z−11−z−1
4.零阶保持器ZOH
零阶保持器方法,S域和Z域的转化关系如下
H
(
z
)
=
(
1
−
Z
−
1
)
Z
[
(
H
(
s
)
s
]
H(z)=(1−Z^{−1})Z[(\frac{H(s)}{s}]
H(z)=(1−Z−1)Z[(sH(s)]
5.零极点匹配法 (Matched Pole Zero)
零极点匹配方法,s域和Z域的转化关系如下。
z
=
e
T
s
s
z=e^{T_ss}
z=eTss
有关零极点匹配的详细介绍可见参考文献1,详细内容如下贴图所示。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0tHFzZr7-1654415583578)(https://raw.githubusercontent.com/Hong-Long/FigureToPicGo/main/Mathed-pole%20-zero.png)]
SOGI 数字离散化
针对SOGI,较为理想的数字离散化方法为Tustin变换和ZOH,Tustin变换和ZOH随着采样频率的增加,具有较好的变换精度。本文主要介绍常用的Tustin离散化方法。这一部分将对其详细的离散化过程进行分析和推导。有关其他方法的离散化,可以根据文中引入的参考文献进行推导和分析。但是在实际应用中,最常用的方法就是Tustin变换,也叫双线性变换。
离散化过程
首先,[本人微信公众号]( https://mp.weixin.qq.com/s?__biz=Mzg4MDgwODMyNA==&mid=2247483678&idx=1&sn=354b122f91054affc7d1e34cbb6cfc13&chksm=cf6ed9f5f81950e32452cf0fa6720e7312e7c39f6b3967c4199fb2af98b98771f063bcb18870&token=2017180163&lang=zh_CN#rd)
或者 [CSDN 博客]( https://blog.csdn.net/qq_31251431/article/details/110466237?spm=1001.2014.3001.5501)所述,SOGI的框图如图1所示。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aft0NPdZ-1654415583579)(https://raw.githubusercontent.com/Hong-Long/FigureToPicGo/main/20220602174016.png)]
Fig. SOGI 基本框架
根据图1所示,可以推导出变换器的两个关键传递函数,如公式(1)和(2)所示。
H
d
(
s
)
=
v
′
v
(
s
)
=
k
ω
s
s
2
+
k
ω
s
+
ω
2
H_d(s)=\frac{v^{'}}{v}(s)=\frac{k\omega s}{s^{2}+k\omega s+\omega ^{2}}
Hd(s)=vv′(s)=s2+kωs+ω2kωs
(1)
H q ( s ) = q v ′ v ( s ) = k ω 2 s 2 + k ω s + ω 2 H_q(s)=\frac{qv^{'}}{v}(s)=\frac{k\omega ^{2}}{s^{2}+k\omega s+\omega ^{2}} Hq(s)=vqv′(s)=s2+kωs+ω2kω2
(2)
接下来将使用Tustin方法对其进行离散化。
首先,根据Tustin方法中,s和z的关系式 s = 2 T s 1 − z − 1 1 + z − 1 = 2 T s z − 1 z + 1 s=\frac{2}{T_s}\frac{1−z^{−1}}{1+z^{−1}}=\frac{2}{T_s}\frac{z-1}{z+1} s=Ts21+z−11−z−1=Ts2z+1z−1,将其带入式1和2。可以分别得到如式3和4所示的表达式。
H d ( z ) = k ω 2 T s z − 1 z + 1 ( 2 T s z − 1 z + 1 ) 2 + k ω 2 T s z − 1 z + 1 + ω 2 H_d(z)=\frac{k\omega \frac{2}{T_s}\frac{z-1}{z+1}}{(\frac{2}{T_s}\frac{z-1}{z+1})^{2}+k\omega \frac{2}{T_s}\frac{z-1}{z+1}+\omega ^{2}} Hd(z)=(Ts2z+1z−1)2+kωTs2z+1z−1+ω2kωTs2z+1z−1
(3)
H q ( z ) = k ω 2 ( 2 T s z − 1 z + 1 ) 2 + k ω 2 T s z − 1 z + 1 + ω 2 H_q(z)=\frac{k\omega ^{2}}{(\frac{2}{T_s}\frac{z-1}{z+1})^{2}+k\omega \frac{2}{T_s}\frac{z-1}{z+1}+\omega ^{2}} Hq(z)=(Ts2z+1z−1)2+kωTs2z+1z−1+ω2kω2
(4)
对其进行化简,可以得到如式5,6所示的简化后的表达式。
H d ( z ) = 2 k ω T s ( z 2 − 1 ) 4 ( z − 1 ) 2 + 2 k ω T s ( z 2 − 1 ) + T s 2 ω 2 ( z + 1 ) 2 H_d(z)=\frac{2k\omega T_s (z^{2}-1)}{4(z-1)^{2}+2k\omega T_s(z^{2}-1)+T_s^{2}\omega^{2}(z+1)^{2}} Hd(z)=4(z−1)2+2kωTs(z2−1)+Ts2ω2(z+1)22kωTs(z2−1)
(5)
H q ( z ) = 2 k ω 2 [ T s ( z + 1 ) ] 2 4 ( z − 1 ) 2 + 2 k ω T s ( z 2 − 1 ) + T s 2 ω 2 ( z + 1 ) 2 H_q(z)=\frac{2k\omega^{2}[T_s(z+1)]^{2}}{4(z-1)^{2}+2k\omega T_s(z^{2}-1)+T_s^{2}\omega^{2}(z+1)^{2}} Hq(z)=4(z−1)2+2kωTs(z2−1)+Ts2ω2(z+1)22kω2[Ts(z+1)]2
(6)
为了进一步简化,便于数字化编程实现,做如下假设
{ x = 2 k ω T s y = ( ω T s ) 2 (7) \left \{ \begin{array}{c} x=2k\omega T_{s}\\ y=(\omega T_{s})^{2} \tag{7} \end{array} \right. {x=2kωTsy=(ωTs)2(7)
则公式5和公式6可以被改写为式8和式9所示表达式。
H d ( z ) = ( x x + y + 4 ) + ( − x x + y + 4 ) z − 2 1 − ( 2 ( 4 − y ) x + y + 4 ) z − 1 − ( x − y − 4 x + y + 4 ) z − 2 H_d(z)=\frac{{(\frac{x}{x+y+4})+(\frac{-x}{x+y+4})z^{-2}}}{1-(\frac{2(4-y)}{x+y+4})z^{-1}-(\frac{x-y-4}{x+y+4})z^{-2}} Hd(z)=1−(x+y+42(4−y))z−1−(x+y+4x−y−4)z−2(x+y+4x)+(x+y+4−x)z−2
(8)
H q ( z ) = ( k y x + y + 4 ) + ( 2 k y x + y + 4 ) z − 1 + ( k y x + y + 4 ) z − 2 1 − ( 2 ( 4 − y ) x + y + 4 ) z − 1 − ( x − y − 4 x + y + 4 ) z − 2 H_q(z)=\frac{{(\frac{ky}{x+y+4})+(\frac{2ky}{x+y+4})z^{-1}}+(\frac{ky}{x+y+4})z^{-2}}{1-(\frac{2(4-y)}{x+y+4})z^{-1}-(\frac{x-y-4}{x+y+4})z^{-2}} Hq(z)=1−(x+y+42(4−y))z−1−(x+y+4x−y−4)z−2(x+y+4ky)+(x+y+42ky)z−1+(x+y+4ky)z−2
(9)
令
{ b 0 = x x + y + 4 b 2 = − x x + y + 4 = − b 0 (10) \left\{ \begin{array}{ll} b_{0}=\frac{x}{x+y+4}\\ b_{2}=\frac{-x}{x+y+4}=-b_{0}\tag{10} \end{array} \right. {b0=x+y+4xb2=x+y+4−x=−b0(10)
{
a
1
=
2
(
4
−
y
)
x
+
y
+
4
a
2
=
x
−
y
−
4
x
+
y
+
4
(11)
\left\{ \begin{array}{ll} a_{1}=\frac{2(4-y)}{x+y+4}\\ a_{2}=\frac{x-y-4}{x+y+4}\tag{11} \end{array}\right.
{a1=x+y+42(4−y)a2=x+y+4x−y−4(11)
{
q
b
0
=
k
y
x
+
y
+
4
q
b
1
=
2
k
y
x
+
y
+
4
=
2
q
b
0
q
b
2
=
k
y
x
+
y
+
4
=
q
b
0
(12)
\left\{ \begin{array}{ll} qb_{0}=\frac{ky}{x+y+4}\\ qb_{1}=\frac{2ky}{x+y+4}=2qb_{0}\\ qb_{2}=\frac{ky}{x+y+4}=qb_{0}\tag{12} \end{array}\right.
⎩⎪⎨⎪⎧qb0=x+y+4kyqb1=x+y+42ky=2qb0qb2=x+y+4ky=qb0(12)
由此可以得到离散化SOGI关键表达式,如式13和式14。
H
d
(
z
)
=
b
0
+
b
2
z
−
2
1
−
a
1
z
−
1
−
a
2
z
−
2
H_{d}(z)=\frac{b_{0}+b_{2}z^{-2}}{1-a_{1}z^{-1}-a_{2}z^{-2}}
Hd(z)=1−a1z−1−a2z−2b0+b2z−2
(13)
H q ( z ) = q b 0 + q b 1 z − 1 + q b 2 z − 2 1 − a 1 z − 1 − a 2 z − 2 H_{q}(z)=\frac{qb_{0}+qb_{1}z^{-1}+qb_{2}z^{-2}}{1-a_{1}z^{-1}-a_{2}z^{-2}} Hq(z)=1−a1z−1−a2z−2qb0+qb1z−1+qb2z−2
(14)
仿真验证
基于以上公式推导,可以得到对应的离散化仿真模型。首先借助PLECS搭建了模块化离散化模型,然后采用C-block编写了C代码对该模块进行测试。
1. 基于PLECS 模块化离散模型
仿真模型搭建
上图给出了各变量的定义,系统的模块化模型如下图所示。
仿真参数具体设置如下:
- Simulation->Simulation Parameters->Solver
Solver Type set as fixed-step, Solver set as Discrete,
Solver options: Fixed step size set as 1 e − 6 1e^{-6} 1e−6 - Initialization
add the following commands.
Ts = 1e-6;
omega=2*pi*50;
k=0.8;
仿真结果
由图可以看出,经过离散化,SOGI基本达到了预期的仿真结果。可以正常得到两个正交的波形
v
′
v^{'}
v′和
q
v
′
qv^{'}
qv′。
伯德图如下。
有关该仿真的源文件以上传到GitHub,有需要的可以到如下链接自行下载。
[SOGI-Discrete GitHub](https://github.com/Hong-Long/Power-electronic-converters/tree/main/SOGI-PLL)
2. 基于PLECS C代码离散化仿真
C代码编写
在进行C代码编写前,同上一节使用离散化仿真模型不同,首先需要将式13和式14改写成如式15和式16所示的序列方程,已方便代码的编写。
v
′
(
k
)
−
a
1
v
′
(
k
−
1
)
−
a
2
v
′
(
k
−
2
)
=
b
0
v
(
k
)
+
b
2
v
(
k
−
2
)
v^{'}(k)-a_{1}v^{'}(k-1)-a_{2}v^{'}(k-2)=b_{0}v(k)+b_{2}v(k-2)
v′(k)−a1v′(k−1)−a2v′(k−2)=b0v(k)+b2v(k−2)
(15)
q v ′ ( k ) − a 1 q v ′ ( k − 1 ) − a 2 q v ′ ( k − 2 ) = q b 0 v ( k ) + q b 1 v ( k − 1 ) + q b 2 v ( k − 2 ) qv^{'}(k)-a_{1}qv^{'}(k-1)-a_{2}qv^{'}(k-2)=qb_{0}v(k)+qb_{1}v(k-1)+qb_{2}v(k-2) qv′(k)−a1qv′(k−1)−a2qv′(k−2)=qb0v(k)+qb1v(k−1)+qb2v(k−2)
(16)
接下来则可以根据式15和式16,编写相对应的C代码。
首先在C-Script 中,Code 菜单中Code declarations中填写如下变量定义代码
double vin_0,vin_1,vin_2;
double u_0,u_1,u_2;
double qu_0,qu_1,qu_2;
double k,omega,ts;
double x,y;
double temp;
double b0,b2;
double a1,a2;
double qb0,qb1,qb2;
double u_0,u_1,u_2;
double qu_0,qu_1,qu_2;
然后在Start function code中添加变量计算代码
k=InputSignal(1,0);
omega=InputSignal(1,1);
ts=InputSignal(1,2);
x = 2 * k *omega * ts;
y = (omega * ts) * (omega * ts);
temp = 1 / (x + y + 4);
b0 = x * temp;
b2 = - b0;
a1 = 2 * (4 - y) * temp;
a2 = (x - y - 4) * temp;
qb0 = k * y * temp;
qb1 = 2 * qb0;
qb2 = qb0;
紧接着在Output function code中添加序列表达式的计算代码。
vin_0 = InputSignal(0,0);
u_0 = (b0 * (vin_0 - vin_2))+
a1 * u_1 + a2 * u_2;
u_2 = u_1;
u_1 = u_0;
qu_0 =(qb0 * vin_0) +
(qb1 * vin_1) +
(qb2 * vin_2) +
(a1 * qu_1) +
(a2 * qu_2);
qu_2 = qu_1;
qu_1 = qu_0;
vin_2 = vin_1;
vin_1 = vin_0;
OutputSignal(0,0)=u_0;
OutputSignal(1,0)=qu_0;
有关C-Scription的设置如下图所示。
在该模型中,共包含2组输入,2组输出,第一组输入包含输入检测信号,第二组输入包括
k
,
ω
,
T
s
k,\omega,T_s
k,ω,Ts共三个参数,输出包括
v
′
,
q
v
′
v^{'},qv^{'}
v′,qv′
由图可以看出,经过离散化,SOGI按照预期产生了互为正交的正弦波
v
′
v^{'}
v′和
q
v
′
qv^{'}
qv′
3. TI 源代码分析
由于近来图腾柱PFC的兴起,所以TI 有提供配套的Totem pole PFC 控制代码,其中就包含SOGI-PLL部分的代码。这部分重点介绍有关SOGI部分的代码。
SOGI部分主要包含以下代码,首先是相关系数的结构体定义。共包含三个结构体,其中结构体SPLL_1PH_SOGI_OSG_COEFF与SOGI相关,SPLL_1PH_SOGI_LPF_COEFF结构体为PLL中PI调节器参数相关结构体;SPLL_1PH_SOGI为PLL相关结构体变量SPLL_1PH_SOGI_config用于配置PLL相关变量,主要包括网侧频率,PLL 中PI 参数;
typedef struct
{
float32_t osg_k;
float32_t osg_x;
float32_t osg_y;
float32_t osg_b0;
float32_t osg_b2;
float32_t osg_a1;
float32_t osg_a2;
float32_t osg_qb0;
float32_t osg_qb1;
float32_t osg_qb2;
} SPLL_1PH_SOGI_OSG_COEFF;
typedef struct
{
float32_t b1;
float32_t b0;
} SPLL_1PH_SOGI_LPF_COEFF;
typedef struct
{
float32_t u[3]; //!< AC input data buffer
float32_t osg_u[3]; //!< Orthogonal signal generator data buffer
float32_t osg_qu[3]; //!< Orthogonal signal generator quadrature data buffer
float32_t u_Q[2]; //!< Q-axis component
float32_t u_D[2]; //!< D-axis component
float32_t ylf[2]; //!< Loop filter data storage
float32_t fo; //!< Output frequency of PLL(Hz)
float32_t fn; //!< Nominal frequency (Hz)
float32_t theta; //!< Angle output (0-2*pi)
float32_t cosine; //!< Cosine value of the PLL angle
float32_t sine; //!< Sine value of the PLL angle
float32_t delta_t; //!< Inverse of the ISR rate at which module is called
SPLL_1PH_SOGI_OSG_COEFF osg_coeff; //!< Orthogonal signal generator coefficient
SPLL_1PH_SOGI_LPF_COEFF lpf_coeff; //!< Loop filter coeffcient structure
} SPLL_1PH_SOGI;
涉及到的函数主要包含以下部分,SPLL_1PH_SOGI_reset为参数复位函数,即将所有参数初始化为0,在程序启动的时候进行调用,SPLL_1PH_SOGI_coeff_calc用于计算离散化后公式中的关键参数,在程序启动的时候进行调用;SPLL_1PH_SOGI_run为PLL中最关键的一个函数,用于生成SOGI,和后续的PLL锁相,在中断中进行调用。经过该函数,会得到网侧电压的相角theta。
static inline void SPLL_1PH_SOGI_reset(SPLL_1PH_SOGI *spll_obj)
{
spll_obj->u[0]=(float32_t)(0.0);
spll_obj->u[1]=(float32_t)(0.0);
spll_obj->u[2]=(float32_t)(0.0);
spll_obj->osg_u[0]=(float32_t)(0.0);
spll_obj->osg_u[1]=(float32_t)(0.0);
spll_obj->osg_u[2]=(float32_t)(0.0);
spll_obj->osg_qu[0]=(float32_t)(0.0);
spll_obj->osg_qu[1]=(float32_t)(0.0);
spll_obj->osg_qu[2]=(float32_t)(0.0);
spll_obj->u_Q[0]=(float32_t)(0.0);
spll_obj->u_Q[1]=(float32_t)(0.0);
spll_obj->u_D[0]=(float32_t)(0.0);
spll_obj->u_D[1]=(float32_t)(0.0);
spll_obj->ylf[0]=(float32_t)(0.0);
spll_obj->ylf[1]=(float32_t)(0.0);
spll_obj->fo=(float32_t)(0.0);
spll_obj->theta=(float32_t)(0.0);
spll_obj->sine=(float32_t)(0.0);
spll_obj->cosine=(float32_t)(0.0);
}
static inline void SPLL_1PH_SOGI_coeff_calc(SPLL_1PH_SOGI *spll_obj)
{
float32_t osgx,osgy,temp, wn;
wn= spll_obj->fn *(float32_t) 2.0f * (float32_t) 3.14159265f;
spll_obj->osg_coeff.osg_k=(float32_t)(0.5);
osgx = (float32_t)(2.0f*0.5f*wn*spll_obj->delta_t);
spll_obj->osg_coeff.osg_x=(float32_t)(osgx);
osgy = (float32_t)(wn*spll_obj->delta_t*wn*spll_obj->delta_t);
spll_obj->osg_coeff.osg_y=(float32_t)(osgy);
temp = (float32_t)1.0/(osgx+osgy+4.0f);
spll_obj->osg_coeff.osg_b0=((float32_t)osgx*temp);
spll_obj->osg_coeff.osg_b2=((float32_t)(-1.0f)*spll_obj->osg_coeff.osg_b0);
spll_obj->osg_coeff.osg_a1=((float32_t)(2.0*(4.0f-osgy))*temp);
spll_obj->osg_coeff.osg_a2=((float32_t)(osgx-osgy-4)*temp);
spll_obj->osg_coeff.osg_qb0=((float32_t)(0.5f*osgy)*temp);
spll_obj->osg_coeff.osg_qb1=(spll_obj->osg_coeff.osg_qb0*(float32_t)(2.0));
spll_obj->osg_coeff.osg_qb2=spll_obj->osg_coeff.osg_qb0;
}
static inline void SPLL_1PH_SOGI_config(SPLL_1PH_SOGI *spll_obj,
float32_t acFreq,
float32_t isrFrequency,
float32_t lpf_b0,
float32_t lpf_b1)
{
spll_obj->fn=acFreq;
spll_obj->delta_t=((1.0f)/isrFrequency);
SPLL_1PH_SOGI_coeff_calc(spll_obj);
spll_obj->lpf_coeff.b0=lpf_b0;
spll_obj->lpf_coeff.b1=lpf_b1;
}
static inline void SPLL_1PH_SOGI_run(SPLL_1PH_SOGI *spll_obj,
float32_t acValue)
{
// Update the spll_obj->u[0] with the grid value
spll_obj->u[0]=acValue;
//
// Orthogonal Signal Generator
//
spll_obj->osg_u[0]=(spll_obj->osg_coeff.osg_b0*
(spll_obj->u[0]-spll_obj->u[2])) +
(spll_obj->osg_coeff.osg_a1*spll_obj->osg_u[1]) +
(spll_obj->osg_coeff.osg_a2*spll_obj->osg_u[2]);
spll_obj->osg_u[2]=spll_obj->osg_u[1];
spll_obj->osg_u[1]=spll_obj->osg_u[0];
spll_obj->osg_qu[0]=(spll_obj->osg_coeff.osg_qb0*spll_obj->u[0]) +
(spll_obj->osg_coeff.osg_qb1*spll_obj->u[1]) +
(spll_obj->osg_coeff.osg_qb2*spll_obj->u[2]) +
(spll_obj->osg_coeff.osg_a1*spll_obj->osg_qu[1]) +
(spll_obj->osg_coeff.osg_a2*spll_obj->osg_qu[2]);
spll_obj->osg_qu[2]=spll_obj->osg_qu[1];
spll_obj->osg_qu[1]=spll_obj->osg_qu[0];
spll_obj->u[2]=spll_obj->u[1];
spll_obj->u[1]=spll_obj->u[0];
//
// Park Transform from alpha beta to d-q axis
//
spll_obj->u_Q[0]=(spll_obj->cosine*spll_obj->osg_u[0]) +
(spll_obj->sine*spll_obj->osg_qu[0]);
spll_obj->u_D[0]=(spll_obj->cosine*spll_obj->osg_qu[0]) -
(spll_obj->sine*spll_obj->osg_u[0]);
//
// Loop Filter
//
spll_obj->ylf[0]=spll_obj->ylf[1] +
(spll_obj->lpf_coeff.b0*spll_obj->u_Q[0]) +
(spll_obj->lpf_coeff.b1*spll_obj->u_Q[1]);
spll_obj->ylf[1]=spll_obj->ylf[0];
spll_obj->u_Q[1]=spll_obj->u_Q[0];
//
// VCO
//
spll_obj->fo=spll_obj->fn+spll_obj->ylf[0];
spll_obj->theta=spll_obj->theta + (spll_obj->fo*spll_obj->delta_t)*
(float32_t)(2.0*3.1415926f);
if(spll_obj->theta>(float32_t)(2.0*3.1415926f))
{
spll_obj->theta=spll_obj->theta - (float32_t)(2.0*3.1415926f);
//spll_obj->theta=0;
}
spll_obj->sine=(float32_t)sinf(spll_obj->theta);
spll_obj->cosine=(float32_t)cosf(spll_obj->theta);
}
有关详细代码可以去TI 官网寻找,我也把其中一份代码上传到了GitHub供大家参考。
[TI-Demo Code download](https://github.com/Hong-Long/Power-electronic-converters)
文章后续会逐渐同步到微信公众号,可关注浏览
欢迎各位同僚可以一起指导进步。