Bernard A.
Bernard A.

Reputation: 1

Simulation time increases considerably on implementing discrete PI controller

I have developed a dynamic phasor model of a grid-connected single phase inverter. Running the open loop model of the simulation (with modulation index and initial angle constant) for a duration of 0.3 seconds with a step-size of 1e-05 takes about 45 seconds. However, implementing a discrete PI controller with sampling rate of 1e-4 leads to a simulation duration of about 30 minutes. My suspicion is the sample function in my PI code. Would be glad if anyone could help with identifying the cause and a possible workaround. The controller code is below. Thanks in advance.

model LinearController_DQ_InverterSP
 // reference currents
 parameter Real Id_ref[3] = {0.0, 10.0, 20.0}; 
 parameter Real Iq_ref[3] = {0.0, 5.0, 10.0};
 //step times
 parameter Real step_times[2] = {0.08, 0.12};
 // current reference currents
 Real Id_ref_curr;
 Real Iq_ref_curr;

 parameter Real Kp_cc = 0.0541 "Proportional term of controller";
 parameter Real Ki_cc = 55.577 "Integral term of controller";
 parameter Real T_sample = 1e-4 "Sampling period";
 
 // previous time step terms
 Real ud_prev(start = 0.0, fixed = true);
 Real uq_prev(start = 0.0, fixed = true);
 Real ed_prev(start = 0.0, fixed = true);
 Real eq_prev(start = 0.0, fixed = true);
 Real Vd_pcc_prev(start = 220*sqrt(2), fixed = true);
 Real Vq_pcc_prev(start = 0.0, fixed = true);
 
 // current time step terms
 Real ud_curr, uq_curr;
 Real ed_curr, eq_curr;
 Real Vin_d, Vin_q;

 Real a_const =  Kp_cc + Ki_cc * T_sample / 2;
 Real b_const = -Kp_cc + Ki_cc * T_sample / 2;
 
 Modelica.Blocks.Interfaces.RealOutput Mr(start = 0.87, fixed=true);  // modulation index
 Modelica.Blocks.Interfaces.RealOutput th(start=0.0, fixed=true) ; // angle
 Modelica.Blocks.Interfaces.RealInput Id ; // measured Id current 
 Modelica.Blocks.Interfaces.RealInput Iq ; // measure Iq current
 Modelica.Blocks.Interfaces.RealInput Vd_pcc ; // Vd of measured grid voltage
 Modelica.Blocks.Interfaces.RealInput Vq_pcc ; // Vq of measured grid voltage 


algorithm
   
   if time < step_times[1] then
     Id_ref_curr := Id_ref[1];
     Iq_ref_curr := Iq_ref[1];
   elseif (time > step_times[1]) and (time < step_times[2]) then
     Id_ref_curr := Id_ref[2];
     Iq_ref_curr := Iq_ref[2];
   else
     Id_ref_curr := Id_ref[3];
     Iq_ref_curr := Iq_ref[3];
   end if;
   
   when sample(0, T_sample) then
     //Calc error
       ed_curr := Id_ref_curr - Id;
       eq_curr := Iq_ref_curr - Iq;
     
    //Calc pid controller output
       ud_curr := ud_prev + a_const * ed_curr + b_const * ed_prev;
       uq_curr := uq_prev + a_const * eq_curr + b_const * eq_prev;
     
     //Apply feedforward term
       Vin_d := (Vd_pcc_prev + ud_prev);
       Vin_q := (Vq_pcc_prev + uq_prev);
     
     //Compute control signals
       th := atan(Vin_q / Vin_d);
       Mr := sqrt(Vin_d^2 + Vin_q^2) / 360;
     
     // Update values
       Vd_pcc_prev := Vd_pcc;
       Vq_pcc_prev := Vq_pcc;
       ed_prev := ed_curr;
       eq_prev := eq_curr;
       ud_prev := ud_curr;
       uq_prev := uq_curr;
   end when;

end LinearController_DQ_InverterSP;

Upvotes: 0

Views: 129

Answers (2)

Markus A.
Markus A.

Reputation: 7525

Did you take a look at the step-size of the integrator and how it changes between the two scenarios? Usually, sampling (or any kind of discretization) forces the solver to take smaller steps by causing events. So e.g. enlarging the step-size from 1e-4s to 1e-3s should increase the performance by about a factor of 10.

Some references regarding this:

Without having a closer look at the example (it doesn't work just by copy/paste), this would should be the explanation for your suspicion.

Upvotes: 1

Hans Olsson
Hans Olsson

Reputation: 12507

One issue is that you are trying to do the Modelica translator's job, by manually handling the previous variables, and writing the assignments in order in an algorithm.

The normal equation-oriented way would be:

model LinearController_DQ_InverterSP
 // reference currents
 parameter Real Id_ref[3] = {0.0, 10.0, 20.0};
 parameter Real Iq_ref[3] = {0.0, 5.0, 10.0};
 //step times
 parameter Real step_times[2] = {0.08, 0.12};
 // current reference currents
 Real Id_ref_curr;
 Real Iq_ref_curr;

 parameter Real Kp_cc = 0.0541 "Proportional term of controller";
 parameter Real Ki_cc = 55.577 "Integral term of controller";
 parameter Real T_sample = 1e-4 "Sampling period";


 // current time step terms
 Real ud_curr(start=0, fixed=true), uq_curr(start=0, fixed=true);
 Real ed_curr(start=0, fixed=true), eq_curr(start=0, fixed=true);
 Real Vin_d, Vin_q;

 Real a_const =  Kp_cc + Ki_cc * T_sample / 2;
 Real b_const = -Kp_cc + Ki_cc * T_sample / 2;

 Modelica.Blocks.Interfaces.RealOutput Mr(start = 0.87, fixed=true);  // modulation index
 Modelica.Blocks.Interfaces.RealOutput th(start=0.0, fixed=true);  // angle
 Modelica.Blocks.Interfaces.RealInput Id;  // measured Id current 
 Modelica.Blocks.Interfaces.RealInput Iq;  // measure Iq current
 Modelica.Blocks.Interfaces.RealInput Vd_pcc(start = 220*sqrt(2), fixed = true);  // Vd of measured grid voltage
 Modelica.Blocks.Interfaces.RealInput Vq_pcc(start = 0.0, fixed = true);  // Vq of measured grid voltage 


equation 

   if time < step_times[1] then
     Id_ref_curr =  Id_ref[1];
     Iq_ref_curr =  Iq_ref[1];
   elseif (time > step_times[1]) and (time < step_times[2]) then
     Id_ref_curr =  Id_ref[2];
     Iq_ref_curr =  Iq_ref[2];
   else
     Id_ref_curr =  Id_ref[3];
     Iq_ref_curr =  Iq_ref[3];
   end if;

   when sample(0, T_sample) then
     //Calc error
       ed_curr =  Id_ref_curr - Id;
       eq_curr =  Iq_ref_curr - Iq;

    //Calc pid controller output
       ud_curr =  pre(ud_curr) + a_const * ed_curr + b_const * pre(ed_curr);
       uq_curr =  pre(uq_curr) + a_const * eq_curr + b_const * pre(eq_curr);

     //Apply feedforward term
       Vin_d =  (pre(Vd_pcc) + pre(ud_curr));
       Vin_q =  (pre(Vq_pcc) + pre(uq_curr));

     //Compute control signals
       th =  atan(Vin_q / Vin_d);
       Mr =  sqrt(Vin_d^2 + Vin_q^2) / 360;
   end when;

end LinearController_DQ_InverterSP;

I haven't checked if there are odd interactions in terms of how the algorithm interacts with the assignments - but at least it is avoided in this variant.

Upvotes: 1

Related Questions