## Proportional-Integral-Derivative (PID) Controller

### 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.

It’s hard to find knowledgeable people on this topic, but you sound like you know what you’re talking about! Thanks

Good work!!

However, should it be a divide operation rather than multiplication at line 31:

ie.

diff = ((curr_error – pid->prev_error) / dt);

instead of

diff = ((curr_error – pid->prev_error) * dt);

Great catch! Consider it changed. Thanks.

Hi,

I am designing a PID controller to control lateral and longitudinal stability of a helicopter. Do you know the MATLAB code for it??

If you could provide that I shall be very thankful to you.

Please respond.

You should be able to take the PID function above and port it to MATLAB. The best thing about PID controllers is that it doesn’t matter what you are controlling, the PID function is always the same. The settings for the 3 gains are the only tuning needed.

Let me know if you have any problems porting the C code to MATLAB. I’d be glad to help.

Hi nic,

Well I might sound a complete dumb person right now but the truth is that I have failed to port the pid function to MATLAB. My MATLAB version does not have pid function in it. I am using R2009b. I have tried in 2007 and 2011 versions as well but all in vain. Also, I am not very good at using MATLAB so you can imagine how hard would it be to port it for me..

It has been 3 weeks now I am trying to figure it out but no gain. Is there anyway you could help me with?? I will really appreciate your time and help.

and thanks for your quick response.

waiting for another one. 🙂

Ok, check out this post. I hope it helps

Hey nic, I am designing a real time quadcopter, and I wanted to do a simulink PID control to simulate its stability. Is there any more tutorials on this in specific or any kind of advice or documents I could read to implement this?

The hardest part about simulating a PID controller is determining how to simulate the system being controlled. PID controllers were developed for situations where the transfer function of the system is unknown or very complex. If you actually found the transfer function of a quadcopter, you’d probably discover a better feedback control system than a PID controller.

But, you can make a poorly behaved simulator, with latencies, and noise, and external forces like wind, changes in gravity, or tree limbs. You could make a better control loop to account for all of that, but it wouldn’t help you in the real world because you don’t have accurate measurements of the wind, tree limbs, or errors in control. If your system is going to use a PID to compensate for a ton of external errors, it’s not hard to make a simulator that will make similar external errors. There’s a lot of value in it, but the devil is in the details. The magic you get out is proportional to the art you put in.

Also, you’d have a hard time tuning the PID gains precisely based on a simulator, unless you very carefully characterized the system. But it would certainly get you a lot closer, and should save a few dozen crashes with the real thing. Just don’t expect your work to be done when it’s working in sim.

Hi Nic,

I’m building a quadcopter with a RaspberryPi – your post is the clearest I’ve found on the PID purpose and code, thanks. Just a couple (three actually) naive questions:

1. I assume there is an independent PID algorithm for each of the X and Y planes, but that’s not necessary for the Z plane as there are no motors to control that way?

2. I assume P derives directly from an acclerometer and D from a gyroscope but from where is I derived? Is this the roll of a magnetometer to show absolute position (or even GPS)

3. I assume dt is simply the time span since the last time the PID algorithm was called (told you it was naive!)

Thanks,

Andy

http://www.pistuffing.co.uk

Oops, a little more thought made me realize all this tied into the accelerometer – it’s the PID which accounts for speed / gravity / position / wind factors. Just the proportional, intergral and differential aspects will compenstate for gravity, wind, momentum etc

Cheers for the great article.

Hove

Hove,

Take a look at the diagram on this post:

https://nicisdigital.wordpress.com/2011/05/17/software-design/

The sensor fusion algorithm should fuse all the sensor data into one measurement, aircraft attitude, or basically the tilt of the quadcopter. You should have a PID controller for any axis (or dimension) being controlled by your software. The inputs are: the desired value, and the current value. The PID controller will output a control signal. This will then drive your motors.

You need to view each stage independently. Good luck!

-Nic

Thanks Nic,

That’s what I’ve coded once I’d finally realized how the PID(s) worked (hugely appreciated, thanks, to the extent I’ve included a back-reference on my site); so I have 3 PIDs, representing the target G-force in each dimension, and therefore the PIDs each return the necessary PWM power change to resolve the difference between the sensor and the target both statically, dynamically and accounting for external noise.

Cheers,

Hove

Thanks, finally think I understand – I was using the PID outputs for each of the X, Y, and Z dimensions as changes to the current output settings rather than absolute values for the output settings. So this rapidly got out of control (only in simulation luckily).

Cheers,

Andy

http://www.pistuffing.co.uk

There is one think I did not understand. How do we choose proportional_gain , integral_gain, double derivative_gain and dt?

Thanks

Hi Awk, great question! This is the hardest thing about PID controllers. There are better ways to make feedback controllers than PID controllers, but they require you to understand the dynamics of your system. There are a few ways you can tune your PID controller, but the best, most formal way is called the Ziegler Nichols method (look it up on Wikipedia). The basic idea is set P, I, and D to zero, then very slowly ramp up the P value until the system oscillates with a constant amplitude. You then use the amplitude and frequency of oscillates to set the P, I, and D gains based on a desired control style.