Table of Contents
This technical note addresses possible implementations for a discrete PI controller and provides general insight into PI tuning strategies. It also includes practical implementations for digital control, on Simulink, PLECS and C/C++.
General principles
PI controllers certainly represent the most intuitive and widespread form of closed-loop (feedback) control. As such, they are frequently implemented in both continuous (analog) and discrete (digital) domains. This is notably due to their simple structure and implementation, relying on two steps:
- The difference between the desired setpoint and the measured variable is computed. This value is considered as an error.
- The PI controller computes a control action that is proportional to this error (proportional part) and makes sure that the process output agrees with the setpoint in steady state (integral part).
PI controller structure
Controller type
Imperix generally uses PI controllers and not PID controllers to avoid complexity and instability issues related to the derivative action. More precisely, the high-frequency gain of the derivative action can indeed cause amplification of measurement noise, which is undesirable. Also, PID controllers generally bring only little improvement when paired with first-order systems (which are very common in power electronics) [1].
Controller structure
PI controllers can be implemented either in parallel (also referred to as non-interacting), series (interacting), or mixed form [2]. This article, will focus on the parallel structure of PI controllers as it allows for the full decoupling of the proportional and integral term which makes manual tuning easier. The block diagram below describes the implementation of a parallel PI controller.
Digital implementation
The well-known continuous time transfer function of a PI controller, given below, should be discretized to be implemented in a digital controller.
$$ (1) \quad C(s) = k_p + \frac{k_i}{s}$$
Here, \(k_p\) and \(k_i\) are the proportional and integral gain of the controller, respectively.
Usually, the main goals when discretizing a continuous function for a control system are to preserve its frequency behavior and stability characteristics. To this end, several possible discretization strategies exist, amongst which the three most common are Forward Euler, Backward Euler, and Tustin [3]. Each method comes with its advantages and drawbacks, which can be summarized as follows in order to guide the choice of implementation [4]:
- Forward Euler: Simple and computationally efficient, but suffers from poor stability.
$$ (2) \quad s = \frac{z-1}{T_s} $$ - Backward Euler: Unconditionally stable, but more computationally intensive than Forward Euler.
$$ (3) \quad s = \frac{z-1}{T_sz} $$ - Tustin: Preserves continuous-time stability and offers superior frequency accuracy compared to Euler methods, at the cost of higher implementation complexity.
$$ (4) \quad s = \frac{2}{T_s}\frac{z-1}{z+1} $$
Where \(T_s\) is the discrete time interval.
Now, discretization methods being a broad topic and out of the scope of this article, the following section will focus on the forward Euler method. But a similar approach can be used for the other two aforementioned methods.
The discretized equation of the PI controller using the forward Euler method would then result in the following equation:
$$ (5) \quad C(z) = \frac{Y(z)}{E(z)} = K_p + K_i T_s \frac{1}{z-1} $$
In the end, as the objective is to implement a PI controller inside of a digital control system, the discretized PI controller can then be translated into the following difference equations for run-time code generation:
$$ (6) \quad \begin{aligned}
& y(k) = P(k) + I(k) = k_p \cdot e(k) + I(k)\\
& I(k) = I(k-1) + k_i \cdot T_s \cdot e(k-1) \\
\end{aligned}$$
Where \(e(k)\) is the error input (the difference between the targeted setpoint and the measured value) and \(y(k)\) is the output of the PI controller.
PI controller tuning strategies
Many different strategies can be used for the tuning of PI controllers, such as Ziegler Nichols, loop shaping, optimization, pole placement, etc. Tuning should consider tradeoffs between tracking performance, load perturbance rejection, effect of measurement noise and other aspects, depending on the control requirements [2].
This section will further detail a popular optimization method, the magnitude optimum, often chosen for its good tradeoff between simplicity and performance. This tuning strategy will aim for a good response to setpoint changes, with the potential drawback of poor perturbance rejection. Alternatively, the symmetric optimum criterion can be used when the focus towards disturbance rejection [5].
The Magnitude (or Modulus) optimum tuning method’s objective is to design a controller so that the overall system’s output (controller + plant) would exactly and instantaneously reproduce its input. That is, the overall system’s transfer function would be unity [6].
To derive the magnitude optimum’s parameters, a first order plant model is considered, described in the Laplace domain, by equation below:
$$ (7) \quad P_1(s) = \frac{K_1}{1+s T_1}$$
The PI controller transfer function is rewritten as:
$$ (8) \quad C(s) = \frac{1+sT_n}{sT_i}$$
The actuator delay is also taken into account and approximated by a first order model as well:
$$ (9) \quad D(s) = e^{(-sT_{d,tot})} \approx \frac{1}{1+s T_{d,tot}}$$
The obtained generic formulas for magnitude optimum, shown below, can then be used for tuning PI controllers [5].
$$ (10) \quad \begin{aligned}
&T_n = T_1\\
&T_i = 2 K_1 T_{d,tot}
\end{aligned}$$
For the symmetric optimum, the generic formulas are shown below [5]
$$ (11) \quad \begin{aligned}
&T_n = 4 T_{d,tot}\\
&T_i = 8 K_1 T_{d,tot}^2
\end{aligned}$$
Rewriting (8) as in (1) results in the following equations for \(K_p\) and \(K_i\):
$$ (12) \quad \begin{aligned}
&K_p = T_n /T_i\\
&K_i = 1 / T_i
\end{aligned}$$
The parameter \(T_{d,tot}\) represents the sum of all the delays in the system (from the data acquisition to the control output). For a practical example of PI controller tuning, please refer to: PI based current control.
PI controller configuration
Several techniques are available to improve the behavior of PI controllers. For instance, anti-windup strategies, setpoint weighting, feedforward, cascaded control are some of the improvements that can be made to conventional PI controllers [1]. A strategy to limit integrator windup is given in the section below.
Integrator wind-up and anti-windup methods
When the control system has to adjust for a large disturbance or setpoint variation, the integrator will accumulate a significant error (wind-up) during the transient phase. This can also happen when a physical variable reaches its limits (in the case of a switched-mode power supply, the duty cycle is usually bounded between 0 and 1 for instance). So when the output finally reaches the reference, the large value accumulated by the integral term will create a significant, undesired overshoot of the output.
To get rid of this unwanted effect, anti-windup algorithms can be implemented. Several techniques are commonly used such as [1]:
- Conditional integration
- Back calculation
- Automatic reset
The below illustration details the conditional integration algorithm, which will disable the integrator when the two following conditions are fulfilled:
- The PI controller output saturates.
- The control and error signals have the same sign (When they don’t, the integrator can help push the controller’s output out of saturation).
Reset
While the control task is not actively running (during system initialization, shutdown, or when transitioning between control modes for instance) it is often necessary to prevent the integrator from accumulating error. PI controllers commonly provide an external reset mechanism to address this. As part of the imperix blockset, the Core state block outputs the appropriate reset signal which can directly be connected to the external reset input of PI controllers. Obviously, this signal is only relevant in an experimental setup and is of no use in simulation.
B-Box / B-Board implementation
Simulink and PLECS
The (discrete) PID controller blocks from Simulink and PLECS can generally be used for the implementation of control algorithms. Please refer to the page Current control with a PI controller for configuration examples of both Simulink and PLECS PI controllers.
C/C++ code
The imperix IDE provides numerous pre-written and pre-optimized functions. Controllers such as P, PI, PID and PR are already available and can be found in the controllers.h/.cpp
files.
As for all controllers, PI controllers are based on:
- A pseudo-object
PIDcontroller
, which contains pre-computed parameters as well as state variables. - A configuration function, meant to be called during
UserInit()
, namedConfigPIDController()
. - A run-time function meant to be called during the user-level ISR such as
UserInterrupt()
, namedRunPIController()
.
Note that this C/C++ implementation of the PI controller is slightly different from the one described above. More information on this implementation can be found in [5].
References
[1] A. Visioli, “Practical PID Control”, 2006
[2] Karl J. Åström and Tore Hägglund, “Advanced PID Control”, 1995
[3] Buso, S. and Mattavelli, P., “Digital Control in Power Electronics: Second Edition”, 2015
[4] Franklin, G.F., Powell, J. and D.Workman, M.L., “Digital Control of Dynamic Systems”, 1998
[5] J. W. Umland and M. Safiuddin, “Magnitude and symmetric optimum criterion for the design of linear control systems: what is it and how does it compare with the others?,” in IEEE Trans. on Industry Applications, May-June 1990.
[6] Longchamp, R., “Commande numérique de systèmes dynamiques: cours d’automatique”, 2010