I am going to implement in C++ software the synchronous frame phase locked loop (SFPLL) for estimation of angle and frequency of the three phase grid 220V/50Hz.
For the internal PI controller setting I have decided to use the design by emulation method i.e. design the controller as if the system to be continuous, transform the PI controller into the discrete domain and verify the design in discrete simulation.
- PI controller design for continuous system
I have chosen the root locus design method for its clarity. The closed loop transfer function of the SFPLL (in case the grid voltages have amplitudes equal to unity) is
\begin{equation} H(s) = \frac{\left(K_p + \frac{K_i}{s}\right)\cdot\frac{1}{s}}{1 +\left(K_p + \frac{K_i}{s}\right)\cdot\frac{1}{s}} = \frac{K_p\cdot s + K_i}{s^2 + K_p\cdot s + K_i}. \end{equation}
In case I compare the characteristic polynomial with the characteristic polynomial of second order system $s^2 + 2\cdot\zeta\cdot\omega_n\cdot s + \omega_n^2$ I have following formulas for the PI controller parameters
\begin{eqnarray} K_p &=& 2\cdot\zeta\cdot\omega_n \Rightarrow \zeta = \frac{K_p}{2\cdot\omega_n} = \frac{K_p}{2\sqrt{K_i}} = \frac{\sqrt{K_p\cdot T_i}}{2} \\ K_i &=& \omega_n^2 \Rightarrow \omega_n = \sqrt{K_i} = \sqrt{\frac{K_p}{T_i}} \end{eqnarray} i.e. \begin{eqnarray} T_i = \frac{2\cdot\zeta}{\omega_n} \end{eqnarray}
Based on the following formula for the settling time
\begin{eqnarray} t_s = \frac{4.6}{\zeta\cdot\omega_n} = \frac{4.6}{\sigma} \end{eqnarray}
I have final formulas for the PI controller parameters design
\begin{eqnarray} K_p &=& 2\cdot\zeta\cdot\omega_n = 2\cdot\sigma = 2\cdot\frac{4,6}{t_s} = \frac{9,2}{t_s} \\ T_i &=& \frac{2\cdot\zeta}{\omega_n} = \frac{2\cdot\zeta}{\frac{4,6}{\zeta\cdot t_s}} = \frac{\zeta^2\cdot t_s}{2,3} \end{eqnarray}
I have chosen the damping ratio $\zeta=0,7$ and settling time $t_s=0,02\,s$ (one period of the grid 50 Hz). Based on that I have $K_p=460\,\mathrm{Hz/V}, T_i=0,0043\,\mathrm{s}$. In respect to the real value of the amplitude of the grid voltage I have $K_p=\frac{460}{220\cdot\sqrt{2}}\,\mathrm{Hz/V}$.
- Transformation of the PI controller into the discrete domain
I have chosen the trapezoidal integration rule for the transformation and I have set the sampling period to the value $50\,\mu s$.
- Design verification
I have developed a simulation of the SFPLL in the Scilab/Xcos software.
a) Grid model
The model simulates three phase grid 220V/50 Hz connected at $t=0.04\,\mathrm{s}$ and with the intial phase $\phi_0=\frac{\pi}{2}$.
b) SFPLL model
The model of the PLL
The C block contains following C language code
#include "scicos_block4.h"
#include "stdio.h"
#define reference_value ((double *)GetRealInPortPtrs(block, 1))
#define actual_value ((double *)GetRealInPortPtrs(block, 2))
#define action_value ((double *)GetRealOutPortPtrs(block, 1))
#define unsaturated_action_value ((double *)GetRealOutPortPtrs(block, 2))
// parameters
#define Kp (GetRparPtrs(block)[0])
#define Ti (GetRparPtrs(block)[1])
#define T (GetRparPtrs(block)[2])
#define Min (GetRparPtrs(block)[3])
#define Max (GetRparPtrs(block)[4])
typedef struct
{
double error;
double proportional_increment;
double integral_increment;
double action_increment;
double tmp;
double error_previous;
double action_previous;
}Pid_work;
FILE *dump_file;
void Pid(scicos_block *block,int flag)
{
Pid_work *work;
if (flag == 4)
{
/* init */
if((*(block->work) = (Pid_work*)scicos_malloc(sizeof(Pid_work))) == NULL)
{
set_block_error(-16);
return;
}
work = *(block->work);
work->error = 0;
work->proportional_increment = 0;
work->integral_increment = 0;
work->action_increment = 0;
work->tmp = 0;
work->error_previous = 0;
work->action_previous = 0;
dump_file = fopen("PI_dump.txt", "w");
fprintf(dump_file, "Kp, Ki, Action_Min, Action_Max, Action_Saturated, Action_Unsaturated \n");
fprintf(dump_file, "==================================================================== \n");
} else if(flag == 1) {
work = *(block->work);
work->error = reference_value[0] - actual_value[0];
work->proportional_increment = Kp*(work->error - work->error_previous);
work->integral_increment = Kp*T/(2*Ti)*(work->error + work->error_previous);
work->action_increment = work->proportional_increment + work->integral_increment;
work->tmp = work->action_previous + work->action_increment;
unsaturated_action_value[0] = work->tmp;
if(work->tmp > Max)
{
action_value[0] = Max;
}
else if(work->tmp < Min)
{
action_value[0] = Min;
}
else
{
action_value[0] = work->tmp;
}
fprintf(dump_file, "%f, %f, %f, %f, %f, %f \n", Kp, Kp*T/(2*Ti), Min, Max, action_value[0], work->tmp);
work->action_previous = action_value[0];
work->error_previous = work->error;
} else if (flag == 5) {
/* ending */
scicos_free(*(block->work));
fclose(dump_file);
}
}
c) Grid voltages reconstructor
This block reconstructs the grid voltages based on the angle, $u_d$ and $u_q$ values computed by the PLL.
As far as the outcomes of the simulation
- $u_d$ vs $u_{d_e}$
- $u_q$ vs $u_{q_e}$
- $f$ vs $f_e$
- $u_a$ vs $u_{a_e}$
I am surprised by the huge overshoot of the frequency despite the chosen damping ration value 0,7 and small sampling period (it corresponds to 400 samples per one period of the grid). Can anybody tell me what is the reason of the huge frequency overshoot?