2.2-kW IPMSM, dual-voltage-forming AFE, CVC

2.2-kW IPMSM, dual-voltage-forming AFE, CVC#

This example simulates a 2.2-kW interior permanent-magnet synchronous machine (IPMSM) drive whose active front end (AFE) uses dual-voltage-forming control [1] and is connected to a weak grid. The grid-side converter regulates both the DC-bus voltage and its output voltage magnitude without a cascaded DC-bus voltage controller: the external power fed to the DC bus by the drive is estimated by a disturbance observer and fed forward. The machine-side converter uses sensorless current-vector control (CVC). The two control systems are independent: they have different sampling periods, and their carriers are not synchronized. The system model is otherwise the same as in 2.2-kW IPMSM, active front end, CVC, except for the weak grid.

from math import pi

import matplotlib.pyplot as plt

import motulator.drive.control.sm as sm_control
from motulator.drive import model as drive_model
from motulator.drive import utils as drive_utils
from motulator.grid import control as grid_control
from motulator.grid import model as grid_model
from motulator.grid import utils as grid_utils

Compute base values based on the nominal values of the machine and the grid converter.

Configure the system model. The two converters are fed from the same DC bus. The grid is weak: its inductance is 0.74 p.u.

Configure the control systems. The grid-side control runs at 10 kHz (5-kHz switching frequency) and the machine-side control at 8 kHz (4-kHz switching frequency). The gains of the dual-voltage-forming controller are given in per-unit values of the grid converter [1].

cfg_g = grid_control.DualVoltageFormingControllerCfg(
    i_max=1.5 * base_g.i,
    L=0.3 * base_g.L,
    C_dc=470e-6,
    R=0.05 * base_g.Z,
    k_d=base_g.u / base_g.p,
    alpha_dc=0.15 * base_g.w,
    alpha_o=2 * base_g.w,
    alpha_o_dc=1.2 * base_g.w,
    k_v=6,
    alpha_c=6 * base_g.w,
    u_nom=base_g.u,
    w_nom=base_g.w,
    T_s=100e-6,
)
ctrl_g = grid_control.GridConverterControlSystem(
    grid_control.DualVoltageFormingController(cfg_g)
)

est_par = par  # Assume accurate model parameter estimates
cfg_m = sm_control.CurrentVectorControllerCfg(
    i_s_max=1.5 * base_m.i, alpha_o=2 * pi * 100, T_s=125e-6
)
vector_ctrl = sm_control.CurrentVectorController(est_par, cfg_m)
speed_ctrl = sm_control.SpeedController(J=0.015, alpha_s=2 * pi * 4)
ctrl_m = sm_control.VectorControlSystem(vector_ctrl, speed_ctrl)

Set the references and the external load torque. The speed is reversed under load, after which the drive regenerates power to the grid.

ctrl_g.set_dc_bus_voltage_ref(650)
ctrl_g.set_ac_voltage_ref(base_g.u)
ctrl_m.set_speed_ref(lambda t: (t > 0.1) * base_m.w_M - (t > 0.7) * 2 * base_m.w_M)
mechanics.set_external_load_torque(lambda t: (t > 0.4) * nom_m.tau)

Create the simulation object and simulate. The clocks of the two control systems are not synchronized: the machine-side control starts 40 µs after the grid-side control. The results of each model and its control system are available by the model names.

Plot the drive and grid-side results in per-unit values. The active power reference shown is the equivalent reference formed by the dual-voltage-forming controller from the estimated external power and the DC-bus energy error.

  • plot 2kw ipmsm afe dvf cvc
  • plot 2kw ipmsm afe dvf cvc

Plot the DC-bus voltage and the power balance: the estimated external power fed to the DC bus (the estimated disturbance power plus the grid power and the resistive losses of the filter) follows the mechanical power plus the losses (mainly the stator resistive losses), and the power drawn from the grid follows it with the delay of the current dynamics in the weak grid.

ctrl_ts = res.ctrl.grid
p_loss = 1.5 * cfg_g.R * abs(ctrl_ts.fbk.i_c) ** 2
p_ext = ctrl_ts.fbk.p_dis + ctrl_ts.fbk.p_g + p_loss
p_M = res.mdl.drive.machine.tau_M * res.mdl.drive.machine.w_M
fig, (ax1, ax2) = plt.subplots(2, 1, sharex=True)
ax1.plot(res.mdl.t, res.mdl.drive.dc_bus.u_dc, label=r"$u_\mathrm{dc}$")
ax1.plot(
    ctrl_ts.t,
    ctrl_ts.ref.u_dc,
    "--",
    ds="steps-post",
    label=r"$u_\mathrm{dc}^\mathrm{ref}$",
)
ax1.set_ylabel("Voltage (V)")
ax1.legend()
ax2.plot(ctrl_ts.t, -p_ext / 1e3, ds="steps-post", label=r"$-\hat{p}_\mathrm{ext}$")
ax2.plot(
    ctrl_ts.t, -ctrl_ts.fbk.p_g / 1e3, ds="steps-post", label=r"$-\hat{p}_\mathrm{g}$"
)
ax2.plot(res.mdl.t, p_M / 1e3, label=r"$\tau_\mathrm{M}\omega_\mathrm{M}$")
ax2.set_ylabel("Power (kW)")
ax2.set_xlabel("Time (s)")
ax2.legend()
plt.show()
plot 2kw ipmsm afe dvf cvc

Plot the grid-side waveforms around the load torque step. The converter current increases within a few milliseconds, as the estimated external power is fed forward.

grid_utils.plot_grid_waveforms(
    res_grid, base_g, t_lims=(0.39, 0.45), plot_pcc_voltage=False
)
plot 2kw ipmsm afe dvf cvc

References

Total running time of the script: (0 minutes 21.239 seconds)

Gallery generated by Sphinx-Gallery