Speed Control#

Proportional-integral (PI) control is widely used in machine drives. A standard one-degree-of-freedom (1DOF) PI controller manipulates only the control error, i.e., it has single input and single output. Its two-degrees-of-freedom (2DOF) variants have two inputs (reference signal and feedback signal), which allows to design disturbance rejection and reference tracking separately [1]. In the following, we will use a speed controller as an example, cf. the motulator.drive.control.SpeedController class. The presented control design can be extended to many other control tasks as well.

Continuous-Time Design#

Even if controllers operate in the discrete-time domain, they are often designed and analyzed in the continuous-time domain.

Typical Structure#

The state-space form of a simple 2DOF PI speed controller is given by

\[\begin{split}\frac{\mathrm{d} \tau_\mathrm{i}}{\mathrm{d} t} &= k_\mathrm{i}\left(\omega_\mathrm{M,ref} - \omega_\mathrm{M}\right) \\ \tau_\mathrm{M,ref} &= k_\mathrm{t}\omega_\mathrm{M,ref} - k_\mathrm{p}\omega_\mathrm{M} + \tau_\mathrm{i}\end{split}\]

where \(\omega_\mathrm{M}\) is the measured (or estimated) mechanical angular speed of the rotor, \(\omega_\mathrm{M,ref}\) is the reference angular speed, and \(\tau_\mathrm{i}\) is the the integral state. Furthermore, \(k_\mathrm{t}\) is the reference feedforward gain, \(k_\mathrm{p}\) is the proportional gain, and \(k_\mathrm{i}\) is the integral gain. Setting \(k_\mathrm{t} = k_\mathrm{p}\) results in the standard PI controller. This 2DOF PI controller can also be understood as a state feedback controller with integral action and reference feedforward [2].

Disturbance-Observer Structure#

The above 2DOF PI controller can be equally represented using the disturbance-observer structure,

\[\begin{split}\frac{\mathrm{d} \tau_\mathrm{i}}{\mathrm{d} t} &= \alpha_\mathrm{i}\left(\tau_\mathrm{M,ref} - \hat \tau_\mathrm{L}\right) \\ \hat \tau_\mathrm{L} &= \tau_\mathrm{i} - (k_\mathrm{p} - k_\mathrm{t})\omega_\mathrm{M} \\ \tau_\mathrm{M,ref} &= k_\mathrm{t}\left(\omega_\mathrm{M,ref} - \omega_\mathrm{M}\right) + \hat \tau_\mathrm{L}\end{split}\]

where \(\alpha_\mathrm{i} = k_\mathrm{i}/k_\mathrm{t}\) is the redefined integral gain and \(\hat \tau_\mathrm{L}\) is the input-equivalent disturbance estimate (i.e., the load torque estimate). This structure is convenient to prevent the integral windup that originates from the actuator saturation [2]. The electromagnetic torque is limited in practice due to the maximum current of the inverter (and possibly due to other constraints as well). Consequently, the realized (limited) torque reference is

\[\bar{\tau}_\mathrm{M,ref} = \mathrm{sat}(\tau_\mathrm{M,ref})\]

where \(\mathrm{sat}(\cdot)\) is the saturation function. If this saturation function is known, the anti-windup of the integrator can be implemented simply as

\[\frac{\mathrm{d} \tau_\mathrm{i}}{\mathrm{d} t} = \alpha_\mathrm{i}\left(\bar{\tau}_\mathrm{M,ref} - \hat \tau_\mathrm{L}\right)\]

The other parts of the above controller are not affected by the saturation. The implementation in the motulator.drive.control.SpeedController class is based on this disturbance-observer form.

Gain Selection Example#

For simplicity, let us assume ideal torque control (\(\tau_\mathrm{M} = \tau_\mathrm{M,ref}\)) and a stiff mechanical system [3]

\[J\frac{\mathrm{d}\omega_\mathrm{M}}{\mathrm{d} t} = \tau_\mathrm{M} - \tau_\mathrm{L}\]

where \(\tau_\mathrm{M}\) is the electromagnetic torque, \(\tau_\mathrm{L}\) is the load torque, and \(J\) is the total moment of inertia. In the Laplace domain, the resulting closed-loop system is given by

\[\omega_\mathrm{M}(s) = \frac{k_\mathrm{t} s + k_\mathrm{i}}{J s^2 + k_\mathrm{p} s + k_\mathrm{i}} \omega_\mathrm{M,ref}(s) - \frac{s}{J s^2 + k_\mathrm{p} s + k_\mathrm{i}} \tau_\mathrm{L}(s)\]

where it can be seen that the gain \(k_\mathrm{t}\) allows to place the reference-tracking zero.

The gain selection

\[k_\mathrm{t} = \alpha_\mathrm{s} \hat{J} \qquad k_\mathrm{p} = 2\alpha_\mathrm{s} \hat{J} \qquad k_\mathrm{i} = \alpha_\mathrm{s}^2 \hat{J}\]

results in

\[\omega_\mathrm{M}(s) = \frac{\alpha_\mathrm{s}}{s + \alpha_\mathrm{s}} \omega_\mathrm{M,ref}(s) - \frac{s}{J (s + \alpha_\mathrm{s})^2} \tau_\mathrm{L}(s)\]

where \(\alpha_\mathrm{s}\) is the closed-loop bandwidth of reference tracking and \(\hat{J} = J\) is assumed.

Discrete-Time Algorithm#

The discrete-time variant of the controller is given by

\[\begin{split}\tau_\mathrm{i}(k+1) &= \tau_\mathrm{i}(k) + T_\mathrm{s} \alpha_\mathrm{i} \left[\bar{\tau}_\mathrm{M,ref}(k) - \hat \tau_\mathrm{L}(k) \right] \\ \hat \tau_\mathrm{L}(k) &= \tau_\mathrm{i}(k) - (k_\mathrm{p} - k_\mathrm{t})\omega_\mathrm{M}(k) \\ \tau_\mathrm{M,ref}(k) &= k_\mathrm{t}\left[\omega_\mathrm{M,ref}(k) - \omega_\mathrm{M}(k)\right] + \hat \tau_\mathrm{L}(k) \\ \bar{\tau}_\mathrm{M,ref}(k) &= \mathrm{sat}[\tau_\mathrm{M,ref}(k)]\end{split}\]

where \(T_\mathrm{s}\) is the sampling period and \(k\) is the discrete-time index. This corresponds to the implementation in the motulator.drive.control.SpeedController class.

References