Dlloydev / QuickPID

A fast PID controller with multiple options. Various Integral anti-windup, Proportional, Derivative and timer control modes.
MIT License
195 stars 50 forks source link

Autotune with float params and output step #14

Closed sorinescu closed 3 years ago

sorinescu commented 3 years ago

Hi,

Awesome job on the library! I'm implementing a PID-enabled heating app, where the temperature is a float value. I'd like to use the autotuner but it has two drawbacks:

I could solve this by doing the output and parameter scaling in my code, but it would be nicer to do it in the library. I'd be happy to contribute a PR if you agree.

Dlloydev commented 3 years ago

Thank you!

I currently have the output step adjustable but with 5 as minimum which came about from tests on an UNO with RC filter. This could easily be changed to float with the minimum limitation removed. Other autotune parameters could also be changed to float where required. I'll be happy to look at a pull request anytime and agree this would be nicer to implement in the library.

Dlloydev commented 3 years ago

New release QuickPID 2.4.5

sorinescu commented 3 years ago

Wow, that was fast :) Thank you!

sorinescu commented 3 years ago

There's one more problem at https://github.com/Dlloydev/QuickPID/blob/master/src/QuickPID.cpp#L304

T1 is the moment when the input is _atSetpoint + 0.2 which is an arbitrary value. I was planning to add a set of parameters like inputAccuracyFactor and inputAccuracyConstant to allow a calculation like _atSetpoint + _atSetpoint*inputAccuracyFactor + inputAccuracyConstant.

This would work with sensors that have either a "full scale" error (like 0.5 degrees Celsius over the measurement range) or a "percentage of reading" error (like 0.5% or the measured value) or a combination of both.

Dlloydev commented 3 years ago

Thanks for your reply.

The _atSetpoint + 0.2 value was to determine if the input is responding and increasing in value. If so, then t1 is recorded which is used to calculate deadtime. Previously while working with integers and having 16 input readings averaged (in the sketch), it would mean that at least 2 readings were greater than the setpoint.

There might be a simpler way to accomplish the same thing while working with floats and not require a set of new parameters. Basically, just testing if the input has increased past the setpoint, then, on the next iteration check if the current input value has increased past the previous input reading.

This works well on my system (RC filter), so I've pushed a commit. Looking forward to hearing if this works with your PID-enabled heating app.

sorinescu commented 3 years ago

It looks good and it's indeed simpler. I'll let you know how it goes 👍