SPLL_1ph_SOGI_F_init(AC_FREQ, (float)((float)(1.0/ISR_CONTROL_FREQUENCY)), &spll1);
SPLL_1ph_SOGI_F_coeff_update(((float) (1.0 / ISR_CONTROL_FREQUENCY)), (float) (2 * PI * AC_FREQ), &spll1);
// from the excel sheet the analog coeffieints are Kp=166.6202275, Ki=14164.43889
SPLL_LPF_Coeff_Update(&spll1,(float)166.6202275,(float)14164.43889,(float)(1.0 / ISR_CONTROL_FREQUENCY));
#include "math.h"
#define CNTRL_ISR_FREQ_RATIO 1
#define INV_PWM_SWITCHING_FREQUENCY ((float)20*1000)
#define ISR_CONTROL_FREQUENCY (INV_PWM_SWITCHING_FREQUENCY)/(CNTRL_ISR_FREQ_RATIO)
#define AC_FREQ 60
#define PI 3.141592653589
//*********** Structure Definition ********//
typedef struct{
float osg_k;
float osg_x;
float osg_y;
float osg_b0;
float osg_b2;
float osg_a1;
float osg_a2;
float osg_qb0;
float osg_qb1;
float osg_qb2;
}SPLL_1ph_SOGI_F_OSG_COEFF;
typedef struct{
float B1_lf;
float B0_lf;
float A1_lf;
}SPLL_1ph_SOGI_F_LPF_COEFF;
typedef struct{
float u[3]; // Ac Input
float osg_u[3];
float osg_qu[3];
float u_Q[2];
float u_D[2];
float ylf[2];
float fo; // output frequency of PLL
float fn; //nominal frequency
float theta[2];
float cos;
float sin;
float delta_T;
SPLL_1ph_SOGI_F_OSG_COEFF osg_coeff;
SPLL_1ph_SOGI_F_LPF_COEFF lpf_coeff;
}SPLL_1ph_SOGI_F;
//*********** Function Declarations *******//
void SPLL_1ph_SOGI_F_init(int Grid_freq, float DELTA_T, SPLL_1ph_SOGI_F *spll);
void SPLL_1ph_SOGI_F_coeff_update(float delta_T, float wn, SPLL_1ph_SOGI_F *spll);
void SPLL_1ph_SOGI_F_FUNC(SPLL_1ph_SOGI_F *spll1);
//*********** Macro Definition ***********//
#define SPLL_1ph_SOGI_F_MACRO(v) \
v.osg_u[0]=(v.osg_coeff.osg_b0*(v.u[0]-v.u[2])) + (v.osg_coeff.osg_a1*v.osg_u[1]) + (v.osg_coeff.osg_a2*v.osg_u[2]); \
v.osg_u[2]=v.osg_u[1]; \
v.osg_u[1]=v.osg_u[0]; \
v.osg_qu[0]=(v.osg_coeff.osg_qb0*v.u[0]) + (v.osg_coeff.osg_qb1*v.u[1]) + (v.osg_coeff.osg_qb2*v.u[2]) + (v.osg_coeff.osg_a1*v.osg_qu[1]) + (v.osg_coeff.osg_a2*v.osg_qu[2]); \
v.osg_qu[2]=v.osg_qu[1]; \
v.osg_qu[1]=v.osg_qu[0]; \
v.u[2]=v.u[1]; \
v.u[1]=v.u[0]; \
v.u_Q[0]=(v.cos*v.osg_u[0]) + (v.sin*v.osg_qu[0]); \
v.u_D[0]=(v.cos*v.osg_qu[0]) - (v.sin*v.osg_u[0]); \
v.ylf[0]=v.ylf[1] + (v.lpf_coeff.B0_lf*v.u_Q[0]) + (v.lpf_coeff.B1_lf*v.u_Q[1]); \
v.ylf[1]=v.ylf[0]; \
v.u_Q[1]=v.u_Q[0]; \
v.fo=v.fn + v.ylf[0]; \
v.theta[0]=v.theta[1] + ((v.fo*v.delta_T)*(float)(2.0*3.1415926)); \
if(v.theta[0]>(float)(2.0*3.1415926)) \
v.theta[0]=(float)(0.0); \
v.theta[1]=v.theta[0]; \
v.sin=(float)(sin(v.theta[0])); \
v.cos=(float)(cos(v.theta[0]));
void SPLL_LPF_Coeff_Update(SPLL_1ph_SOGI_F *spll, float Kp, float Ki, float Ts)
{
spll->lpf_coeff.B0_lf= ((2.0)*Kp+(float)Ki*(float)Ts)*0.5;
spll->lpf_coeff.B1_lf= -((2.0)*Kp-(float)Ki*(float)Ts)*0.5;
spll->lpf_coeff.A1_lf = 1;
}
//*********** Structure Init Function ****//
void SPLL_1ph_SOGI_F_init(int Grid_freq, float DELTA_T, SPLL_1ph_SOGI_F *spll_obj)
{
spll_obj->u[0]=(float)(0.0);
spll_obj->u[1]=(float)(0.0);
spll_obj->u[2]=(float)(0.0);
spll_obj->osg_u[0]=(float)(0.0);
spll_obj->osg_u[1]=(float)(0.0);
spll_obj->osg_u[2]=(float)(0.0);
spll_obj->osg_qu[0]=(float)(0.0);
spll_obj->osg_qu[1]=(float)(0.0);
spll_obj->osg_qu[2]=(float)(0.0);
spll_obj->u_Q[0]=(float)(0.0);
spll_obj->u_Q[1]=(float)(0.0);
spll_obj->u_D[0]=(float)(0.0);
spll_obj->u_D[1]=(float)(0.0);
spll_obj->ylf[0]=(float)(0.0);
spll_obj->ylf[1]=(float)(0.0);
spll_obj->fo=(float)(0.0);
spll_obj->fn=(float)(Grid_freq);
spll_obj->theta[0]=(float)(0.0);
spll_obj->theta[1]=(float)(0.0);
spll_obj->sin=(float)(0.0);
spll_obj->cos=(float)(0.0);
// loop filter coefficients for 20kHz
spll_obj->lpf_coeff.B0_lf=(float)(166.9743);
spll_obj->lpf_coeff.B1_lf=(float)(-166.266);
spll_obj->lpf_coeff.A1_lf=(float)(-1.0);
spll_obj->delta_T=DELTA_T;
}
//*********** Structure Coeff Update *****//
void SPLL_1ph_SOGI_F_coeff_update(float delta_T, float wn, SPLL_1ph_SOGI_F *spll)
{
float osgx,osgy,temp;
spll->osg_coeff.osg_k=(float)(0.5);
osgx=(float)(2.0*0.5*wn*delta_T);
spll->osg_coeff.osg_x=(float)(osgx);
osgy=(float)(wn*delta_T*wn*delta_T);
spll->osg_coeff.osg_y=(float)(osgy);
temp=(float)1.0/(osgx+osgy+4.0);
spll->osg_coeff.osg_b0=((float)osgx*temp);
spll->osg_coeff.osg_b2=((float)(-1.0)*spll->osg_coeff.osg_b0);
spll->osg_coeff.osg_a1=((float)(2.0*(4.0-osgy))*temp);
spll->osg_coeff.osg_a2=((float)(osgx-osgy-4)*temp);
spll->osg_coeff.osg_qb0=((float)(0.5*osgy)*temp);
spll->osg_coeff.osg_qb1=(spll->osg_coeff.osg_qb0*(float)(2.0));
spll->osg_coeff.osg_qb2=spll->osg_coeff.osg_qb0;
}
//*********** Function Definition ********//
void SPLL_1ph_SOGI_F_FUNC(SPLL_1ph_SOGI_F *spll_obj)
{
// Update the spll_obj->u[0] with the grid value before calling this routine
//-------------------------------//
// 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->cos*spll_obj->osg_u[0]) + (spll_obj->sin*spll_obj->osg_qu[0]);
spll_obj->u_D[0]=(spll_obj->cos*spll_obj->osg_qu[0]) - (spll_obj->sin*spll_obj->osg_u[0]);
//---------------------------------//
// Loop Filter //
//---------------------------------//
spll_obj->ylf[0]=spll_obj->ylf[1] + (spll_obj->lpf_coeff.B0_lf*spll_obj->u_Q[0]) + (spll_obj->lpf_coeff.B1_lf*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[0]=spll_obj->theta[1] + (spll_obj->fo*spll_obj->delta_T)*(float)(2.0*3.1415926);
if(spll_obj->theta[0]>(float)(2.0*3.1415926))
spll_obj->theta[0]=(float)(0.0);
spll_obj->theta[1]=spll_obj->theta[0];
spll_obj->sin=(float)sin(spll_obj->theta[0]);
spll_obj->cos=(float)cos(spll_obj->theta[0]);
}
SPLL_1ph_SOGI_F spll1;
float count = 0;
#include "math.h"
// Define Input data
float Vac = InputSignal(0, 0);
//SPLL 1ph SOGI Method initialization
count++;
spll1.u[0] = Vac;
SPLL_1ph_SOGI_F_MACRO(spll1);
//
// output
//
OutputSignal(0, 0) = spll1.theta[0];
OutputSignal(0, 1) = count;