# Discrete implementation of the PI controller

I have been implementing discrete PI controller in the incremental (velocity) form in C++. I have been looking for the anti-windup mechanism. One idea which I have can be described by following pseudocode:

    integral_gain = proportional_gain*sampling_period/(2*integral_time_constant);

// e(k)
error = reference_value - actual_value;

// dup(k)= kp*[e(k) - e(k-1)]
proportional_increment = proportional_gain * (error - error_previous);
// trapezoidal integration rule i.e. dui(k) = ki*[e(k) + e(k-1)]
integral_increment = integral_gain * (error + error_previous);
// du(k) = dup(k) + dui(k)
action_increment = proportional_increment + integral_increment;
// u(k) = u(k-1) + du(k)
tmp = action_previous + action_increment;

// anti-windup
if (tmp > action_max) {
action = action_max;
} else if (tmp < action_min) {
action = action_min;
} else {
action = tmp;
}

// u(k-1) = u(k)
action_previous = action;
// e(k-1) = e(k)
error_previous = error;


In math:

Let $$x_k$$ be the "action". Further, define an anti-windup function as

$$f_{aw}(x) = \begin{cases} x_{max} & x > x_{max} \\ x_{min} & x < x_{min} \\ x & \mathrm {otherwise} \end{cases}$$

Then calculate $$x_k$$ from:

$$\Delta p = k_p (e_k - e_{k-1}) \\ \Delta i = k_i (e_k + e_{k-1}) \\ x_k = f_{aw} \left ( x_{k-1} + \Delta p + \Delta i \right)$$

I am not really sure whether the anti-windup mechanism mentioned above will be appropriate despite the fact that the incremental form is used. Can anybody help?

• "One idea which I have" -- why reinvent the wheel when there are already known implementations (plus, Xcos allows you to enter C/C++ code to verify)? May 28, 2021 at 11:14
• @aconcernedcitizen thank you for useful link. In case I understand correctly the mentioned antiwind-up schemes are for the positional form of the PID controller. I have been looking for antiwind-up scheme for velocity form of the PID controller. May 28, 2021 at 12:40
• you don't have an anti-windup scheme by the way, you only perform a saturation.
– Ben
May 28, 2021 at 13:18
• @Ben I know that saturation isn't sufficient in case the positional form of the PI is used. But I think that it could be correct anti wind-up mechanism in case the velocity form of PI is used due to the fact that only the increment of the integral is calculated in that case. May 28, 2021 at 13:28
• you don't actually have an integrator, come to think of it...
– Ben
May 28, 2021 at 13:57

Yes, the output of the controller will be limited to between your action_max and action_min -- this is good. Since your output is also your integrator state, you'll be effecting anti-windup. If I'm not horribly mistaken, if your output is saturated, as soon as the error term starts pointing in the opposite direction of the limit it's at, then it'll back away from that limit.