
.. DO NOT EDIT.
.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY.
.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE:
.. "drive_examples/current_vector/plot_2kw_ipmsm_afe_cvc.py"
.. LINE NUMBERS ARE GIVEN BELOW.

.. only:: html

    .. note::
        :class: sphx-glr-download-link-note

        :ref:`Go to the end <sphx_glr_download_drive_examples_current_vector_plot_2kw_ipmsm_afe_cvc.py>`
        to download the full example code.

.. rst-class:: sphx-glr-example-title

.. _sphx_glr_drive_examples_current_vector_plot_2kw_ipmsm_afe_cvc.py:


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.

.. GENERATED FROM PYTHON SOURCE LINES 15-27

.. code-block:: Python

    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








.. GENERATED FROM PYTHON SOURCE LINES 28-29

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

.. GENERATED FROM PYTHON SOURCE LINES 29-35

.. code-block:: Python


    nom_m = drive_utils.NominalValues(U=370, I=4.3, f=75, P=2.2e3, tau=14)
    base_m = drive_utils.BaseValues.from_nominal(nom_m, n_p=3)
    nom_g = grid_utils.NominalValues(U=400, I=5, f=50, P=2.2e3)
    base_g = grid_utils.BaseValues.from_nominal(nom_g)








.. GENERATED FROM PYTHON SOURCE LINES 36-39

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.

.. GENERATED FROM PYTHON SOURCE LINES 39-59

.. code-block:: Python


    afe = grid_model.VoltageSourceConverter()
    inv = drive_model.VoltageSourceConverter()
    dc_bus = drive_model.DCBus(C_dc=470e-6, u_dc=650, converters=[afe, inv])

    ac_filter = grid_model.LFilter(L_f=0.1 * base_g.L)
    ac_source = grid_model.ThreePhaseSource(w_g=base_g.w, e_g=base_g.u)
    grid_sys = grid_model.GridConverterSystem(
        afe, ac_filter, ac_source, pwm=True, dc_bus=dc_bus
    )

    par = drive_model.SynchronousMachinePars(
        n_p=3, R_s=3.6, L_d=0.036, L_q=0.051, psi_f=0.545
    )
    machine = drive_model.SynchronousMachine(par)
    mechanics = drive_model.MechanicalSystem(J=0.015)
    drive_sys = drive_model.Drive(machine, mechanics, inv, pwm=True, dc_bus=dc_bus)

    mdl = drive_model.CompositeModel({"grid": grid_sys, "drive": drive_sys})








.. GENERATED FROM PYTHON SOURCE LINES 60-62

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

.. GENERATED FROM PYTHON SOURCE LINES 62-81

.. code-block:: Python


    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)








.. GENERATED FROM PYTHON SOURCE LINES 82-84

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

.. GENERATED FROM PYTHON SOURCE LINES 84-90

.. code-block:: Python


    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)








.. GENERATED FROM PYTHON SOURCE LINES 91-94

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.

.. GENERATED FROM PYTHON SOURCE LINES 94-102

.. code-block:: Python


    sim = drive_model.Simulation(
        mdl, {"grid": ctrl_g, "drive": ctrl_m}, t_start={"drive": 40e-6}
    )
    res = sim.simulate(t_stop=1)
    res_drive = drive_model.SimulationResults(res.mdl.drive, res.ctrl.drive)
    res_grid = grid_model.SimulationResults(res.mdl.grid, res.ctrl.grid)








.. GENERATED FROM PYTHON SOURCE LINES 103-104

Plot the drive and grid-side results in per-unit values.

.. GENERATED FROM PYTHON SOURCE LINES 104-109

.. code-block:: Python


    # sphinx_gallery_thumbnail_number = 3
    drive_utils.plot(res_drive, base_m)
    grid_utils.plot_control_signals(res_grid, base_g)




.. rst-class:: sphx-glr-horizontal


    *

      .. image-sg:: /drive_examples/current_vector/images/sphx_glr_plot_2kw_ipmsm_afe_cvc_001.png
         :alt: plot 2kw ipmsm afe cvc
         :srcset: /drive_examples/current_vector/images/sphx_glr_plot_2kw_ipmsm_afe_cvc_001.png
         :class: sphx-glr-multi-img

    *

      .. image-sg:: /drive_examples/current_vector/images/sphx_glr_plot_2kw_ipmsm_afe_cvc_002.png
         :alt: plot 2kw ipmsm afe cvc
         :srcset: /drive_examples/current_vector/images/sphx_glr_plot_2kw_ipmsm_afe_cvc_002.png
         :class: sphx-glr-multi-img





.. GENERATED FROM PYTHON SOURCE LINES 110-113

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.

.. GENERATED FROM PYTHON SOURCE LINES 113-134

.. code-block:: Python


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




.. image-sg:: /drive_examples/current_vector/images/sphx_glr_plot_2kw_ipmsm_afe_cvc_003.png
   :alt: plot 2kw ipmsm afe cvc
   :srcset: /drive_examples/current_vector/images/sphx_glr_plot_2kw_ipmsm_afe_cvc_003.png
   :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 135-137

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

.. GENERATED FROM PYTHON SOURCE LINES 137-151

.. code-block:: Python


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



.. image-sg:: /drive_examples/current_vector/images/sphx_glr_plot_2kw_ipmsm_afe_cvc_004.png
   :alt: plot 2kw ipmsm afe cvc
   :srcset: /drive_examples/current_vector/images/sphx_glr_plot_2kw_ipmsm_afe_cvc_004.png
   :class: sphx-glr-single-img






.. rst-class:: sphx-glr-timing

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


.. _sphx_glr_download_drive_examples_current_vector_plot_2kw_ipmsm_afe_cvc.py:

.. only:: html

  .. container:: sphx-glr-footer sphx-glr-footer-example

    .. container:: sphx-glr-download sphx-glr-download-jupyter

      :download:`Download Jupyter notebook: plot_2kw_ipmsm_afe_cvc.ipynb <plot_2kw_ipmsm_afe_cvc.ipynb>`

    .. container:: sphx-glr-download sphx-glr-download-python

      :download:`Download Python source code: plot_2kw_ipmsm_afe_cvc.py <plot_2kw_ipmsm_afe_cvc.py>`

    .. container:: sphx-glr-download sphx-glr-download-zip

      :download:`Download zipped: plot_2kw_ipmsm_afe_cvc.zip <plot_2kw_ipmsm_afe_cvc.zip>`


.. only:: html

 .. rst-class:: sphx-glr-signature

    `Gallery generated by Sphinx-Gallery <https://sphinx-gallery.github.io>`_
