# 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 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 at 12:40
• you don't have an anti-windup scheme by the way, you only perform a saturation.
– Ben
May 28 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 at 13:28
• you don't actually have an integrator, come to think of it...
– Ben
May 28 at 13:57

## 1 Answer

Define "appropriate".

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.

So you have an anti-windup method that is a good candidate.

However, anti-windup is a nonlinear control law, which is appropriate to use when you're dealing with some plant nonlinearity or some optimality criterion that is not least-square-error. Usually you're dealing with actuator saturation, and usually you just want a stable system and you're willing to let it take a bit extra-long to settle when it has to move a long way. In that case then, yes, this control law may be "appropriate".

But ultimately, the "appropriateness" of a controller depends on your plant, how it's being used, and if you're working in a team, whether your colleagues agree that it's appropriate*. It's an opinion call. So you need to determine if it's appropriate by your lights, and if you're in a team, you need to convince the team that you're right.

* Because the best control rule ever isn't any good at all if your boss won't let you implement it.