2.2-kW IPMSM, active front end, CVC

2.2-kW IPMSM, active front end, CVC#

This example simulates a 2.2-kW interior permanent-magnet synchronous machine (IPMSM) drive equipped with an active front end (AFE), i.e., a grid-connected converter that controls the DC-bus voltage. The machine-side converter uses sensorless current-vector control (CVC), and the grid-side converter uses grid-following current-vector control with a DC-bus voltage controller. The two control systems are independent: they have different sampling periods, and their carriers are not synchronized.

from math import pi

import matplotlib.pyplot as plt

import motulator.drive.control.sm as sm_control
from motulator.common.utils import complex2abc
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-side converter system and the drive are modeled separately, each with its own PWM, and combined into a composite model.

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).

cfg_g = grid_control.CurrentVectorControllerCfg(
    i_max=1.5 * base_g.i, L=0.1 * base_g.L, T_s=100e-6
)
dc_bus_voltage_ctrl = grid_control.DCBusVoltageController(
    C_dc=470e-6, alpha_dc=2 * pi * 50, p_max=1.5 * base_g.p
)
ctrl_g = grid_control.GridConverterControlSystem(
    grid_control.CurrentVectorController(cfg_g), dc_bus_voltage_ctrl
)

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_reactive_power_ref(0)
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.

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

Plot the DC-bus voltage and the power balance: the power drawn from the grid (as estimated by the grid-side control) equals the mechanical power plus the losses (mainly the stator resistive losses), except during the DC-bus voltage transients.

p_g = res.ctrl.grid.fbk.p_g
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(
    res.ctrl.grid.t,
    res.ctrl.grid.ref.u_dc,
    "--",
    ds="steps-post",
    label=r"$u_\mathrm{dc}^\mathrm{ref}$",
)
ax1.set_ylabel("Voltage (V)")
ax1.legend()
ax2.plot(res.ctrl.grid.t, -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 cvc

Plot the switched phase-a voltages of the two converters over one millisecond. The switching periods differ, and the switching instants are not aligned.

u_ga = complex2abc(res.mdl.grid.converter.u_c_ab)[0]
u_sa = complex2abc(res.mdl.drive.converter.u_c_ab)[0]
fig, (ax1, ax2) = plt.subplots(2, 1, sharex=True, sharey=True)
ax1.plot(res.mdl.t, u_ga, label=r"$u_\mathrm{ga}$")
ax1.set_ylabel("Voltage (V)")
ax1.legend(loc="lower right")
ax2.plot(res.mdl.t, u_sa, label=r"$u_\mathrm{sa}$")
ax2.set_ylabel("Voltage (V)")
ax2.set_xlabel("Time (s)")
ax2.set_xlim(0.5, 0.501)
ax2.set_ylim(-500, 500)
ax2.legend(loc="lower right")
plt.show()
plot 2kw ipmsm afe cvc

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

Gallery generated by Sphinx-Gallery