(Psim, C code)(Need to insert detailed comments for each step ) Here is C code a
ID: 2081920 • Letter: #
Question
(Psim, C code)(Need to insert detailed comments for each step)
Here is C code about 3-level NPC connected inverter with PLL system.
and Simple comments are inserted.
Could you insert detailed comments?
#include
#define pi 3.141592653589
#define T_samp 100.e-6
//variable declaration
double f = 0.;
double T_cnt = 0.;
double L_f = 0., R_f = 0.;
double wc_i = 0.;
double theta = 0., thetae=0.;
double v_a_ref = 0.;
double v_b_ref = 0.;
double v_c_ref = 0.;
double v_de_ref = 0.;
double v_qe_ref = 0.;
double v_ds_ref = 0.;
double v_qs_ref = 0.;
double v_a_ref_scale = 0.;
double v_b_ref_scale = 0.;
double v_c_ref_scale = 0.;
double dc_link = 0.;
double car = 0. , car_u=0. , car_d =0.;
double i_a_in = 0.;
double i_b_in = 0.;
double i_c_in = 0.;
double i_de_in_ref = 0. , i_qe_in_ref=0.;
double i_ds_in = 0., i_qs_in = 0.;
double i_de_in = 0., i_qe_in = 0.;
double p_gain_i = 0., i_gain_i = 0.;
double i_de_in_err = 0., i_qe_in_err = 0.;
double i_de_err_int = 0., i_qe_err_int = 0.;
double sa1 = 0., sa2 = 0., sa3 = 0., sa4 = 0.;
double sb1 = 0., sb2 = 0., sb3 = 0., sb4 = 0.;
double sc1 = 0., sc2 = 0., sc3 = 0., sc4 = 0.;
double zeta = 0.7, wn = 200.;
double Va = 0., Vb = 0., Vc = 0.;
double V_in_AB = 0., V_in_BC = 0., V_in_CA = 0.;
double wc = 0.;
double Vds = 0., Vqs = 0., Vde =0.,Vqe=0.;
double Vm = 0., Ts=0.;
double La = 0., Lb = 0.,we=0.;
double Vde_err = 0., Vde_ref = 0., Vde_err_int=0., Vde_err_in=0.;
double Kp = 0., Ki = 0., wrate=0.;
double Y_old = 0., X_old = 0., Y = 0., Yde=0.;
__declspec(dllexport) void simuser(double t, double dt, double *in, double *out)
{
//increase T_cnt
T_cnt += dt;
//input variable setting
car = in[0];
i_a_in = in[1];
i_b_in = in[2];
i_c_in = in[3];
dc_link = in[4];
V_in_AB = in[5];
V_in_BC = in[6];
V_in_CA = in[7];
//current controll constant
if (t < 0.2)
{
i_de_in_ref = 0., i_qe_in_ref = 5.;
}
else if (t < 0.3)
{
i_de_in_ref = 0., i_qe_in_ref = 10.;
}
else
{
i_de_in_ref = 0., i_qe_in_ref = 5.;
}
//T_cnt increase by dt and It works if it is bigger than T_samp
//then, T_cnt reset
if (T_cnt >= T_samp)
{
//line voltage -> phase voltage
Va = (V_in_AB - V_in_CA)*0.33333333;
Vb = (V_in_BC - V_in_AB)*0.33333333;
Vc = -(Va + Vb);
wc = 1. + 2. + zeta + wn;
Vds = (2.*Va - Vb - Vc) / 3.;
Vqs = (Vb - Vc) / sqrt(3.);
Vde = Vds*cos(theta) + Vqs*sin(theta);
Vqe = -Vds*sin(theta) + Vqs * cos(theta);
Vm = sqrt(Vds*Vds + Vqs*Vqs);
/*
La = (2. - wc*T_samp) / (2. + wc*T_samp);
Lb = (wc*T_samp) / (2. + wc*T_samp);
Y = (La * Y_old) + Lb * (Vde + X_old);
Y_old = Y;
X_old = Yde;
*/
Vde_err = Vde_ref - Vde;
Vde_err_int += Vde_err * T_samp;
Kp = 2. * zeta * wn / (Vm + 0.000000001);
Ki = (wn*wn) / ((Vm + 0.000000001)*wc);
f = 60.;
wrate = 2. * pi * f;
we = Vde_err * Kp + Vde_err_in * Ki + wrate;
//thetae += we*T_samps; //Synchronous Reference Frame frequency
theta += we*T_samp;
if (theta > pi) { theta -= 2.*pi; }
else if (theta < -pi) { theta += 2.*pi; }
/*
theta += 2.* pi*f*T_samp;
if (theta < 0.)
{
theta += 2.*pi;
}
if (theta > 2*pi)
{
theta -= 2.*pi;
}
*/
//transform to d and q axis variables
i_ds_in = (2.*i_a_in - i_b_in - i_c_in) / 3.;
i_qs_in = (1. / sqrt(3.))*(i_b_in - i_c_in);
//transform to Rotating Reference Frame d-q axis variable
i_de_in = i_ds_in * cos(theta) + i_qs_in * sin(theta);
i_qe_in = -i_ds_in * sin(theta) + i_qs_in * cos(theta);
L_f = 0.002;
R_f = 0.1;
wc_i = 1000.;
p_gain_i = L_f * wc_i;
i_gain_i = R_f * wc_i;
i_de_in_err = i_de_in_ref - i_de_in;
i_qe_in_err = i_qe_in_ref - i_qe_in;
i_de_err_int += i_de_in_err * T_samp;
i_qe_err_int += i_qe_in_err * T_samp;
//Rotating Reference Frame
v_de_ref = p_gain_i * i_de_in_err + i_gain_i * i_de_err_int;
v_qe_ref = p_gain_i * i_qe_in_err + i_gain_i * i_qe_err_int;
//v_de_ref = 0.;
//v_qe_ref = 150.; //The current magnitude changes. By this value-> currnet control(open loop)
//Stationary Reference Frame
v_ds_ref = v_de_ref * cos(theta) - v_qe_ref * sin(theta); //inverse transform using theta
v_qs_ref = v_de_ref * sin(theta) + v_qe_ref * cos(theta);
//3phases
v_a_ref = v_ds_ref;//Change to 3 phases again
v_b_ref = (-1.* v_ds_ref + sqrt(3.)*v_qs_ref) / 2;
v_c_ref = (-1.* v_ds_ref - sqrt(3.)*v_qs_ref) / 2;
v_a_ref_scale = (v_a_ref / dc_link) + 0.5;
v_b_ref_scale = (v_b_ref / dc_link) + 0.5;
v_c_ref_scale = (v_c_ref / dc_link) + 0.5;
//T_cnt reset
T_cnt -= T_samp;
}
//Set output value compared with triangle wave
if (v_a_ref_scale > car)
{
sa1 = 1, sa2 = 1, sa3 = 0, sa4 = 0;
}
else
{
sa1 = 0, sa2 = 0, sa3 = 1, sa4 = 1;
}
if (v_b_ref_scale > car)
{
sb1 = 1, sb2 = 1, sb3 = 0, sb4 = 0;
}
else
{
sb1 = 0, sb2 = 0, sb3 = 1, sb4 = 1;
}
if (v_c_ref_scale > car)
{
sc1 = 1, sc2 = 1, sc3 = 0, sc4 = 0;
}
else
{
sc1 = 0, sc2 = 0, sc3 = 1, sc4 = 1;
}
//output
out[0] = Vm;//magnitude
out[1] = we;//frequency
out[2] = theta;//phase
out[3] = Va;
out[4] = Vb;
out[5] = Vc;
out[6] = Vde;
out[7] = Vqe;
out[8] = v_a_ref;
out[9] = v_b_ref;
out[10] = v_c_ref;
out[11] = i_qe_in;
out[12] = i_qe_in_ref;
out[13] = sa1;
out[14] = sa2;
out[15] = sa3;
out[16] = sa4;
out[17] = sb1;
out[18] = sb2;
out[19] = sb3;
out[20] = sb4;
out[21] = sc1;
out[22] = sc2;
out[23] = sc3;
out[24] = sc4;
}
/*
#include
double Carrier = 0.;
double Duty_ref = 0.;
double Gate_signal = 0.;
__declspec(dllexport) void simuser(double t, double dt, double *in, double *out)
{
Carrier = in[0];
Duty_ref = in[1];
if (Carrier >- Duty_ref)
Gate_signal = 0;
if (Carrier < Duty_ref)
Gate_signal = 1;
out[0] = Gate_signal;
}
double v_tri=0.;
double v_out=0.;
double a = 0.;
int sw = 0;
__declspec(dllexport) void simuser(double t, double dt, double *in, double *out)
{
v_tri = in[0];
a = 0.7;
if (v_tri > a)
sw = 1;
else
sw = 0;
out[0] = sw;
out[1] = a;
}
*/
Explanation / Answer
#include
#define pi 3.141592653589
#define T_samp 100.e-6
//variable declaration
double f = 0.;
double T_cnt = 0.;
double L_f = 0., R_f = 0.;
double wc_i = 0.;
//12 IGBT's used require for npc inverter. So here initializing their reference voltages.
double theta = 0.;
double v_a_ref = 0.;
double v_b_ref = 0.;
double v_c_ref = 0.;
double v_de_ref = 0.;
double v_qe_ref = 0.;
double v_ds_ref = 0.;
double v_qs_ref = 0.;
double v_a_ref_scale = 0.;
double v_b_ref_scale = 0.;
double v_c_ref_scale = 0.;
double dc_link = 0.;
//initializing corresponding currents.
double car = 0. , car_u=0. , car_d =0.;
double i_a_in = 0.;
double i_b_in = 0.;
double i_c_in = 0.;
double i_de_in_ref = 0. , i_qe_in_ref=0.;
double i_ds_in = 0., i_qs_in = 0.;
double i_de_in = 0., i_qe_in = 0.;
double p_gain_i = 0., i_gain_i = 0.;
double i_de_in_err = 0., i_qe_in_err = 0.;
double i_de_err_int = 0., i_qe_err_int = 0.;
//initializing corresponding switches
double sa1 = 0., sa2 = 0., sa3 = 0., sa4 = 0.;
double sb1 = 0., sb2 = 0., sb3 = 0., sb4 = 0.;
double sc1 = 0., sc2 = 0., sc3 = 0., sc4 = 0.;
double zeta = 0.7, wn = 200.;
double Va = 0., Vb = 0., Vc = 0.;
double V_in_AB = 0., V_in_BC = 0., V_in_CA = 0.;
double wc = 0.;
double Vds = 0., Vqs = 0., Vde =0.,Vqe=0.;
double Vm = 0., Ts=0.;
double La = 0., Lb = 0.,we=0.;
double Vde_err = 0., Vde_ref = 0., Vde_err_int=0., Vde_err_in=0.;
double Kp = 0., Ki = 0., wrate=0.;
double Y_old = 0., X_old = 0., Y = 0., Yde=0.;
// This function will take all the parametric values requires to calculate different parameters including voltage ,current by applying conditional approches as per the dependence on other parameters i.e theta, T etc.
__declspec(dllexport) void simuser(double t, double dt, double *in, double *out)
{
//increase T_cnt
T_cnt += dt;
//input variable setting
car = in[0];
i_a_in = in[1];
i_b_in = in[2];
i_c_in = in[3];
dc_link = in[4];
V_in_AB = in[5];
V_in_BC = in[6];
V_in_CA = in[7];
//current controll constant
if (t < 0.2)
{
i_de_in_ref = 0., i_qe_in_ref = 5.;
}
else if (t < 0.3)
{
i_de_in_ref = 0., i_qe_in_ref = 10.;
}
else
{
i_de_in_ref = 0., i_qe_in_ref = 5.;
}
//T_cnt increase by dt and It works if it is bigger than T_samp
//then, T_cnt reset
if (T_cnt >= T_samp)
{
//line voltage -> phase voltage
Va = (V_in_AB - V_in_CA)*0.33333333;
Vb = (V_in_BC - V_in_AB)*0.33333333;
Vc = -(Va + Vb);
wc = 1. + 2. + zeta + wn;
Vds = (2.*Va - Vb - Vc) / 3.;
Vqs = (Vb - Vc) / sqrt(3.);
Vde = Vds*cos(theta) + Vqs*sin(theta);
Vqe = -Vds*sin(theta) + Vqs * cos(theta);
Vm = sqrt(Vds*Vds + Vqs*Vqs);
/*
La = (2. - wc*T_samp) / (2. + wc*T_samp);
Lb = (wc*T_samp) / (2. + wc*T_samp);
Y = (La * Y_old) + Lb * (Vde + X_old);
Y_old = Y;
X_old = Yde;
*/
Vde_err = Vde_ref - Vde;
Vde_err_int += Vde_err * T_samp;
Kp = 2. * zeta * wn / (Vm + 0.000000001);
Ki = (wn*wn) / ((Vm + 0.000000001)*wc);
f = 60.;
wrate = 2. * pi * f;
we = Vde_err * Kp + Vde_err_in * Ki + wrate;
//thetae += we*T_samps; //Synchronous Reference Frame frequency
theta += we*T_samp;
if (theta > pi) { theta -= 2.*pi; }
else if (theta < -pi) { theta += 2.*pi; }
/*
theta += 2.* pi*f*T_samp;
if (theta < 0.)
{
theta += 2.*pi;
}
if (theta > 2*pi)
{
theta -= 2.*pi;
}
*/
//transform to d and q axis variables
i_ds_in = (2.*i_a_in - i_b_in - i_c_in) / 3.;
i_qs_in = (1. / sqrt(3.))*(i_b_in - i_c_in);
//transform to Rotating Reference Frame d-q axis variable
i_de_in = i_ds_in * cos(theta) + i_qs_in * sin(theta);
i_qe_in = -i_ds_in * sin(theta) + i_qs_in * cos(theta);
L_f = 0.002;
R_f = 0.1;
wc_i = 1000.;
p_gain_i = L_f * wc_i;
i_gain_i = R_f * wc_i;
i_de_in_err = i_de_in_ref - i_de_in;
i_qe_in_err = i_qe_in_ref - i_qe_in;
i_de_err_int += i_de_in_err * T_samp;
i_qe_err_int += i_qe_in_err * T_samp;
//Rotating Reference Frame
v_de_ref = p_gain_i * i_de_in_err + i_gain_i * i_de_err_int;
v_qe_ref = p_gain_i * i_qe_in_err + i_gain_i * i_qe_err_int;
//v_de_ref = 0.;
//v_qe_ref = 150.; //The current magnitude changes. By this value-> currnet control(open loop)
//Stationary Reference Frame
v_ds_ref = v_de_ref * cos(theta) - v_qe_ref * sin(theta); //inverse transform using theta
v_qs_ref = v_de_ref * sin(theta) + v_qe_ref * cos(theta);
//3phases
v_a_ref = v_ds_ref;//Change to 3 phases again
v_b_ref = (-1.* v_ds_ref + sqrt(3.)*v_qs_ref) / 2;
v_c_ref = (-1.* v_ds_ref - sqrt(3.)*v_qs_ref) / 2;
v_a_ref_scale = (v_a_ref / dc_link) + 0.5;
v_b_ref_scale = (v_b_ref / dc_link) + 0.5;
v_c_ref_scale = (v_c_ref / dc_link) + 0.5;
//T_cnt reset
T_cnt -= T_samp;
}
//Set output value compared with triangle wave
if (v_a_ref_scale > car) // Switches are used conditinally for different conditions.
{
sa1 = 1, sa2 = 1, sa3 = 0, sa4 = 0;
}
else
{
sa1 = 0, sa2 = 0, sa3 = 1, sa4 = 1;
}
if (v_b_ref_scale > car) //
{
sb1 = 1, sb2 = 1, sb3 = 0, sb4 = 0;
}
else
{
sb1 = 0, sb2 = 0, sb3 = 1, sb4 = 1;
}
if (v_c_ref_scale > car)
{
sc1 = 1, sc2 = 1, sc3 = 0, sc4 = 0;
}
else
{
sc1 = 0, sc2 = 0, sc3 = 1, sc4 = 1;
}
// Displys Complete Output value used above.
//output
out[0] = Vm;//magnitude
out[1] = we;//frequency
out[2] = theta;//phase
out[3] = Va;
out[4] = Vb;
out[5] = Vc;
out[6] = Vde;
out[7] = Vqe;
out[8] = v_a_ref;
out[9] = v_b_ref;
out[10] = v_c_ref;
out[11] = i_qe_in;
out[12] = i_qe_in_ref;
out[13] = sa1;
out[14] = sa2;
out[15] = sa3;
out[16] = sa4;
out[17] = sb1;
out[18] = sb2;
out[19] = sb3;
out[20] = sb4;
out[21] = sc1;
out[22] = sc2;
out[23] = sc3;
out[24] = sc4;
}
/*
#include
double Carrier = 0.;
double Duty_ref = 0.;
double Gate_signal = 0.;
//Function to perform condtional gate signal output based on carrier.
__declspec(dllexport) void simuser(double t, double dt, double *in, double *out)
{
Carrier = in[0];
Duty_ref = in[1];
if (Carrier >- Duty_ref)
Gate_signal = 0;
if (Carrier < Duty_ref)
Gate_signal = 1;
out[0] = Gate_signal;
}
double v_tri=0.;
double v_out=0.;
double a = 0.;
int sw = 0;
// Switching outputs
__declspec(dllexport) void simuser(double t, double dt, double *in, double *out)
{
v_tri = in[0];
a = 0.7;
if (v_tri > a)
sw = 1;
else
sw = 0;
out[0] = sw;
out[1] = a;
}
Related Questions
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.