PowerElecHub

PMSM Field-Oriented Control Lab: Current and Speed PI Tuning

A field-oriented drive is two PI loops stacked on a simple model: an inner current loop that sets torque and an outer speed loop that asks for current. Tuning them on paper takes two lines of algebra. Seeing what the gains do takes a motor. This lab simulates a 48 V PMSM in the rotor dq frame, runs the same discrete controllers a microcontroller would, and redraws every curve as soon as a slider moves. The rotor on the left replays the run in slow motion, with the stator current vector drawn on top.

Experiment

Current PI on i_d and i_q (10 kHz)

Textbook tuning: Kp_i = L·ω_bw, Ki_i = R·ω_bw. The PI zero then cancels the R/L pole and the loop behaves like ω_bw/(s + ω_bw).
ω_bw = Kp_i/L = 2π·500 Hz · Ki_i/Kp_i = 250 rad/s (R/L = 250)

Speed PI → i_q* (1 kHz)

Starting point: Kp_ω = J·ω_sc/K_t, Ki_ω = Kp_ω·ω_sc/4, with K_t = 1.5·p·λ_m. Keep ω_sc at least 5 to 10 times below the current-loop bandwidth.
ω_sc ≈ Kp_ω·K_t/J = 2π·50 Hz · current/speed = 10

Motor: R = 0.5 Ω, L_d = L_q = 2 mH, λ_m = 0.05 Wb, p = 4 pole pairs, J = 1×10⁻⁴ kg·m², B = 1×10⁻⁴ N·m·s. V_dc = 48 V, so the voltage limit is V_dc/√3 = 27.7 V. Current limit 20 A, i_d* = 0.

Rotor, dq axes and current vector
abcNSdqi_s

Drawn as an equivalent two-pole machine, so the rotor angle shown is the electrical angle. Playback runs about 1333 times slower than real time. The bars on the a, b, c axes are the phase currents.

t
6 ms
i_d / i_q
-0.00043 / 1 A
T_e
0.3 N·m
Speed
300 rpm
|v|
6.79 V
θ_e
43°

Result

i_q rise time 10–90 %
310 µs
Ideal 2.2/ω_bw
700 µs
Overshoot
2.46 %
Current-loop bandwidth
500 Hz
i_q step: command and response
1.1-0.082A6 ms0
i_q*i_q
d and q currents
1.1-0.084A6 ms0
i_di_q
Applied voltage and its limit
V_dc/√330-2.6V6 ms0
v_dv_q|v|
Phase currents (inverse Park)
1.1-0.95A6 ms0
i_ai_bi_c

Model: dq equations of a surface-magnet PMSM integrated with RK4 inside each 100 µs control period; the voltage computed in one period is applied in the next. PWM ripple, dead time, saturation and iron loss are not modeled. Anti-windup is conditional integration on both PI controllers.

The model behind the lab

In the rotor frame the stator equations are L_d·di_d/dt = v_d − R·i_d + ω_e·L_q·i_q and L_q·di_q/dt = v_q − R·i_q − ω_e·(L_d·i_d + λ_m), with ω_e = p·ω_m. Torque is T_e = 1.5·p·(λ_m·i_q + (L_d − L_q)·i_d·i_q), which for a surface magnet with L_d = L_q reduces to 1.5·p·λ_m·i_q: torque follows i_q and nothing else. The shaft obeys J·dω_m/dt = T_e − B·ω_m − T_L.

Both current controllers run at 10 kHz and the speed controller at 1 kHz. The voltage vector is clipped to the circle of radius V_dc/√3, which is the largest sinusoidal voltage space-vector modulation can produce without overmodulation. The d axis gets priority, and i_q* is clipped to ±20 A.

Why Kp = L·ω_bw and Ki = R·ω_bw

Seen from v_q, the q-axis current is a first-order plant 1/(L·s + R) once the back-EMF term is removed. A PI controller Kp + Ki/s has a zero at Ki/Kp. Placing that zero on the motor pole R/L cancels it, and the open loop becomes Kp/(L·s): an integrator with crossover Kp/L. Closing the loop gives a first-order response with bandwidth ω_bw = Kp/L and a 10–90 % rise time of 2.2/ω_bw.

That result assumes a continuous controller. Try the 500 Hz preset with the computation delay turned off: the measured rise time comes within about 20 % of the ideal value, and the remaining gap is the 10 kHz sampling itself. Turn the delay back on and the response gets faster with a small overshoot, because the loop now contains a delay of one 100 µs period. At 1 kHz the overshoot is around 50 %, and with the 1.4 kHz preset the current rings for well over a millisecond. With a one-sample delay and a pure proportional gain, the discrete loop goes unstable when Kp·T_s/L reaches 1, which here is a bandwidth of about 1.6 kHz. That is why practical current loops are often designed for a bandwidth of roughly a tenth to a twentieth of the sampling frequency.

Decoupling and the voltage limit

The terms ω_e·L_q·i_q and ω_e·(L_d·i_d + λ_m) tie the two axes together, and both grow with speed. Without feedforward, the q-axis integrator has to build up the full back-EMF on its own and every i_q step disturbs i_d. Hold the rotor at 1000 rpm, step i_q and toggle decoupling: with it off, i_d moves away from zero during the step and the q-axis integrator carries the back-EMF. Adding v_d,ff = −ω_e·L_q·i_q and v_q,ff = ω_e·(L_d·i_d + λ_m) removes most of this, leaving the PI controllers only the R and L dynamics they were tuned for.

At 48 V the inverter can deliver at most about 27.7 V per axis vector, and the back-EMF λ_m·ω_e already reaches 21 V at 1000 rpm. In speed mode, command 1500 rpm and the voltage trace runs into the limit line before the speed gets there: the motor stalls around its base speed no matter how the gains are set. Real drives continue past this point by field weakening, driving i_d negative to reduce the flux linkage. This lab does not model field weakening; it only saturates the voltage, which is enough to show why the limit exists.

Separating the speed loop from the current loop

The speed controller treats the current loop as if it delivered i_q* instantly. That is only reasonable when the current loop is much faster. The speed-loop preset sets a 200 Hz speed crossover on top of a 500 Hz current loop, a ratio of 2.5. In this model the speed overshoot roughly doubles, from about 17 % to about 34 %, and i_q* runs into the 20 A limit during the step; part of the extra overshoot comes from the lag of the current loop and part from that limit. Common practice is a ratio of 5 to 10. The speed integrator's zero, placed here at a quarter of the crossover, sets how quickly the load torque is rejected and how much the speed overshoots after a large step.

Things to try

Set Ki_i ten times too low and i_q stops short of its command and creeps toward it: the zero no longer cancels the pole and a slow tail appears. Increase the i_q step to 10 A and the current rises along an almost straight line because the voltage vector is saturated, not because of the gains. In speed mode, set the load torque to 2 N·m and i_q settles near 6.7 A, since each ampere of i_q produces K_t = 0.3 N·m. These numbers come from this motor model and will be different for your own machine.

References

R. Krishnan, Permanent Magnet Synchronous and Brushless DC Motor Drives, CRC Press, 2010. N. Mohan, Advanced Electric Drives: Analysis, Control and Modeling Using MATLAB/Simulink, Wiley, 2014. Related pages on this site: Clarke and Park transforms, SVPWM, control block diagrams, the PID code generator and the PI discretization tool.

The animation follows the equations stated on this page. Conventions differ between textbooks and software libraries; check the one your code uses before comparing numbers.