Modular Inverter Framework
This section describes the modular inverter framework developed in the MARiE-Project funded by the German Federal Ministry for Economic Affairs and Climate Action.
Structure
The inverter model is split in two parts: the inner loop and the outer loop.
The inner loop either acts as a voltage source
+---------+
u_d_ref -->| |
u_q_ref -->| Voltage |--> u_d
i_d_dis -->| Source |--> u_q
i_q_dis -->| |
+---------+
which gets a dq
voltage reference and tries to achive this reference despite the dq
current disturbance.
Alternatively, the inner loop can mimic a current source, which tries to realsize a given current setpoint despite a disturbance voltage at the output terminals:
+---------+
i_d_ref -->| |
i_q_ref -->| Current |--> i_d
u_d_dis -->| Source |--> i_q
u_q_dis -->| |
+---------+
The outer loop provides references to the inner loop blocks. As an input, outerloops have acces to the measured currents and voltages at the point of common coupling. They either eject a dq-reference for the inner voltage source or the inner current soruce:
+---------+
i_d_meas -->| |
i_q_meas -->| Outer |--> u_d_ref or i_d_ref
u_d_meas -->| Loop |--> u_q_ref or i_q_ref
u_q_meas -->| |
+---------+
PowerDynamics.jl
provides predefined outer loop as well as inner loop models as IOBlocks
provide by BlockSystems.jl
, which can be used to create IONodes
(see Custom-Nodes-using-BlockSystems.jl).
Example
In order to construct a modular inverter we need to import the ModularInverter
module to the namespace:
using PowerDynamics
using BlockSystems
using PowerDynamics.ModularInverter
First, we need to define the inner loop as an IOBlock
object. You can either use your own or make use of the Predefined Inner Loops.
inner = CascadedVoltageControl()
IOBlock :VCFOM with 24 eqs
├ inputs: i_r(t), i_i(t), u_ref_r(t), u_ref_i(t)
├ outputs: u_r(t), u_i(t)
├ istates: LC₊i_f_r(t), LC₊i_f_i(t), …19…,VC₊γ_i(t)
└ iparams: (empty)
As you can see, the input/output structure of that innerloop adheres to the volten source innerloop convention.
Next you define the outer loop, either create you own based on the interface or pick from the Predefined Outer Loops.
outer = DroopControl()
IOBlock :droop with 5 eqs
├ inputs: u_meas_i(t), u_meas_r(t), i_meas_i(t), i_meas_r(t)
├ outputs: u_ref_r(t), u_ref_i(t)
├ istates: P_fil(t), Q_fil(t), δ(t)
└ iparams: τ_P, τ_Q, …5…,K_Q
There are still a lot of open parameters, we need to assign specific values to create the IONode
(@ref) later. We can do so by using the keyword aguments of the constructor:
outer = DroopControl(;
ω_ref = 2π*50, # frequency reference
V_ref = 1, # voltage reference (pu)
P_ref = 1, # active power reference (pu)
Q_ref = 0, # reactive power reference (pu)
K_P = 0.4, # active droop gain
K_Q = 0.004, # reactive droop gain
τ_P = 0.1, # active power filter constant
τ_Q = 0.1, # reactive power filter constant
)
IOBlock :droop with 5 eqs
├ inputs: u_meas_i(t), u_meas_r(t), i_meas_i(t), i_meas_r(t)
├ outputs: u_ref_r(t), u_ref_i(t)
├ istates: P_fil(t), Q_fil(t), δ(t)
└ iparams: (empty)
The full inverter model is created by combining outer and inner model:
inv = Inverter(inner, outer)
IOBlock :droop_VCFOM with 27 eqs
├ inputs: i_r(t), i_i(t)
├ outputs: u_r(t), u_i(t)
├ istates: P_fil(t), Q_fil(t), …22…,VC₊γ_i(t)
└ iparams: (empty)
Which satisfies the interface for IONodes
. To create the node
node = IONode(inv);
Which is a valid node definition which can be used in any PowerDynamics.jl
context.
Model Reduction
PowerDynamics.jl
also implements automated model order reduction of linear models using the balance residualization technique. Internaly, we make use of the method implementaion in ControlSystems.jl
. For that, a linear block (such as the cascaded inner loops) can be decomposed in to its A
, B
, C
and D
matrix for regular LTI representation.
For example, we could creat a 10th order representation of the previously defined inner loop by calling
reduced_inner = balresid(inner, 10; reconstruct=false)
IOBlock :VCFOM_trunc_10 with 12 eqs
├ inputs: i_r(t), i_i(t), u_ref_r(t), u_ref_i(t)
├ outputs: u_r(t), u_i(t)
├ istates: z₁(t), z₂(t), …7…,z₁₀(t)
└ iparams: (empty)
To obtain the reduced order model we can construct the inverter again:
reduced_inverter = Inverter(reduced_inner, outer)
IOBlock :droop_VCFOM_trunc_10 with 15 eqs
├ inputs: i_r(t), i_i(t)
├ outputs: u_r(t), u_i(t)
├ istates: P_fil(t), Q_fil(t), …10…,z₁₀(t)
└ iparams: (empty)
... and the reduced node
reduced_node = IONode(reduced_inverter);
PowerDynamics.ModularInverter.balresid
— Functionbalresid(blk::IOBlock, order; warn=BlockSystems.WARN[], verbose=false, reconstruct=false)
This function creates a model reduced version of blk
of given order using the balanced residualization method. Only works for linear systems. Internaly, it uses the baltrunc
function from ControlSystems.jl
to apply the method to an LTI. The LTI system matrices A,B,C and D are determined symbolicially from the IOBlock
object.
If reconstruct=true
the resulting system will include removed_eqs
to reconstruct the original states from the projected states z_i
.
Predefined Inner Loops
PowerDynamics.ModularInverter.CascadedVoltageControl
— FunctionCascadedVoltageControl(;pr=true, ff=true)
Cascaded voltage controler over a LC filter, which controlls the output voltage using 2 levels of cascaded dq controllers.
PowerDynamics.ModularInverter.CascadedVoltageControlCS
— FunctionCascadedVoltageControlCS(;pr=true, ff=true)
Cascaded voltage controler over a LCL filter, which controlls the filter voltage using 2 levels of cascaded dq controllers.
Acts as a current source because of the second L in the filter.
PowerDynamics.ModularInverter.CascadedCurrentControl
— FunctionCascadedCurrentControl(;pr=true)
Cascaded current controler over a LCL filter, which controlls the output current using 3 levels of cascaded dq controllers.
PowerDynamics.ModularInverter.PT1Source
— FunctionPT1Source(; params...)
Create Voltage source which follows angle directly but amplitude with a PT1-lag.
PowerDynamics.ModularInverter.IdealSource
— FunctionIdealSource()
Ideal voltage source which follows the reference directly.
PowerDynamics.ModularInverter.IdealCSource
— FunctionIdealCSource()
Ideal current source which follows the reference directly.
Predefined Outer Loops
PowerDynamics.ModularInverter.FixedVoltage
— FunctionFixedVoltage(; params...)
Outer loop control for a voltage source which tries to keep voltage constant (slack like behavior).
u_d_fix, u_i_fix
v
+-------------------+
| |
| u_r_ref = u_d_fix |--> u_r_ref
| u_i_ref = u_i_fix |--> u_i_ref
| |
+-------------------+
PowerDynamics.ModularInverter.DroopControl
— FunctionDroopControl(; params...)
Return block for droop control outer control.
ω_ref, V_ref, P_ref, Q_ref, K_P, K_Q, τ_P, τ_Q
v
+-----------------------------------------------------+
| P_meas = u_meas_r*i_meas_r + i_meas_i*u_meas_i |
i_r_meas -->| Q_meas = -u_meas_r*i_meas_i + i_meas_r*u_meas_i |
i_i_meas -->| d/dt P_fil = (P_meas - P_fil) / τ_P |--> u_r_ref
u_r_meas -->| d/dt Q_fil = (Q_meas - Q_fil) / τ_P |--> u_i_ref
u_i_meas -->| d/dt δ = ω_ref - K_P*(-P_ref + P_fil) |
| V = V_ref - K_Q*(-Q_ref + Q_fil) |
+-----------------------------------------------------+
PowerDynamics.ModularInverter.Synchronverter
— FunctionSynchronverter(; params...)
Synchronverter outer loop control for a voltage controlled converter.
ω0, V_ref, P_ref, Q_ref, Dp, Kq, Kv
v
+---------------------------------------------------------------------+
| V = sqrt(u_meas_r^2 + u_meas_i^2) |
| Q = -sqrt(3/2) * MfIf * (ω0 + ω) |
| * (-sin(θ)*i_meas_r + cos(θ)*i_meas_i) |
i_r_meas -->| Te = sqrt(3/2) * MfIf * (cos(θ)*i_meas_r + sin(θ)*i_meas_i) |
i_i_meas -->| d/dt ω = 1/J * P_ref/ω0 - Dp*ω - Te, |--> u_r_ref
u_r_meas -->| d/dt θ = ω |--> u_i_ref
u_i_meas -->| d/dt MfIf = (Q_ref - Q + Dq*(V_ref - V))/Kv], |
| u_ref_r = sqrt(3/2) * MfIf * (ω0 + ω) * cos(θ) |
| u_ref_i = sqrt(3/2) * MfIf * (ω0 + ω) * sin(θ) |
+---------------------------------------------------------------------+
PowerDynamics.ModularInverter.PLLCurrent
— FunctionPLLCurrent(; params...)
Outer loop control for a current source inverter, which employs a dynamic PLL to estimate the phase and frequency of the voltage at PCC. The single parameter, i_mag_ref
is interpeted as current reference in d
component (pure active power injection with fixed current).
PowerDynamics.ModularInverter.ConstantPower
— FunctionConstantPower(; params...)
Outer loop control for a current source inverter, which measures the voltage at PCC and commands the i_ref_r
and i_ref_i
such that the desired power at PCC is achived.
PowerDynamics.ModularInverter.FiltConstantPower
— FunctionFiltConstantPower(; params...)
Outer loop control for a current source inverter, which measures the voltage at PCC and commands the i_ref_r
and i_ref_i
such that the desired power at PCC is achived. In contrast to the ConstantPower
-outer loop, the current references follow a PT1 behavior with time constant τ.
Inverter Construction
PowerDynamics.ModularInverter.Inverter
— FunctionInverter(inner, outer; name))
Combines an inner and an outer loop to a closed loop model of an voltage-srouce-inverter.
Both inner and outer loops musst be IOBlock
objects adhering to the interface
Inner loop inputs/outputs:
+---------+
u_r_ref -->| |
u_i_ref -->| Voltage |--> u_r
i_r -->| Source |--> u_i
i_i -->| |
+---------+
Outer loop inputs/outputs:
+---------+
i_r_meas -->| |
i_i_meas -->| Outer |--> u_r_ref
u_r_meas -->| Loop |--> u_i_ref
u_i_meas -->| |
+---------+
PowerDynamics.ModularInverter.InverterCS
— FunctionInverterCS(inner, outer; name))
Combines an inner and an outer loop to a closed loop model of an current-source-inverter.
Both inner and outer loops musst be IOBlock
objects adhering to the interface
Inner loop inputs/outputs:
+---------+
i_r_ref -->| |
i_i_ref -->| Current |--> i_r
u_r -->| Source |--> i_i
u_i -->| |
+---------+
Outer loop inputs/outputs:
+---------+
i_r_meas -->| |
i_i_meas -->| Outer |--> i_r_ref
u_r_meas -->| Loop |--> i_i_ref
u_i_meas -->| |
+---------+
This page was generated using Literate.jl.