### PID Intro:

The heart of any real control system has a feedback controller. When the system’s process is unknown or hard to model, a Proportional-Integral-Derivative (PID) controller is an efficient method for control. If the system’s process is known, a custom controller will yield higher efficiency. However, modeling complex systems in attempt to design a custom controller may result in a much higher development time and cost than can be afforded. In both cases, a PID controller is a very efficient method for controlling all types of systems.

### PID Theory:

PID controllers can be understood(partially) without an in depth lecture on control theory. PID controllers use 3 sub-controllers combined into 1 controller using a simple sum. The 3 controllers are:

**Proportional:**

The proportional section of a PID controller is a basic intuitive approach to feedback control. A naive approach to feedback control would say, the farther away from perfect the system is, the more it should work to get perfect. In a perfect world without friction, momentum, etc., this system alone would work great! This is proportional control. However, our world is imperfect and we need to add smarter feedback compensation.
**Integral:**

The integral section of a PID controller compensates environment imperfections such as friction, wind, and other such imperfections that would resist the system to reach its perfect state. An integral controller works by keeping a sum of all the error the system has seen. In calculus, this is equivalent to the area underneath the curve up to the current point. The controller increases its control signal as the summed error gets larger.
**Derivative:**

The derivative section of a PID controller compensates environment imperfections such as momentum which causes the system to overshoot its perfect state. The derivative controller lessens its control signal as the speed in which it is achieving its perfect state increases. In calculus, this is the slope of the error signal.

### Example:

Let’s consider an example to show how a PID controller could be used. Our example will be an airborne GPS navigation system in a helicopter. The aircraft knows where it is and where it is being told to be. Using basic subtraction, it can figure out the distance to the desired location. This is the error signal. It indicates how far from perfect it is.

Lets say that the PID controller is controlling the forward thrust of the helicopter and that the direction is automatically set by something else (in other words, the helicopter always points the direction it should).

The proportional controller would just set the thrust according to the distance away from the target location. This is a simple approach but most likely will not work by itself. As the helicopter gains momentum, it will become harder to slow down. Using proportional control only, the helicopter will overshoot its target and possibly oscillate around the target location. Another issue is wind. The thrust controller should compensate for wind because a tail wind could cause an positional overshoot and a head wind might cause it to never get there.

The integral controller continues to sum the error it incurs and adjusts appropriately. In the head wind example, the thrust would increase until the aircraft could reach its target destination.

The derivative controller measures the speed in which the error signal is changing, which for the helicopter is simply the relative ground velocity. As the helicopter approaches its destination the derivative controller reduces the thrust allowing the helicopter not to overshoot its target position. In the event of tail wind, it reduces the thurst even more so that it can’t be pushed past the target.

For the helicopter example, all 3 sub-controllers must be used. To use all of them, you just sum the control signals of all 3.

### Implementation:

If you think this sounds hard to implement, you are wrong. PID controllers were designed to be generic and easily adapted to all systems. As mentioned before, PID controllers have 3 sub-controllers. Each controller has a parameter that must be tuned, called ‘gain’. To add a PID controller to a system, you just need to attach the generic PID controller and tune the 3 values.

The following C code is an efficient PID controller.

typedef struct {
double windup_guard;
double proportional_gain;
double integral_gain;
double derivative_gain;
double prev_error;
double int_error;
double control;
} PID;
void pid_zeroize(PID* pid) {
// set prev and integrated error to zero
pid->prev_error = 0;
pid->int_error = 0;
}
void pid_update(PID* pid, double curr_error, double dt) {
double diff;
double p_term;
double i_term;
double d_term;
// integration with windup guarding
pid->int_error += (curr_error * dt);
if (pid->int_error < -(pid->windup_guard))
pid->int_error = -(pid->windup_guard);
else if (pid->int_error > pid->windup_guard)
pid->int_error = pid->windup_guard;
// differentiation
diff = ((curr_error - pid->prev_error) / dt);
// scaling
p_term = (pid->proportional_gain * curr_error);
i_term = (pid->integral_gain * pid->int_error);
d_term = (pid->derivative_gain * diff);
// summation of terms
pid->control = p_term + i_term + d_term;
// save current error as previous error for next iteration
pid->prev_error = curr_error;
}

### Windup Guard:

As you may have noticed, the code has a feature called windup guard. This is a critical feature that must be used in most control systems. Windup guarding is simply just setting a cap on the maximum value that the integrated error can be. This is typically most needed for startup conditions and situations for switching in and out of control. Let’s look at our helicopter example again. Consider the situation where the helicopter can be piloted by a person or the PID autonomous controller. If the human operator had a target destination only a few feet away from the current position but held the helicopter still, the integral portion of the PID controller would continue to sum the error seen. Eventually this error would grow very large. If the pilot then switched to autonomous mode, the controller’s output thrust signal would be huge, most likely causing a wreck. There are two solutions to this problem. The first is using a cap for the maximum absolute value of the integrated value. This is the windup guard. Another solution would be to call the `pid_zeroize`

function each time the GPS target is set and each time the autonomous control system is enabled. In either case, setting a safe maximum value using a windup guard is good practice.

### Optimization:

This code can be optimized if the `pid_update`

function is called at the exact same rate every time. In this case, all references to ‘dt’ can be removed. This will change the optimal values for the integral and derivative gains but once tuned, will respond the same way. In this code, this optimization only removes one multiplication operation and one division operation.

It is possible to change this code to run on fixed-point arithmetic rather than floating-point. This dramatically increases the efficiency but system limits and precision may be compromised. Only use fixed-point if you are sure that you are using enough precision.

EDIT: fixed bug on line 31. changed multiply to divide.