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.