Arduino PID Library

br3ttb,

You might want to include a default constructor in your next build. This might be my lack of experience with this platform but the following would not compile:

include <WProgram.h> 
include<PID_Beta6.h>
class foo{
public:
PID myPID;
}

Apparently it would not compile b/c it could not find a matching function call to PID();

I am new to this particular platform, so I could be missing something, however to get this to work in my class I had add the default constructor to your code and recompile.

Otherwise your package looks good.

I never considered that people would be embedding my class into another class. COOL!

The reason I didn't go with a default constructor is that for the pid to run correctly, it HAS to have the things specified in the current constructor (input, output, setpoint, tuning parameters.) I figured that would be a gentle way to get people to specify them.

maybe a middle of the road option would be to include a default constructor but have it commented out? if you're writing a new class you'll likely have the know-how to find/ uncomment. if you're the standard Arduino user you'll notice no change. thoughts?

Brett

[his example 1]


  • PID Simple Example
  • Reading analog input 0 to control analog PWM output 3
    ********************************************************/

#include <PID_Beta6.h>

//Define Variables we'll be connecting to
double Setpoint, Input, Output;

//Specify the links and initial tuning parameters
PID myPID(&Input, &Output, &Setpoint,2,5,1);

void setup()
{
//initialize the variables we're linked to
Input = analogRead(0);
Setpoint = 100;

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

void loop()
{
Input = analogRead(0);
myPID.Compute();
analogWrite(3,Output);
}


[Your non-working example]
include <WProgram.h>
include<PID_Beta6.h>
class foo{
public:
PID myPID;
}


I guess I don't understand your critique - your example stuff doesn't look like his example stuff????

Can you 'splain the problem in words of at most two syllables? :slight_smile:

Brian W

Class? The only thing I recall about class is that if your late too often you could receive saturday detention. :wink:

Lefty

Brian:

psyber is using the library in a way I never even considered. Most people will take the pid library and use it right in their Arduino program, the way my example illustrates.

the way I understand it, psyber encountered a problem trying to embed a pid within a library of his own creation. On the library creation side, the rules are a little different. To make it work, he needed to -very lightly- massage the pid library code. His suggestion was aimed at saving the next guy some trouble.

Lefty: This is all I know about class :wink: : Sidney Poitier - IMDb

Brett

Here is another vote for making it easier to embed the PID library in another class. I was in the process of creating a motor control class which would embed a PID controller to set the PWM signal to the motor when I saw psyber's post.

Edit:
It may not be necessary to add a default constructor. I haven't tested this yet but it does compile.

test.pde

#include<PID_Beta6.h>
#include "foo.h"

foo myFoo;

setup()
{
}

loop()
{
}

foo.h

class foo
{
public:
   foo();

   PID myPID;
   double Input;
   double Output;
   double Setpoint;
}

foo.cpp

#include "PID_Beta6.h"
#include "foo.h"

foo::foo() : myPID(&Input, &Output, &Setpoint,2,5,1)
{
   // initialize foo
}

I had to look up initialization lists, in my real life I've never used them. In another environment I'd include a pointer to a PID object in my class and use new to create it in the constructor.

I has use this libary to control angle of robot arm, it work as well on fixed setpoint.

if my setpoint is change it will not go to setpoint, it have offset. i try to increase D parameter, i would not help.

i guess my problem is my motor start moving at PWM 80%. when is start moving it's very fast and on next sampling it already overshoot.

anyone have some idea to slove this. :wink:

on next sampling it already overshoot. anyone have some idea to slove this.

you can use the SetSampleTime() function to make the pid sample more quickly. (Arduino Playground - PIDLibraryAdvancedMethods)

Brett

I want to make a motor controller that uses distance as the target but is able to accelerate until reaches a certain speed (sometimes is max speed), continue with that speed until almost at destination and decelerate until it reaches the target distance and stops. Sometimes I need to make small adjustments and speed never reaches the set speed and needs to decelerate because it reaches the destination.
Any advices on how to do that?
Thanks.

Can this PID library include a function to accelerate from 0 to SetSpeed and continue at that speed until the SetPoint is reached (because it will automatically decelerate before reaching the SetPoint)?

I have tried to do a function that accelerates until Speed = SetSpeed and only then activate the PID controller, but sometimes I need to make small corrections so the Speed never reaches SetSpeed. Can this be done in the PID controller?

I don't think so. the pid is a "simple" control element whose job is to make Input = Setpoint. once you want to do more complicated things, you'll need to make the pid part of a larger control strategy. it sounds like that's what you're trying to do anyway, so let's talk about that.

First, I'm not sure I completely understand your application. You use both SetSpeed and SetPoint in your question. I'm would assume that Speed is the output from the pid, and Setpoint is the value you want the PID Input to achieve. I'm not sure though.

I don't want to give you bad advice at this point. Could you give a description of what it is you're trying to do in the real world (i.e. "I've got this thermonuclear jetpack, and I'm tyring to control take-off velocity. my inputs and outputs are...") I'll be able to give better advice once I know what it is you're trying to do.

Brett

foo.cpp
Code:

#include "PID_Beta6.h"
#include "foo.h"

foo::foo() : myPID(&Input, &Output, &Setpoint,2,5,1)
{
// initialize foo
}

I had to look up initialization lists, in my real life I've never used them. In another environment I'd include a pointer to a PID object in my class and use new to create it in the constructor.

Nice! I figured there was some way to do it without monkeying around with the original library. I just wish there was a more intuitive method as my C/C++ is extremely rusty. I don't think this is covered in any of my old textbooks either. >:(

br3ttb:
As for the middle ground solution, I see no difference between you adding the code and then commenting it out, and having a developer simply add the code. In either case someone still has to edit the class and rebuild the library.

I hate to resurrect this old thread, but it is a good one, and the PID software looks really good.

Before finding this thread, I wrote my own. I was particularly interested to see how wind-up was handled. I saw that the Integral term was not incremented when the output was maxed.

This seems like a great idea, but doesn't it cause a bit of a glitch when the output drops down from max? Maybe the integral term is well below the value resulting in maximum output due to some other factor such as the differential.

Is this really going to make much of a glitch under these circumstances? I suspect that a "properly" tuned loop will not have such odd behaviour that the differential can push the output that far up/down.

I attempted to limit wind-up by not allowing the integral term to exceed the value that results in full output on its own. Is this not good enough?

-Tony

doesn't it cause a bit of a glitch when the output drops down from max?

I haven't noticed this. the inclusion of the (err>0) and (err<0) are supposed to (and seem to) keep this from happening

limit wind-up by not allowing the integral term to exceed the value that results in full output on its own. Is this not good enough?

the short answer is "yes." It's not as simple with the form of the pid I'm using, because I have a bias term in the mix. I'm in the process of migrating the library toward the method you describe.

Brett

Brett, nice library and easy to use and tidies up my code nicely. Any news on the 'lite'version for basic functionality?

Cheers,
Mike

Any news on the 'lite'version for basic functionality?

I've actually decided to ditch the idea of a lite version. Instead I'm working on reducing the footprint of the full version. The next revision of the library is almost done. it uses integer math throughout, so it's about half the size and 10X faster.

Brett

[edit]On second thought I may be able to add some preprocessor flags to remove a lot of the extra functionality, resulting in a lite library. I'll see what I can do[/edit]

Sounds brill! Look forward to using it.

Mike

Before everything... It's just an advice,I don't want to look pretentious... :-[
I don't understand why you have problems making your PID faster....maybe because I've never used it :stuck_out_tongue: . Sometimes the measurement is not at the same frequency than the Computing frequency, maybe you can't achieve the maximum speed because you are not using timer interrupts, and almost every PID ready-to-use software made by big companies uses timer interrupts. When you use timer interrupts the only limit is the clock speed and the timer's pre-escalator, ahh one last thing, the common acronyms are:
Set Point, (SP)
input: PV (Present Value)
output: MV(manipulated variable)
error
dt : (delta t) that's what you call calc period
Kp
Ki,Ti (I prefer Ki than Ti, where Ki=Kp/Ti)
Kd,Td (same with Kd, Kd=Kp*Td)

EDIT: PV: process variable

input: PV (Present Value)

I was taught that PV = Process Variable

Lefty

I was taught that PV = Process Variable

Ditto.

Of course you are right, PV is process variable, there is a present value, but that is not it. :wink: LOL