br3ttb / Arduino-PID-Library

1.91k stars 1.1k forks source link

Derivative Kick #77

Open terryjmyers opened 6 years ago

terryjmyers commented 6 years ago

As per your article: http://brettbeauregard.com/blog/2011/04/improving-the-beginner%E2%80%99s-pid-derivative-kick/ You've choosen to do D on input. Most modern PID controllers use D on error. I think the kick experienced when a setpoint is changed can be easily solved by simply disabling dInput (set it to 0) whenever there is a setpoint change:

Code to insert as line 69: if (*mySetpoint != mySetpointREM) dInput = 0.0

Code to insert as line 91 to determine if change: mySetpointREM = *mySetpoint

You'd also add the above to Initiaize() and of course make mySetpointREM a private DOUBLE.

terryjmyers commented 6 years ago

This would of course not work with your implementation of the Velocity form equation( the p_on_e business). Derivative smoothing could also be implemented which is a feature on many Industrial PID control algorithms. A simple low pass filter would work well. There's a site I've used to create the code for low pass filters, I'll posted later. But a filter with a time constant of four or five computes would work

br3ttb commented 6 years ago

Can you give me an example of a modern controller that uses DonE by default? DonE came first. all the ones I've seen that have a DonM option (Rockwell PIDE instruction, for example,) have it enabled by default.

E and M are mathematically equivalent in all cases other than when dSP!=0. So what you've just proposed is an algorithm that would have the EXACT same performance as DonM, but using an extra variable and if statement instead of just inlining the solution with no additional logic/computation. doesn't seem like an improvement to me, but to each their own.

On Mon, Apr 16, 2018 at 4:18 PM Terry J Myers notifications@github.com wrote:

As per your article: http://brettbeauregard.com/blog/2011/04/improving-the-beginner%E2%80%99s-pid-derivative-kick/ You've choosen to do D on input. Most modern PID controllers use D on error. I think the kick experienced when a setpoint is changed can be easily solved by simply disabling dInput (set it to 0) whenever there is a setpoint change:

Code to insert as line 69: if (*mySetpoint != mySetpointREM) dInput = 0.0

Code to insert as line 91 to determine if change: mySetpointREM = *mySetpoint

You'd also add the above to Initiaize() and of course make mySetpointREM a private DOUBLE.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/br3ttb/Arduino-PID-Library/issues/77, or mute the thread https://github.com/notifications/unsubscribe-auth/AAWL8g-6VeoxZzJeTnlyVsv1JY83mFMhks5tpPx2gaJpZM4TXMAf .

terryjmyers commented 6 years ago

Rockwell controllogix pid(not pide which is only available in a fb, and uses the Velocity form anyway) ladder function uses d on e by default. What you've implemented is the independent form of the PID equation. Have you considered using the dependent form? There are some major advantages such as having the i&d term model dependent, then just having to adjust proportional based on how critically damped the response is

terryjmyers commented 6 years ago

I'm really not trying to knock your code, I'm merely trying to better understand the design decisions behind it so I can adapt it to my project. FYI I'm no PID slouch. I'm a professional Control Systems engineer with a decade of experience, I give PID tuning seminars professionally. I've developed my own tuning tools(https://www.eevblog.com/forum/projects/pid-tuning-spreadsheet/), and was even featured in a recent PID YouTube video by GreatScott. I understand the math behind all of the various transfer functions, I've just never had to implement the algorithm in c code. So I'm trying to adopt my practical knowledge to what I see here for a personal project(reflow oven)

br3ttb commented 6 years ago

right. The pide instruction is the modern version (donm,) pid instruction is the old one (donE.)

I agree that dependent form is better. The first version of the arduino library (beta6) used that, and easily 80% of the questions I fielded were from beginners not understanding why it was different from what was on Wikipedia. I decided it wasn't worth it. If you want the dependent form you can easily modify the settunings function to convert dependent parameters to independent internals.

On Mon, Apr 16, 2018, 4:51 PM Terry J Myers notifications@github.com wrote:

Rockwell controllogix pid ladder function uses d on e by default. What you've implemented is the independent form of the PID equation. Have you considered using the dependent form? There are some major advantages such as having the i&d term model dependent, then just having to adjust proportional based on how critically damped the response is

— You are receiving this because you commented.

Reply to this email directly, view it on GitHub https://github.com/br3ttb/Arduino-PID-Library/issues/77#issuecomment-381744986, or mute the thread https://github.com/notifications/unsubscribe-auth/AAWL8rsNk2RQnjwqSX0oHl-8Af0Au2Lbks5tpQQ9gaJpZM4TXMAf .

terryjmyers commented 6 years ago

Yes the pide is the more "modern" version. However, I haven't found any system that I couldn't tune to within a inch of its life using the ladder pid function block. And believe me, I can guarantee that if you live anywhere in the US I've tuned loops that have made products you use/eat every day :). I've only wrapped the pide fb up into a udf in order to utilize the auto-tune bump test feature. But 95% of the time I use my spreadsheet(https://www.dropbox.com/s/vzbc1h9yfr6kz67/PID%20tuning.xlsx?dl=0) with an open loop method to determine I and D, then a closed loop method to determine my critical gain, then just lower gain until I get the response I want. The other 5% I'll use TuneWizard. I also got a lot of pushback from other engineers in my company when I pushed for dependent as a standard. But after a while they all gave in after I showed them how I and D can be determined mathematically and simply..then just find the right gain that suites the process.

I'm going to mess around with the library a bit to see if I can properly convert it into dependent gains so I can use my spreadsheet (after I fork a version for seconds vs minutes).

It still might be good to add some derivative smoothing though. I'm not sure if the pide does this, but using this: http://www.schwietering.com/jayduino/filtuino/ with a Butterworth LPF filter, 0.05 alpha creates the following code:


//Low pass butterworth filter order=1 alpha1=0.05 
class  FilterBuLp1
{
    public:
        FilterBuLp1()
        {
            v[0]=0.0;
        }
    private:
        float v[2];
    public:
        float step(float x) //class II 
        {
            v[0] = v[1];
            v[1] = (1.367287359973195227e-1 * x)
                 + (0.72654252800536101020 * v[0]);
            return 
                 (v[0] + v[1]);
        }
};

This LPF has a time constant of 4 steps (or 4 calls of compute). I'm going to play around with it to see if its any use.
I created some code that simulated dead time (just a FIFO stack), and using a much longer filter like above to create the lag to simulate a process so I can easily test the pid performance.

br3ttb commented 6 years ago

This is is all well and good, but is off topic from your original assertion that your code (or donE in general,) are an improvement over what's in there now. If you still feel that is the case, please respond to my pushback above (identical performance with messier code.) Otherwise please close this issue.

On Mon, Apr 16, 2018, 9:07 PM Terry J Myers notifications@github.com wrote:

Yes the pide is the more "modern" version. I haven't found any control system that the ladder pid function block could not take care of. I've only wrapped the pide fb up into a udf in order to utilize the auto-tune bump test feature. But 95% of the time I use my spreadsheet( https://www.dropbox.com/s/vzbc1h9yfr6kz67/PID%20tuning.xlsx?dl=0) with an open loop method to determine I and D, then a closed loop method to determine my critical gain, then just lower gain until I get the response I want. The other 5% I'll use TuneWizard. I also got a lot of pushback from other engineers in my company when I pushed for dependent as a standard. But after a while they all gave in after I showed them how I and D can be determined mathematically and simply..then just find the right gain that suites the process.

I'm going to mess around with the library a bit to see if I can properly convert it into dependent gains so I can use my spreadsheet (after I fork a version for seconds vs minutes).

It still might be good to add some derivative smoothing though. I'm not sure if the pide does this, but using this: http://www.schwietering.com/jayduino/filtuino/ with a Butterworth LPF filter, 0.05 alpha creates the following code:

//Low pass butterworth filter order=1 alpha1=0.05 class FilterBuLp1 { public: FilterBuLp1() { v[0]=0.0; } private: float v[2]; public: float step(float x) //class II { v[0] = v[1]; v[1] = (1.367287359973195227e-1 * x)

  • (0.72654252800536101020 * v[0]); return (v[0] + v[1]); } };

This LPF has a time constant of 4 steps (or 4 calls of compute). I'm going to play around with it to see if its any use. I created some code that simulated dead time (just a FIFO stack), and using a much longer filter like above to create the lag to simulate a process so I can easily test the pid performance.

— You are receiving this because you commented.

Reply to this email directly, view it on GitHub https://github.com/br3ttb/Arduino-PID-Library/issues/77#issuecomment-381797081, or mute the thread https://github.com/notifications/unsubscribe-auth/AAWL8p07eHyZfP3bp3gWOtDUBvLPnLCOks5tpUBAgaJpZM4TXMAf .

JakeSays commented 3 years ago

@terryjmyers I found this to be quite informative. Do you have more information I could study?