6.7-kW SyRM, saturated#

This example simulates observer-based V/Hz control of a saturated 6.7-kW synchronous reluctance motor drive. The saturation is not taken into account in the control method (only in the system model).

import numpy as np
from motulator.drive import model
import motulator.drive.control.sm as control
from motulator.drive.utils import (
    BaseValues, NominalValues, plot, Sequence, SynchronousMachinePars)

Compute base values based on the nominal values (just for figures).

nom = NominalValues(U=370, I=15.5, f=105.8, P=6.7e3, tau=20.1)
base = BaseValues.from_nominal(nom, n_p=2)

A saturation model is created based on [1], [2]. For simplicity, the saturation model parameters are hard-coded in function below, but the same model structure can also be used for other synchronous motors. For PM motors, the magnetomotive force (MMF) of the PMs can be modeled using constant current source i_f on the d-axis [2], [3]. Correspondingly, this approach assumes that the MMFs of the d-axis current and of the PMs are in series. This model cannot capture the desaturation phenomenon of thin iron ribs, see [4] for details. For such motors, look-up tables can be used.

def i_s(psi_s):
    """
    Magnetic model for a 6.7-kW synchronous reluctance motor.

    Parameters
    ----------
    psi_s : complex
        Stator flux linkage (Vs).

    Returns
    -------
    complex
        Stator current (A).

    Notes
    -----
    For nonzero `i_f`, the initial value of the stator flux linkage `psi_s0`
    needs to be solved, e.g., as follows::

    from scipy.optimize import minimize_scalar
    res = minimize_scalar(
        lambda psi_d: np.abs(
                    (a_d0 + a_dd*np.abs(psi_d)**S)*psi_d - i_f))
    psi_s0 = complex(res.x)

    """
    # Parameters
    a_d0, a_dd, S = 17.4, 373., 5  # d-axis self-saturation
    a_q0, a_qq, T = 52.1, 658., 1  # q-axis self-saturation
    a_dq, U, V = 1120., 1, 0  # Cross-saturation
    i_f = 0  # MMF of PMs
    # Inverse inductance functions
    G_d = a_d0 + a_dd*np.abs(psi_s.real)**S + (
        a_dq/(V + 2)*np.abs(psi_s.real)**U*np.abs(psi_s.imag)**(V + 2))
    G_q = a_q0 + a_qq*np.abs(psi_s.imag)**T + (
        a_dq/(U + 2)*np.abs(psi_s.real)**(U + 2)*np.abs(psi_s.imag)**V)
    # Stator current
    return G_d*psi_s.real - i_f + 1j*G_q*psi_s.imag

Configure the system model.

mdl_par = SynchronousMachinePars(n_p=2, R_s=.54)
machine = model.SynchronousMachine(mdl_par, i_s=i_s, psi_s0=0)
# Magnetically linear SyRM model for comparison
# mdl_par = SynchronousMachinePars(
#     n_p=2, R_s=.54, L_d=37e-3, L_q=6.2e-3, psi_f=0)
# machine = model.SynchronousMachine(mdl_par)
mechanics = model.StiffMechanicalSystem(J=.015)
converter = model.Inverter(u_dc=540)
mdl = model.Drive(converter, machine, mechanics)

Configure the control system.

par = SynchronousMachinePars(n_p=2, R_s=.54, L_d=37e-3, L_q=6.2e-3, psi_f=0)
cfg = control.ObserverBasedVHzControlCfg(
    par, max_i_s=2*base.i, min_psi_s=base.psi, max_psi_s=base.psi)
ctrl = control.ObserverBasedVHzControl(par, cfg)

Set the speed reference and the external load torque.

# Speed reference
times = np.array([0, .125, .25, .375, .5, .625, .75, .875, 1])*8
values = np.array([0, 0, 1, 1, 0, -1, -1, 0, 0])*base.w
ctrl.ref.w_m = Sequence(times, values)
# External load torque
times = np.array([0, .125, .125, .875, .875, 1])*8
values = np.array([0, 0, 1, 1, 0, 0])*nom.tau
mdl.mechanics.tau_L = Sequence(times, values)

Create the simulation object and simulate it.

sim = model.Simulation(mdl, ctrl)
sim.simulate(t_stop=8)

Plot results in per-unit values. By omitting the argument base you can plot the results in SI units.

plot(sim, base)
plot obs vhz ctrl syrm 7kw

References

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

Gallery generated by Sphinx-Gallery