Source code for soft4pes.control.lin.lcl_conv_curr_ctr

"""
Current Controller (CC) for the control of the converter current with LC(L) filter.

[Ref.]. V. Pirsto, J. Kukkola and M. Hinkkanen, "Multifunctional Cascade Control of Voltage-Source 
Converters Equipped With an LC Filter," IEEE Trans. Ind. Electron., vol. 69, no. 3, 
pp. 2610-2620, March 2022.
"""

from types import SimpleNamespace
import numpy as np
from soft4pes.utils import alpha_beta_2_dq, dq_2_alpha_beta
from soft4pes.control.common.controller import Controller
from soft4pes.control.common.utils import get_modulating_signal, magnitude_limiter


[docs]class LCLConvCurrCtr(Controller): """ Current Controller for converter current with an LC(L) filter. Parameters ---------- sys : object System model containing electrical parameters and base values. Attributes ---------- u_ii_comp : complex Integrator state for the converter voltage reference in the dq-frame. v_conv_kp1_comp : complex Next converter voltage reference in the dq-frame. u_km1_abc : ndarray (3,) Previous converter voltage reference in the abc-frame. sys : object System model containing electrical parameters and base values. ctr_pars : SimpleNamespace Controller parameters including delta, K_i, k_ii, and K_ti. """ def __init__(self, sys): super().__init__()
[docs] self.u_ii_comp = complex(0, 0)
[docs] self.v_conv_kp1_comp = complex(0, 0)
[docs] self.u_km1_abc = np.array([0, 0, 0])
[docs] self.sys = sys
[docs] self.ctr_pars = None
[docs] def set_sampling_interval(self, Ts): """ Set the sampling interval and compute controller parameters. Parameters ---------- Ts : float Sampling interval [s]. """ self.Ts = Ts Ts_pu = self.Ts * self.sys.base.w # Closed-loop controller bandwidth (10x crossover frequency) alpha_c = 2 * np.pi / 10 / Ts_pu # The closed-loop pole locations p_1 = 0 p_2 = np.exp(-alpha_c * Ts_pu) p_3 = p_2 # Consider delta due to considering delay delta = np.exp(-self.sys.par.wg * Ts_pu * 1j) # Coefficients phi = np.exp((-self.sys.par.R_fc / self.sys.par.X_fc) * Ts_pu) * delta gamma = (delta - phi) / self.sys.par.R_fc k_2 = -p_1 - p_2 - p_3 + phi + 1 k_1 = (p_1 * p_2 + p_1 * p_3 + p_2 * p_3 + k_2 * phi + k_2 - phi) / gamma K_i = np.array([k_1, 0, k_2]) # Integral gain k_ii = (-p_1 * p_2 * p_3 + k_1 * gamma - k_2 * phi) / gamma # Feedforward gain k_ti = k_ii / (1 - p_3) self.ctr_pars = SimpleNamespace(delta=delta, K_i=K_i, k_ii=k_ii, k_ti=k_ti)
[docs] def execute(self, sys, kTs): """ Execute the Current Controller (CC) and save the controller data. Parameters ---------- sys : object System model. kTs : float Current discrete time instant [s]. Returns ------- 1 x 3 ndarray of floats Three-phase modulating signal. """ vg = sys.get_grid_voltage(kTs) # Get the grid-voltage angle theta = np.arctan2(vg[1], vg[0]) # Get the reference for current step i_conv_ref_comp = complex(*self.input.i_conv_ref_dq) # Get the converter current in dq-frame i_conv_comp = complex(*alpha_beta_2_dq(sys.i_conv, theta)) # Get the capacitor voltage in dq-frame vc_comp = complex(*alpha_beta_2_dq(sys.vc, theta)) # Get the converter voltage v_conv_comp = self.v_conv_kp1_comp * self.ctr_pars.delta x_LC = np.array([i_conv_comp, vc_comp, v_conv_comp]) v_conv_ref_unlim_comp = (self.ctr_pars.k_ti * i_conv_ref_comp) - np.dot( self.ctr_pars.K_i, x_LC) + self.u_ii_comp # Limiting the converter voltage reference v_conv_ref_comp = magnitude_limiter(v_conv_ref_unlim_comp, sys.conv.v_dc / 2) self.v_conv_kp1_comp = v_conv_ref_comp self.u_ii_comp += self.ctr_pars.k_ii * ( ((v_conv_ref_comp - v_conv_ref_unlim_comp) / self.ctr_pars.k_ti) + (i_conv_ref_comp - i_conv_comp)) # Get the modulating signal and Hold it for one cycle before sending it out from the # controller u_abc = self.u_km1_abc v_conv_ref_dq = np.array([v_conv_ref_comp.real, v_conv_ref_comp.imag]) v_conv_ref = dq_2_alpha_beta(v_conv_ref_dq, theta) self.u_km1_abc = get_modulating_signal(v_conv_ref, sys.conv.v_dc) self.output = SimpleNamespace(u_abc=u_abc) return self.output