## SOGI-FLL-PLL
简述SOGI原理及程序实现。
SOGI主要有两种:一种是基波频率固定的SOGI,另一种是结合锁频环(FLL)实现频率自适应的SOGI。
1.基波频率固定的SOGI,其结构框图如图所示。
SOGI的功能就是产生两个完全正交的信号v’和qv’,理想情况下v’等于v,err为0。为了探究SOGI的效果我们可以根据框图列出以下传递函数。
s代表90度相位,则从上式可以发现,v’会超前qv’90度。把s=jw0代入,err为0,当s等于其它值时,err均不为0,且偏离越远误差越大。如伯德图所示,只有在基波频率处,对err有无穷小增益,此为SOGI的选频特性。
这意味着在使用这种SOGI时必须知道输入对象的频率,且频率不能变化太大,否则SOGI将无法准确跟踪。不过电网频率的波动一般不大,可以用于电网琐相。
2.带锁频环的SOGI,老规矩,先上结构框图
可以看到和原来的区别就是加了一个FLL,把原来乘固定的w0变成了乘w’。频率的偏差会造成err泛滥,用err反过来调节频率,err不停,调频不止,从而达到频率自适应。不要问我FLL怎么来的,问就是站在巨人的肩膀上从天而降来的,对我而言这只是一个工具,如果你知道它的前世今生可以给我分享一下它的故事。整个框图看着就两个系数,k和另一个看着很牛但叫不上名字的符号,k可以根据典型二阶系统的最佳工业系数,将其定为根号2,另外一个如果你没意见的话就是46,如果有意见的话就自己画画伯德图按照你的喜好拿捏它。
3.无论使用哪种方法,经过SOGI之后,想必已经拿到了准确的两个正交分量v’和qv’或者也可以说是alpha/beta静止坐标系下的两个分量,但最终我们想要的还是输入信号的角度信息。
从图中我们可以发现,想要角度的话可以简单的通过arctan(qv’/v’)进行求解,显然这比较简单粗暴不够闭环,当然也不否认这是一种行之有效的办法。如果不想这么直接了当的话,也可以找个PLL(锁相环)来牵线搭桥,PLL控制框图如下。
至于锁相环的原理和参数设计推导暂时不讨论。上传了一个m文件进行简单的参数设计。
4.最后是SOGI-FLL的程序实现,后项差分,不使用PLL。当然你也可以根据传递函数采用喜欢的方式进行离散,得到更适合自己的程序。
#define Sogi_k 1.414
#define FLL_gain -46
typedef struct
{
float *input;
float errv ;
float v_p;
float qv_p_temp ;
float qv_p ;
float w_p;
float errf ;
float Mag_2 ;
float phase ;
float cos ;
float mag ;
float Ts;
}SOGI;
volatile SOGI FLL;
memset((void *)&FLL,0,sizeof(FLL));
FLL.errv = *(FLL.input) - FLL.v_p;
FLL.v_p = FLL.w_p*(Sogi_k*FLL.v_p - FLL.qv_p)*FLL.Ts + FLL.v_p;
FLL.qv_p_temp = FLL.qv_p_temp + FLL.v_p*FLL.Ts;
FLL.qv_p = FLL.w_p*FLL.qv_p_temp;
FLL.errf = FLL.errv*FLL.qv_p;
FLL.Mag_2 = FLL.v_p*FLL.v_p + FLL.qv_p*FLL.qv_p;
FLL.w_p = FLL.w_p + FLL.w_p*Sogi_k*FLL.errf*FLL_gain*FLL.Ts/(FLL.Mag_2 + 0.1);
if(FLL.w_p < sogi_w_min)FLL.w_p = sogi_w_min;
FLL.phase = atan2(FLL.qv_p,FLL.v_p);
FLL.cos = cos(FLL.phase );
FLL.mag = sqrt(FLL.Mag_2 );