Arduino PID Library

Sadly, this is my first post on this forum, and as such, I am not allowed to post http links. I'll remove the base tags and leave the Playgound strings. hopefully you can can find your way there. Sorry for the inconvenience.

I have just added my first ever contribution to the Arduino Playground. An Arduino PID Library: /playground/Code/PIDLibrary

The Barebones PID (/playground/Main/BarebonesPIDForEspresso) has been around for awhile, but I think this is a significant improvement. My goal was to make a pid that was identical to those found in industry, with all the bells and whistles.

I have it listed as a Beta, and I'm open to any suggestions you may have. Let me know what you think!

EDIT: I forgot to add an important piece of information. I'm a controls engineer specializing in pid control. I do this for a living and I figured I'd share the wealth.

UPDATE: 2011-04-15 Library is out of beta (finally)

1 Like

maybe I can post the links in a reply:
http://www.arduino.cc/playground/Code/PIDLibrary
http://www.arduino.cc/playground/Main/BarebonesPIDForEspresso

Thanks for the contribution!

This looks like a robust and comprehensive treatment of the PID controller. I was looking for something like that ;).

Haven't tested it, but it looks good.

A couple of comments -

The description of SetCalcFrequency() indicates the parameter is actually a period, not a frequency. If this is the case then the function would be better named SetCalcPeriod().

The description of Reset() is overly brief. Perhaps it is due to my unfamiliarity with PID controllers, but does this function only reset the current calculated values of measured error and any accumulated integration value? Is the value of Output affected? What about the IOLimits and Tuning parameters?

Excellent point about the frequency. That will have to be changed. Being a chemical and not an electrical engineer, I tend to use those terms interchangeably (the way some misuse precision and accuracy.) stupid mistake. looking through some manufacturers' documentation, it seems that the industry standard name is TSample or SampleTime. not sure if this is as descriptive as CalcPeriod or not.

I had struggled with whether or not to make Reset() public. I doubt it will be needed. Some manufacturers offer a similar function so I decided to as well. Think of Reset() as the soft reset on your phone. you could achieve the same effect by going to manual and immediately back to auto; the output would stay the same, the limits would stay the same, but the controller would "forget" everything that had happened before that point.

I appreciate the feedback. please let me know how it works if you decide to use it. (Sadly,) I'm sure there's at least one or two bugs left to be found.

I am new to using a PID, but will be doing so on a home brewing project ;D

I might suggest some helper functions that allow use of a digital device to simulate PWM (like the BBPID).

I'll be giving this a run this weekend.

EDIT: or I could just read the second example :-[

Could somebody be kind enough to give and explain application concepts for PID?

Thanks!

Chris

I'll try it from the "30,000 foot view".

Imagine that you have cruise control in your car and it is set at 60 mph.

If you are traveling at 30mph and hit resume, the car should apply say 70% power to increase this speed to the target.

However, as you approach that target (say 50 mph), that throttle needs to be decreased, otherwise you will overshoot the target.

Once you reach your target, there will be times that you need to adjust the throttle to maintain that speed. You would likely do this as a small adjustment (1-2%) instead of a On/Off (0 or 100%) adjustment.

From the authors' file he writes:

  • If none of the above made sense to you, and you would like it to, go to:
  • http://www.controlguru.com . Dr. Cooper was my controls professor, and is
  • gifted at concisely and clearly explaining PID control

I will be using it to accurately control stepped temperatures over a period of time.

Larry's example is a good one.

I wanted to jump in to keep Chris from possibly becoming scared after visiting Dr. Cooper's site. That link was put there more to answer the question: "ok, I kind of get pid and have used it, but how does it WORK"

to answer the more simple question of "why use pid?" maybe it will help to look at something that is not pid: the kitchen stove.

when you set your oven to 350 degF, that's not actually what you get. the oven actually cycles above and below that by maybe as much as 10 degrees. when you get to 340, the burner turns on full blast, and when you get to 360, it shuts off completely. this On/Off style of control is fine for a stove; it all averages out.

if, however, we took that same strategy and put it in a car, it would not work. we would set the speed to 60mph. when we got to 50 we would floor the gas pedal, and at 70 we would let off completely. very uncomfortable.

so what pid lets us do is get an intermediate output value; something other than 0 and 100%. This allows for much tighter control, which is a must for certain applications.

hope this helps,

Brett

would you like to see what a heating system looks like when it only has a bi-metal thermostat and what it looks like after a PID is applied? I built the BBCC system and plotted an espresso pull without the PID enabled and a pull with the PID enabled.

Check out these images:
without the PID enabled:
http://picasaweb.google.com/lh/photo/x68EzW2yrshM0udw0MJfKw

with the PID enabled:
http://picasaweb.google.com/lh/photo/cHzCR15XaT0FJJZeoWLevw

note: I have two heat settings(brew/steam) and in the test run, the temp rises to the first/brew temp and then a short while later I push the button to set the temp to the higher/steam temp. After a short period on steam, I then set the target temp back to the brew temp.

You can see that with the standard bimetal thermostat, the temp swings all over the place around the target temp but with the PID control enabled, there's a small overshoot and a quick recovery and much more stable and steady temperature held.

Doug

Seems to work pretty well even for things that require rather short update intervals (10 ms), for PWM control of a motor with an encoder. I'm not sure if it could run much faster (I haven't attempted to measure the time it takes to execute a cycle).

Is there any chance of an integer version of the library? Integer math would certainly run faster on the ATMega168, since it's doing floating point emulation in software. This might also cut down on footprint, but I would hope that the compiler isn't spitting out copies of all the instructions needed for fp emulation at each stage they are used.

Is there any chance of an integer version of the library?

definitely. everything's on the table. I wrote this library for it to be used, and if there's something that people want in there I'm happy to do it.

to be honest I never thought of doing integer math. I usually use PID control on large systems (think factories,) where 100ms is the fastest a PID controller will ever have to go. I optimized the code, but forgot how much of a hog floating point operations are.

maybe that can be the "lite" version of the library. when I suggested that initially I was assuming that would mean a limited function set, but maybe integer math is all that's necessary.

also, while I'm typing, I'm thinking of including feed-forward capabilities in the next version (or is that "versions" now.)

I'd love to hear feedback on the above, and if anyone has used this library to control something I'd love to hear about that too. it may be helpful if others see how this tool is being used.

How about adding autotune capablity? I know many of the standalone industrial PID controllers have that function and it can save a ton of time when trying to tune a new loop.

How about adding autotune capablity?

sadly, that's one thing I can't do. part of my employment agreement explicitly states that I can't tune loops (or write code that does same) except under the umbrella of my company. somehow writing an entire pid controller and making it freely available is ok though. go figure.

the library is such that someone could write a parallel program to perform autotune manipulations and get some numbers. if anyone decides to take this on (and I don't think it looks violently dangerous) I'd be happy to include it.

Heres a second vote for the integer version, & possibly without the input/output scaling as well.

I'm testing a system to keep two fairly rapid linear actuators synchronised with a master potentiometer & the two PID calculations each loop are sapping a lot of cycles. All I need is a straight 10bit in >> 10 bit out as fast as possible.

I am so pleased to have found the PID Library that you created, br3ttb.

It could be the perfect solution to my current challenge. I have a question regarding the output.

The analogy that you give regarding the cruise control is a nice one, and I understand the beauty of the PID's ability to limit the overshoot by "letting up on the gas."

My basic question is how do I interpret the "Output Value?" What does it represent? It seems to be a "Correction Value" specifically related to the "Input Value" and the "Setpoint."

This may seem obvious, but so far (without using the PID) I have been splitting my sensor input, which is a value between 0-255 at my desired setpoint, roughly the mid-point, and using the values on one side of the setpoint to drive a motor in one direction and the values on the other side of the setpoint to drive the motor in the opposite direction.

Thus, my question...given the one value for Output how should i interpret this value

I imagine that I could split the value and feed it into two separate PID's if that is necessary.

Thanks for any help :smiley:

what I would suggest is to have your output range from negative to positive. (-255 to 255 say) your code would look something like this:

double Input, Output, Setpoint;
 PID pid(&Input, &Output, &Setpoint, -3,4,1);

 void setup()
 {

   pid.SetIOLimits(0,1023,-255,255); //tell the PID to range the output from -255 to 255 
   Output = 0; //start the output "motor stopped" and vary from there

   pid.SetMode(AUTO); //turn on the PID
 }


 void loop()
 {
   //give the PID the opportunity to compute if needed
   Input = //whatever your input is
   pid.Compute();

    if (Output>0)
    {
    //spin the motor one way at speed = Output
    }
    else if(Output<0)
    {
    //spin the motor the other way at speed = -1* Output
    }
    else
    {
    //motor stopped
    }
 }

hope that helps, Brett

Thanks so much, Brett.

I will try this solution.

Aaron

Why is it so hard to find the PID Library in the playground? there seems to be no link to it at all or am i being dumb? :-/

Modesty mostly. and fear. I didn't want to presume to add my library to the lexicon. at least not until I made sure that there weren't glaring errors I had missed. it's been about 2 months now, so I feel a little more comfortable adding it. here you go: Arduino Playground - GeneralCodeLibrary