Pages: 1 [2] 3 4 ... 9   Go Down
Author Topic: Arduino PID Library  (Read 49522 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 9
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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-grin



 

Logged

Boston
Offline Offline
Full Member
***
Karma: 0
Posts: 101
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
Code:
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
« Last Edit: January 14, 2009, 09:32:22 am by br3ttb » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 9
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks so much, Brett.

I will try this solution.

Aaron
Logged

London, England
Offline Offline
Edison Member
*
Karma: 4
Posts: 1026
Go! Go! Arduinoooo !!!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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?  :-/
Logged

Boston
Offline Offline
Full Member
***
Karma: 0
Posts: 101
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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:  http://www.arduino.cc/playground/Main/GeneralCodeLibrary
Logged

London
Offline Offline
Tesla Member
***
Karma: 10
Posts: 6250
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

br3ttb, no need to be modest smiley-wink

I did some minor editing to the font sizes to make the page a little easier to read, hope you don't mind.
« Last Edit: January 15, 2009, 10:44:27 am by mem » Logged

London, England
Offline Offline
Edison Member
*
Karma: 4
Posts: 1026
Go! Go! Arduinoooo !!!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Ahh glad it wasn't me being dumb then smiley-wink

Nice to see it up there for all to see smiley
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 11
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Here's another vote for the int version.  

I'm currently trying to use your library to control motor speeds for a robot.  I haven't gotten everything working correctly yet, but I'm concerned that the arduino will not be able to run the methods in this library and still process interrupts at the required frequency (as high as 1700kHz)?  How is this done on and industrial motor controller?  Do they do the PID math on the physical motor controller, or is it done elsewhere on a main processor?
Logged

Boston
Offline Offline
Full Member
***
Karma: 0
Posts: 101
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I want to make sure we're on the same page here.  for simplicity's sake, I set up the library so you call .Compute() every cycle.  most of the time, the library says "I don't need to recalculate yet" and immediately spits back to the calling routine.  the recalculation happens at 1Hz by default, but can be adjusted to be slower or faster using the SetCalcFrequency function.

so most of the time Compute() kicks back "instantly."  I don't think there's an interrupt problem there.  however, on the cycles where recalculation is occurring I think there may be. I did some bench tests before I published the library the calc speed was about 12 microseconds (8.3kHz.)  so it may be possible, if the interrupt pulse is faster than that, and it comes while the pid is calculating, the signal may be missed.

I have no idea how this is done in motor controllers.  my experience is on slower moving stuff, and as a consequence it's not a problem for the pid to be "slow" as well.

I am currently working on an integer version of the library (and the crowd goes wild.)  it's not going to be anywhere as feature rich as the "full" version, but hopefully it will be much, much faster.  

Brett
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 11
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

That's kinda what I was thinking but this clarifies it much more.  I think you may right about the possibility of missing pulses while in a calculation but that's one of the many pitfalls of dead-reckoning navigation.  However, I don't think it's going to be a big problem because I think my overall error from other factors will outweigh the lost counts here and there.  It sounds like your 'full' library may work but I bet the 'lite/int' version would work a lot better!!   smiley-wink

Thanks, this has been a big help to me!
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 74
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This is great!  Thanks so much, I am going to try it out soon on an oven controller.  I'll let you know how it works out.
Logged

Australia
Offline Offline
Jr. Member
**
Karma: 0
Posts: 99
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I don't mean to nag, but that SetCalcFrequency() really needs to be changed to SetCalcPeriod(). Likewise GetCalcFreq().

IMO it's important to avoid misleading function names, particularly early in the library lifecycle, before the installed base is too large, and there's too much traction.

Apart from that it's a great library.
« Last Edit: January 27, 2009, 06:52:12 pm by crimony » Logged

Boston
Offline Offline
Full Member
***
Karma: 0
Posts: 101
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks!

I think nag might be a little strong.  I've taken it as a gentle reminder.  smiley

I'm working on the integer (or "lite") form.  I'll release it bundled with the pid library, and on both I'm planning on renaming it as "SampleTime", in keeping with the industry standard.

-Brett
Logged

Boston
Offline Offline
Full Member
***
Karma: 0
Posts: 101
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

ok, so I finished (or thought I finished) the integer form, and I wasn't happy.  it was only 1k smaller and 30% faster.  not good enough.  I'm going to keep working on it, but unfortunately it's going to be a while.

in the mean time, the 0.5 beta has been sitting there with it's flaws. So... I've decided to upload the next version of the beta (v0.6) without the promised integer library.  sorry about that.

at any rate, with the bad news out of the way, let's talk about the good news.  updated pid library!  bonus!  I took care of the obvious (and less obvious) snags with the library, and added a very powerful advanced feature.

"snag" fixes:
* CalcFrequency has been changed to SampleTime.  finally.
* The library now has a version-specific name: <PID_Beta6.h>  This way, you can put up your code, and even 4 years (and 20 revisions) from now, everyone will know which version of the library you used.
* I felt that SetIOLimits was a bit confusing, since for the most part,  the input limits will never be changed.  I decided to split it into two functions:  SetInputLimits and SetOuputLimits.  The output limit function was left on the standard function page, while the input limit function is now hidden on the advanced page.

advanced feature:  
Feed Forward.  good lord is this powerful.  essentially it lets you add your own knowledge to what the pid is doing.  so, if you know that the controller is about to get hit with a major disturbance, you can help it along, and address the disturbance far more effectively than using just pid alone.

take a second to look at the updated wiki (http://www.arduino.cc/playground/Code/PIDLibrary) and let me know if I missed anything!

Brett
Logged

Left Coast, CA (USA)
Offline Offline
Brattain Member
*****
Karma: 361
Posts: 17263
Measurement changes behavior
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for your effort on this. One question I have is how would one best invoke a reverse action control function, as required in industrial controllers for working with fail open and fail close control valves?

Thanks
Lefty
Logged

Pages: 1 [2] 3 4 ... 9   Go Up
Jump to: