Controllers

The discrete FOC control blocks. Each follows the same convention: a *State / *Params / *Output struct trio plus a mutating *_step! function, called once per fixed-step iteration of the hybrid loop.

Inner current controller

Runs closest to the machine, turning dq current references into a dq voltage command.

InductionMachineDrives.CurrentControllerDiscreteOutput — Type
CurrentControllerDiscreteOutput(; kwargs...)

Result of one current_controller_step! call. A fresh instance is returned each sample; nothing here is carried over, the loop's memory lives in CurrentControllerDiscreteState.

Only vsd/vsq drive the plant. Everything else is diagnostic and is what the simulators log per sample.

Fields

  • vsd, vsq: the dq stator voltage command in V, after feedforward and saturation. This is the block's actual output, rotated to alpha-beta by the caller.
  • isd_ref_lim, isq_ref_lim: current references in A after limiting to the Is_max circle with d-axis priority.
  • isd_filt, isq_filt: the filtered measurements in A actually used this sample.
  • err_d, err_q: the regulated current errors in A.
  • vsd_PI, vsq_PI: PI contribution in V, proportional plus integrator.
  • vsd_ff, vsq_ff: decoupling feedforward in V. vsq_ff includes the back-EMF term omega_e*k*lambda_rd. Both are zero when use_feedforward is false.
  • vsd_unsat, vsq_unsat: the command in V before saturation, i.e. PI plus feedforward.
  • vs_mod_unsat: magnitude of that unsaturated command in V. Compare against Vs_max to see how much voltage headroom is left.
  • saturado: true when the voltage limit was hit this sample (saturado is Spanish for saturated, kept from the MATLAB original).
  • is_mod: magnitude of the filtered current vector in A.

See also CurrentControllerDiscreteParams.

source
InductionMachineDrives.CurrentControllerDiscreteParams — Type
CurrentControllerDiscreteParams(; kwargs...)

Immutable tuning and machine constants of the discrete FOC inner current loop, consumed by current_controller_step!. Defaults describe the small bench machine; the 160 kW case passes its own values.

The PI gains are not stored — they are derived from these parameters on every step as tau_cl = ts_spec/3, Kp = sigma_Lss/tau_cl, Ki = Rs/tau_cl and Kaw = 1/Kp, so changing ts_spec between steps retunes the loop immediately.

Fields

  • Rs: stator resistance in Ω, sets the integral gain.
  • sigma_Lss: transient inductance Lss - Lm^2/Lrr in H, sets the proportional gain and the cross-coupling feedforward.
  • k: rotor coupling coefficient Lm/Lrr, dimensionless, scales the back-EMF feedforward.
  • Ts: controller sample time in s.
  • ts_spec: specified closed-loop settling time of the current loop in s.
  • tau_f: time constant in s of the optional current measurement filter.
  • Vs_max: stator voltage magnitude limit in V. The command is scaled, not clipped per axis, so its direction survives saturation.
  • Is_max: stator current magnitude limit in A, applied to the references with d-axis priority.
  • use_filter, use_feedforward, use_saturation, use_antiwindup: development flags for switching the corresponding stage off. All default to true, which is what every simulator in this package uses.

See also CurrentControllerDiscreteState, CurrentControllerDiscreteOutput.

source
InductionMachineDrives.CurrentControllerDiscreteState — Type
CurrentControllerDiscreteState(; kwargs...)

Mutable state carried by the discrete FOC inner current loop between samples, advanced in place by current_controller_step!. All fields default to zero, which is the correct start for a machine at standstill; a non-zero start is better handled by passing reset = true on the first step, which seeds the filters from the present measurements.

Fields

  • ui_d, ui_q: d- and q-axis PI integrator states in V. Updated by Ki * err * Ts each sample, minus the anti-windup back-calculation term when the voltage command saturates.
  • isd_filt, isq_filt: one-pole low-pass filtered dq current measurements in A. Bypassed (set equal to the raw measurement) when use_filter is false.

See also CurrentControllerDiscreteParams, CurrentControllerDiscreteOutput.

source
InductionMachineDrives.current_controller_step! — Method
current_controller_step!(state, p; isd_ref, isq_ref, isd_med, isq_med,
                         omega_e, lambda_rd, reset = false)

Advance the discrete FOC inner current loop by one sample period p.Ts.

This is the innermost block of the hybrid loop: it turns dq current references into the dq stator voltage command that is then rotated to alpha-beta and applied to the plant. It is called once per fixed-step iteration, after the outer torque or speed loop has produced isd_ref/isq_ref.

state is mutated in place — the two integrator states ui_d/ui_q and the two filtered measurements isd_filt/isq_filt. The result is returned as a fresh CurrentControllerDiscreteOutput.

Arguments

  • state::CurrentControllerDiscreteState: integrator and filter state, mutated.
  • p::CurrentControllerDiscreteParams: machine constants, tuning, limits and the four feature flags.
  • isd_ref, isq_ref: dq current references in A, before limiting.
  • isd_med, isq_med: measured dq currents in A (med for medido).
  • omega_e: electrical angular frequency in rad/s, used by the decoupling feedforward only.
  • lambda_rd: d-axis rotor flux linkage in Wb, normally from the rotor-flux observer.
  • reset: when true, zero both integrators and seed the filter states with the present measurements, giving a bumpless start. Applied before anything else in the step.

Steps

  1. PI gains. Recomputed every call from p: tau_cl = ts_spec/3, Kp = sigma_Lss/tau_cl, Ki = Rs/tau_cl, and the back-calculation gain Kaw = 1/Kp. The integrator accumulates Ki * err * Ts, so Ki carries units of V/(A·s).
  2. Measurement filter. With use_filter, a one-pole low pass with alpha = Ts/(tau_f + Ts); otherwise the raw measurements pass through.
  3. Reference limiting, d-axis priority. The flux-producing axis wins: if |isd_ref| > Is_max it is clamped and isq_ref_lim is forced to zero. Otherwise isq_ref is limited to sqrt(Is_max^2 - isd_ref_lim^2), so the commanded current vector stays inside the Is_max circle.
  4. PI on the errors, proportional part plus stored integrator.
  5. Feedforward decoupling, with use_feedforward: vsd_ff = -omega_e*sigma_Lss*isq_filt and vsq_ff = omega_e*sigma_Lss*isd_filt + omega_e*k*lambda_rd, the second term being the back-EMF.
  6. Voltage saturation, with use_saturation: if the unsaturated command exceeds Vs_max in magnitude, both components are scaled by the same factor, preserving direction rather than clipping per axis, and saturado is set.
  7. Anti-windup, with use_antiwindup: when saturated, the integrator is corrected by Kaw times the difference between the unsaturated and saturated PI parts, feedforward excluded.

The four flags exist for development and bring-up; all default to true, which is the configuration the simulators use.

See also CurrentControllerDiscreteState, CurrentControllerDiscreteParams and CurrentControllerDiscreteOutput.

source

Outer torque loop, F1 constant flux

InductionMachineDrives.OuterTorqueFluxF1Output — Type
OuterTorqueFluxF1Output(; kwargs...)

Result of one outer_torque_flux_f1_step! call, returned fresh each sample. isd_ref/isq_ref are what the inner current controller consumes; the rest is diagnostic.

Fields

  • isd_ref, isq_ref: dq current references in A for current_controller_step!.
  • Te_ref_out: torque reference in N·m after slew-rate limiting and clamping to Te_max.
  • lambda_ref_out: rotor flux reference in Wb. Constant at Lm*isd_nom in F1 mode.
  • e_wm, e_Te, e_lambda: always zero here. They exist so torque and speed outer loops share an output layout; only the speed loops fill in e_wm.
  • sat_isd, sat_isq, sat_Te: saturation flags, +1 at the upper limit, -1 at the lower limit, 0 when unlimited.
  • T_load_est: the TL argument passed through unchanged, logged for comparison. This block does not use it.
  • Kt_nom: nominal torque constant 1.5*p*k*Lm*isd_nom in N·m/A used for the torque-to-isq map.
  • isq_max_disp: q-axis current in A still available inside the Is_max circle after the d-axis has taken its share (disponible, available).

See also OuterTorqueFluxF1Params.

source
InductionMachineDrives.OuterTorqueFluxF1Params — Type
OuterTorqueFluxF1Params(; kwargs...)

Machine constants and limits of the F1 constant-flux torque outer loop, consumed by outer_torque_flux_f1_step!.

Fields

  • Ts: sample time in s. Both slew-rate limits are converted to a per-sample step with it.
  • p: pole pairs.
  • Lm, Lrr: magnetizing and rotor inductance in H. They fix the coupling coefficient k = Lm/Lrr and hence the nominal torque constant Kt_nom = 1.5*p*k*Lm*isd_nom.
  • isd_nom: the constant d-axis current reference in A that defines F1 mode. Flux is held at Lm*isd_nom at all speeds — there is no field weakening in this block.
  • Is_max: stator current magnitude limit in A, bounding the dq reference vector with d-axis priority.
  • isd_min: lower bound in A on the d-axis reference, so the machine is never left without flux.
  • Te_max: torque reference magnitude limit in N·m.
  • Te_dot_max: torque reference slew rate in N·m/s.
  • id_dot_max: d-axis current reference slew rate in A/s. Rotor flux cannot change instantly, so the flux command is ramped rather than stepped.

See also OuterTorqueFluxF1State, OuterTorqueFluxF1Output.

source
InductionMachineDrives.OuterTorqueFluxF1State — Type
OuterTorqueFluxF1State(; kwargs...)

Mutable state of the F1 constant-flux torque outer loop, advanced in place by outer_torque_flux_f1_step!. This loop has no integrator: its only memory is the two slew-rate limiters (ant for anterior, the previous value).

Fields

  • Te_ref_ant: previous ramped torque reference in N·m, the starting point for this sample's Te_dot_max step.
  • id_ref_ant: previous ramped d-axis current reference in A. The default equals the default isd_nom, so a fresh state starts at nominal flux instead of ramping up from zero.

See also OuterTorqueFluxF1Params, OuterTorqueFluxF1Output.

source
InductionMachineDrives.outer_torque_flux_f1_step! — Method
outer_torque_flux_f1_step!(state, p; Te_ref_ext, TL = 0.0, reset = false)

Advance the F1 constant-flux torque outer loop by one sample period p.Ts and return the dq current references the inner current controller should track.

This is the mode_control = 1 (TORQUE) + mode_torque = 1 (T1) + mode_flux = 1 (F1) path of the MATLAB original: an externally commanded torque is slew- and magnitude-limited, then converted to isq through the nominal torque constant, while isd is held at nominal flux. There is no feedback here — the block is a feedforward reference shaper, so it has no integrator and cannot wind up.

state is mutated in place; the result is a fresh OuterTorqueFluxF1Output.

Arguments

  • state::OuterTorqueFluxF1State: the two slew-rate limiter memories, mutated.
  • p::OuterTorqueFluxF1Params: machine constants and limits.
  • Te_ref_ext: externally commanded electromagnetic torque in N·m. Positive accelerates toward positive speed, per J*dω/dt = Te + TL - B*ω.
  • TL: load torque in N·m, passed through to T_load_est for logging only. Same sign convention: positive TL also accelerates toward positive speed.
  • reset: when true, reinitialise the ramp states and seed the torque ramp at Te_ref_ext, so the first step does not ramp up from zero.

Steps

  1. Torque reference shaping. Te_ref_ext is ramped at Te_dot_max and then clamped to ±Te_max, setting sat_Te.
  2. F1 flux reference. isd targets the constant isd_nom, ramped at id_dot_max and clamped to [isd_min, Is_max].
  3. Torque-to-current map. isq_ref = Te_ref_out / Kt_nom with the nominal torque constant. Because flux is constant in F1, this map is exact as long as the actual flux equals Lm*isd_nom.
  4. Current-circle limiting, d-axis priority. isq_ref is clamped to sqrt(Is_max^2 - isd_ref^2), so flux is preserved and torque gives way.

See also outer_speed_flux_f1_step! for the speed-controlled counterpart, and outer_speed_flux_mtpa_step! for the variable-flux alternative.

source

Outer speed loop, F1 constant flux

InductionMachineDrives.OuterSpeedFluxF1Output — Type
OuterSpeedFluxF1Output(; kwargs...)

Result of one outer_speed_flux_f1_step! call, returned fresh each sample. isd_ref/isq_ref drive the inner current controller; everything else is diagnostic and is logged per sample by the speed simulators.

Fields

  • isd_ref, isq_ref: dq current references in A for current_controller_step!.
  • Te_ref_out: torque reference in N·m after clamping to ±Te_max, i.e. Te_PI + Te_ff limited.
  • lambda_ref_out: rotor flux reference in Wb, Lm*isd_ref. Equals Lm*isd_nom below base speed and drops in field weakening.
  • wm_ref_ramp: speed reference in rad/s after wm_dot_max slew limiting — the reference the PI actually regulates against.
  • wm_filt: filtered speed measurement in rad/s.
  • e_wm: speed error wm_ref_ramp - wm_filt in rad/s.
  • e_Te, e_lambda: always zero, kept for layout compatibility with the other outer loops.
  • sat_isd, sat_isq, sat_Te: saturation flags, +1 upper, -1 lower, 0 unlimited.
  • T_load_est: the TL_est argument passed through, whether or not feedforward used it.
  • Kt_nom: torque constant in N·m/A at nominal flux.
  • isq_max_disp: q-axis current in A still available inside the Is_max circle after the d-axis share.
  • Kt_ref: torque constant in N·m/A at the actual flux reference. Differs from Kt_nom only under field weakening, and it is the one used for the torque-to-isq map.
  • isd_ref_no_fw: the d-axis reference in A that would have been commanded without field weakening, i.e. isd_nom.
  • fw_speed: max(|wm_filt|, |wm_ref_ramp|) in rad/s, the speed the field-weakening decision is based on. Using the larger of the two avoids weakening too late during fast reel-in/reel-out transients.
  • field_weakening_active: 1 while the flux is being reduced, 0 otherwise.
  • Te_PI: PI contribution to the torque reference in N·m.
  • Te_ff: feedforward contribution in N·m, load_ff_sign*TL_est + B*wm_ref_ramp + J*dωref/dt.

See also OuterSpeedFluxF1Params.

source
InductionMachineDrives.OuterSpeedFluxF1Params — Type
OuterSpeedFluxF1Params(; kwargs...)

Machine constants, tuning and limits of the F1 constant-flux speed outer loop, consumed by outer_speed_flux_f1_step!.

As in the inner loop, the PI gains are derived on every step rather than stored: Kp_wm = J/(ts_wm/3), Ki_wm = Kp_wm/min(J/B, ts_dist_wm) and Kaw_wm = 1/Kp_wm.

Fields

  • Ts: sample time in s.
  • p: pole pairs.
  • Lm, Lss, Lrr: magnetizing, stator and rotor inductance in H. Lss is used only by the field-weakening voltage ellipse.
  • J: total inertia in kg·m², motor plus load. Sets Kp_wm and the acceleration feedforward.
  • B: viscous friction coefficient in N·m·s/rad, opposing motion in J*dω/dt = Te + TL - B*ω. Enters both the integral time constant and the friction feedforward.
  • isd_nom: nominal d-axis current in A — the flux level F1 holds below base speed.
  • Is_max: stator current magnitude limit in A.
  • isd_min: lower bound in A on the d-axis reference, also the floor of field weakening.
  • Te_max: torque reference magnitude limit in N·m.
  • wm_dot_max: speed reference slew rate in rad/s². Set it very high (e.g. 1e6) when a recorded profile should be played back unaltered.
  • id_dot_max: d-axis current reference slew rate in A/s.
  • use_field_weakening: when true, reduce flux above wm_base_fw instead of holding isd_nom at all speeds.
  • wm_base_fw: mechanical base speed in rad/s above which field weakening starts. Compared internally in electrical terms, as p*wm_base_fw.
  • Vs_max: stator voltage limit in V used by the field-weakening voltage ellipse. Keep it consistent with the inner controller's Vs_max.
  • tau_f_wm: speed measurement filter time constant in s.
  • ts_wm: specified closed-loop settling time of the speed loop in s.
  • ts_dist_wm: disturbance-rejection time constant in s, capping the integral time constant when the mechanical time constant J/B is long.
  • use_load_feedforward: when true, add load_ff_sign * TL_est to the feedforward torque. Requires a meaningful TL_est, e.g. from load_torque_kalman_step!.
  • load_ff_sign: sign of that term, -1.0 by design. With J*dω/dt = Te + TL - B*ω a positive TL already accelerates the machine, so cancelling it requires Te_ff = J*dωref/dt + B*ωref - TL_est. Flipping this to +1 doubles the disturbance instead of rejecting it.

See also OuterSpeedFluxF1State, OuterSpeedFluxF1Output.

source
InductionMachineDrives.OuterSpeedFluxF1State — Type
OuterSpeedFluxF1State(; kwargs...)

Mutable state of the F1 constant-flux speed outer loop, advanced in place by outer_speed_flux_f1_step! (ant is anterior, the previous value).

Fields

  • ui_wm: speed PI integrator state in N·m, corrected by back-calculation when the torque reference saturates.
  • wm_filt: low-pass filtered mechanical speed measurement in rad/s.
  • wm_ref_ant: previous ramped speed reference in rad/s. Its per-sample change also supplies the J*dω/dt feedforward term.
  • id_ref_ant: previous ramped d-axis current reference in A, defaulting to the default isd_nom so a fresh state starts at nominal flux.

See also OuterSpeedFluxF1Params, OuterSpeedFluxF1Output.

source
InductionMachineDrives.outer_speed_flux_f1_step! — Method
outer_speed_flux_f1_step!(state, p; wm_ref, wm_med, omega_e = nothing,
                          TL_est = 0.0, reset = false)

Advance the F1 constant-flux speed outer loop by one sample period p.Ts and return the dq current references for the inner current controller.

This is the mode_control = 2 (SPEED) + mode_torque = 1 (T1) + mode_flux = 1 (F1) path of the MATLAB original, extended with optional field weakening and optional load-torque feedforward. A PI on speed error plus a model-based feedforward produces a torque reference, which is then mapped to isq at the commanded flux level.

state is mutated in place; the result is a fresh OuterSpeedFluxF1Output.

Arguments

  • state::OuterSpeedFluxF1State: PI integrator, speed filter and the two ramp memories, mutated.
  • p::OuterSpeedFluxF1Params: machine constants, tuning and limits.
  • wm_ref: commanded mechanical speed in rad/s, before slew limiting. Signed — the loop tracks both directions.
  • wm_med: measured mechanical speed in rad/s (med for medido).
  • omega_e: synchronous electrical speed in rad/s, normally RotorFluxObserverDiscreteOutput.omega_e. Used only by field weakening. Pass nothing (the default) and the block falls back to the pole-pair-scaled mechanical speed p*fw_speed; a non-finite value takes the same fallback.
  • TL_est: estimated load torque in N·m, positive when it accelerates toward positive speed. Only used when p.use_load_feedforward is true.
  • reset: when true, zero the integrator, seed the speed filter with wm_med and the reference ramp with wm_ref, and restore nominal flux. Applied before anything else in the step.

Steps

  1. Speed filtering and reference ramp. One-pole filter with alpha = Ts/(tau_f_wm + Ts); the reference is slew-limited at wm_dot_max.
  2. PI plus feedforward. Te_ref = Kp_wm*e_wm + ui_wm + (load_ff_sign*TL_est + B*wm_ref_ramp + J*dωref/dt), clamped to ±Te_max. The integrator is then updated with Ki_wm*e_wm*Ts minus Kaw_wm times the clamped-away excess, so the loop does not wind up against the torque limit.
  3. Flux reference. Constant isd_nom, unless use_field_weakening is true and the electrical speed exceeds p*wm_base_fw. Then isd_ref is the smallest of isd_nom, the inverse-speed limit isd_nom*ω_base/ω, and the steady-state voltage-ellipse limit built from Vs_max, floored at isd_min. The result is ramped at id_dot_max, since rotor flux cannot step.
  4. Torque-to-current map. isq_ref = Te_ref_out / Kt_ref where Kt_ref uses the achieved flux Lm*isd_ref, not the nominal one — this is what keeps the torque correct while the field is weakened.
  5. Current-circle limiting, d-axis priority, as in the torque loop.

Note that the mechanical convention J*dω/dt = Te + TL - B*ω is what fixes load_ff_sign = -1.0. Changing that sign turns load feedforward from compensation into amplification.

See also outer_speed_flux_mtpa_step! for the variable-flux alternative, load_torque_kalman_step! for producing TL_est, and simulate_foc_speed_f1_hybrid for a complete loop using this block.

source

Outer speed loop, constrained MTPA with field weakening

See MTPA integration for the include-order constraint that this controller imposes on src/InductionMachineDrives.jl.

InductionMachineDrives.OuterSpeedFluxMTPAOutput — Type
OuterSpeedFluxMTPAOutput(; kwargs...)

Result of one outer_speed_flux_mtpa_step! call, returned fresh each sample. isd_ref/isq_ref drive the inner current controller; the diagnostics below make it possible to see which constraint set the flux at any instant.

Fields

  • isd_ref, isq_ref: dq current references in A for current_controller_step!.
  • Te_ref_out: torque reference in N·m after clamping to ±Te_max.
  • lambda_ref_out: rotor flux reference in Wb, Lm*isd_ref. Unlike F1 this moves continuously with the torque demand.
  • wm_ref_ramp: slew-limited speed reference in rad/s.
  • wm_filt: filtered speed measurement in rad/s.
  • e_wm: speed error in rad/s.
  • e_Te, e_lambda: always zero, kept for layout compatibility.
  • sat_isd, sat_isq, sat_Te: saturation flags, +1 upper, -1 lower, 0 unlimited.
  • T_load_est: the TL_est argument passed through.
  • Kt_isd: the bilinear torque coefficient 1.5*p*Lm^2/Lrr in N·m/A².
  • isd_mtpa: the unconstrained MTPA solution sqrt(|Te_ref|/Kt_isd) in A.
  • isd_floor: flux-floor constraint lambda_rd_floor/Lm in A, or 0 when disabled.
  • isd_reserve: torque-reserve constraint in A, or 0 when disabled.
  • isd_desired: the applied target, max of the three above and isd_min, capped at Is_max/sqrt(2). Comparing it against the three tells you which constraint is binding.
  • isq_max_disp: q-axis current in A available inside the current circle.
  • Te_current_limited: torque in N·m actually achievable with the commanded isd_ref/isq_ref, i.e. Kt_isd*isd_ref*isq_ref. Below Te_ref_out whenever the current circle bites.
  • torque_current_limited: 1 when isq hit the circle limit, 0 otherwise.
  • Te_PI: PI contribution in N·m.
  • Te_ff: feedforward contribution in N·m.

See also OuterSpeedFluxMTPAParams.

source
InductionMachineDrives.OuterSpeedFluxMTPAParams — Type
OuterSpeedFluxMTPAParams(; kwargs...)

Machine constants, tuning and limits of the constrained-MTPA speed outer loop, consumed by outer_speed_flux_mtpa_step!. The speed PI is designed exactly as in OuterSpeedFluxF1Params; the extra fields are the three constraints that make plain MTPA usable on a winch.

Fields

  • Ts: sample time in s.
  • p: pole pairs.
  • Lm, Lrr: magnetizing and rotor inductance in H. They fix Kt_isd = 1.5*p*Lm^2/Lrr, the constant of the bilinear torque model Te = Kt_isd * isd * isq.
  • J: total inertia in kg·m².
  • B: viscous friction coefficient in N·m·s/rad.
  • isd_nom: d-axis current in A used to initialise the ramp state on reset. In MTPA it is a starting point, not a setpoint.
  • Is_max: stator current magnitude limit in A. Also caps the MTPA solution at Is_max/sqrt(2), the point where isd = isq fills the current circle.
  • isd_min: lower bound in A on the d-axis reference.
  • Te_max: torque reference magnitude limit in N·m.
  • wm_dot_max: speed reference slew rate in rad/s².
  • id_dot_max: d-axis current reference slew rate in A/s.
  • lambda_rd_floor: minimum rotor flux in Wb to hold regardless of torque demand. Pure MTPA collapses the flux near zero torque, which would leave the machine unable to respond; this is the floor that prevents it. Set to 0 to disable.
  • Te_reserve: torque in N·m that must remain achievable within Is_max at any moment. Translated into a flux floor Te_reserve/(1.5*p*k*Lm*Is_max), it buys fast response to a sudden load change at the cost of some efficiency. Set to 0 to disable.
  • tau_f_wm: speed measurement filter time constant in s.
  • ts_wm: specified closed-loop settling time of the speed loop in s.
  • ts_dist_wm: disturbance-rejection time constant in s.
  • use_load_feedforward: when true, add load_ff_sign * TL_est to the feedforward torque.
  • load_ff_sign: -1.0 by design, as required by J*dω/dt = Te + TL - B*ω.

See also OuterSpeedFluxMTPAState, OuterSpeedFluxMTPAOutput.

source
InductionMachineDrives.OuterSpeedFluxMTPAState — Type
OuterSpeedFluxMTPAState(; kwargs...)

Mutable state of the constrained-MTPA speed outer loop, advanced in place by outer_speed_flux_mtpa_step!. Layout is identical to OuterSpeedFluxF1State — the two controllers differ in how they choose the flux level, not in what they remember.

Fields

  • ui_wm: speed PI integrator state in N·m.
  • wm_filt: filtered mechanical speed in rad/s.
  • wm_ref_ant: previous ramped speed reference in rad/s.
  • id_ref_ant: previous ramped d-axis current reference in A. Unlike F1, this one keeps moving during normal operation, since MTPA retargets the flux whenever the torque demand changes.

See also OuterSpeedFluxMTPAParams, OuterSpeedFluxMTPAOutput.

source
InductionMachineDrives.outer_speed_flux_mtpa_step! — Method
outer_speed_flux_mtpa_step!(state, p; wm_ref, wm_med, TL_est = 0.0,
                            reset = false)

Advance the constrained-MTPA speed outer loop by one sample period p.Ts and return the dq current references for the inner current controller.

Counterpart of outer_speed_flux_f1_step! with the same speed PI and the same feedforward, but a different flux policy. F1 holds isd at isd_nom whatever the torque; this block chooses isd per sample to minimise stator current for the torque demanded — Maximum Torque Per Ampere — using the bilinear model

Te = Kt_isd * isd * isq,    Kt_isd = 1.5 * p * Lm^2 / Lrr

whose optimum is isd = |isq|, i.e. isd_mtpa = sqrt(|Te_ref|/Kt_isd). Pure MTPA is not usable on its own — it starves the flux at low torque, so the machine cannot respond to a sudden load — hence the three floors described below. This is the mode_flux = F3 path of the MATLAB original.

state is mutated in place; the result is a fresh OuterSpeedFluxMTPAOutput.

Arguments

  • state::OuterSpeedFluxMTPAState: PI integrator, speed filter and the two ramp memories, mutated.
  • p::OuterSpeedFluxMTPAParams: machine constants, tuning, limits and the two constraint settings.
  • wm_ref: commanded mechanical speed in rad/s, signed, before slew limiting.
  • wm_med: measured mechanical speed in rad/s.
  • TL_est: estimated load torque in N·m, positive when it accelerates toward positive speed. Used only when p.use_load_feedforward is true.
  • reset: when true, zero the integrator, seed the speed filter with wm_med and the reference ramp with wm_ref, and set the flux ramp to isd_nom.

Steps

  1. Speed filtering, reference ramp, PI plus feedforward — identical to outer_speed_flux_f1_step!, including the back-calculation anti-windup against ±Te_max.
  2. Constrained flux choice. isd_desired is the largest of the MTPA optimum isd_mtpa, the flux floor lambda_rd_floor/Lm, the torque reserve Te_reserve/(1.5*p*k*Lm*Is_max) and isd_min, then capped at Is_max/sqrt(2) — beyond that point a larger isd could not be matched by an equal isq inside the current circle. The result is ramped at id_dot_max because rotor flux cannot change instantaneously.
  3. Torque-to-current map. isq_ref = Te_ref_out / (Kt_isd * isd_ref), using the flux actually commanded this sample.
  4. Current-circle limiting, d-axis priority. isq_ref is clamped to sqrt(Is_max^2 - isd_ref^2); Te_current_limited then reports the torque that remains achievable.

There is deliberately no field weakening here: the flux is already speed- independent and demand-driven. If you need voltage-limit-aware flux reduction, use outer_speed_flux_f1_step! with use_field_weakening = true.

See also simulate_foc_speed_mtpa_hybrid for a complete loop using this block.

source