Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

(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;


}