diff options
| author | James Feist <james.feist@linux.intel.com> | 2019-01-31 15:52:22 -0800 |
|---|---|---|
| committer | James Feist <james.feist@linux.intel.com> | 2019-02-05 11:30:05 -0800 |
| commit | 572c43dab62f9e207781b96e7e48b7b38ca024e5 (patch) | |
| tree | 137db460c1d23e7a620a78b8a8cf8dd86891eeb8 /pid | |
| parent | 1738e2a2b705f64e0c823b095b504dfe397a87ab (diff) | |
| download | phosphor-pid-control-572c43dab62f9e207781b96e7e48b7b38ca024e5.tar.gz phosphor-pid-control-572c43dab62f9e207781b96e7e48b7b38ca024e5.zip | |
Add Hysteresis to pid controllers
Add hysteresis to pid controllers to lower pwm changes.
It is defaulted to 0 so it should be transparent
to any controller that choses not to implement it.
This is the same pattern used by the stepwise controller.
Tested-by: Unit tests passed
Change-Id: Ib47114285b0017258b7f77eaf067d310f95a0c60
Signed-off-by: James Feist <james.feist@linux.intel.com>
Diffstat (limited to 'pid')
| -rw-r--r-- | pid/ec/pid.hpp | 4 | ||||
| -rw-r--r-- | pid/pidcontroller.cpp | 36 | ||||
| -rw-r--r-- | pid/pidcontroller.hpp | 6 | ||||
| -rw-r--r-- | pid/util.cpp | 2 |
4 files changed, 46 insertions, 2 deletions
diff --git a/pid/ec/pid.hpp b/pid/ec/pid.hpp index 779ced5..3ab64cd 100644 --- a/pid/ec/pid.hpp +++ b/pid/ec/pid.hpp @@ -31,6 +31,8 @@ typedef struct limits_t out_lim; // clamp of output double slew_neg; double slew_pos; + double positiveHysteresis; + double negativeHysteresis; } pid_info_t; double pid(pid_info_t* pidinfoptr, double input, double setpoint); @@ -47,6 +49,8 @@ struct pidinfo ec::limits_t out_lim; // clamp of output double slew_neg; double slew_pos; + double positiveHysteresis; + double negativeHysteresis; }; } // namespace ec diff --git a/pid/pidcontroller.cpp b/pid/pidcontroller.cpp index 7be6ceb..e3eaaff 100644 --- a/pid/pidcontroller.cpp +++ b/pid/pidcontroller.cpp @@ -20,6 +20,7 @@ #include <algorithm> #include <chrono> +#include <cmath> #include <iostream> #include <map> #include <memory> @@ -38,8 +39,39 @@ void PIDController::process(void) // Get input value input = inputProc(); - // Calculate new output - output = ec::pid(getPIDInfo(), input, setpt); + auto info = getPIDInfo(); + + // if no hysteresis, maintain previous behavior + if (info->positiveHysteresis == 0 && info->negativeHysteresis == 0) + { + // Calculate new output + output = ec::pid(info, input, setpt); + + // this variable isn't actually used in this context, but we're setting + // it here incase somebody uses it later it's the correct value + lastInput = input; + } + else + { + // initialize if not set yet + if (std::isnan(lastInput)) + { + lastInput = input; + } + + // if reading is outside of hysteresis bounds, use it for reading, + // otherwise use last reading without updating it first + else if ((input - lastInput) > info->positiveHysteresis) + { + lastInput = input; + } + else if ((lastInput - input) > info->negativeHysteresis) + { + lastInput = input; + } + + output = ec::pid(info, lastInput, setpt); + } // Output new value outputProc(output); diff --git a/pid/pidcontroller.hpp b/pid/pidcontroller.hpp index 9ed3be2..3d38c2a 100644 --- a/pid/pidcontroller.hpp +++ b/pid/pidcontroller.hpp @@ -49,6 +49,11 @@ class PIDController : public Controller return &_pid_info; } + double getLastInput(void) + { + return lastInput; + } + protected: ZoneInterface* _owner; @@ -57,4 +62,5 @@ class PIDController : public Controller ec::pid_info_t _pid_info; double _setpoint; std::string _id; + double lastInput = std::numeric_limits<double>::quiet_NaN(); }; diff --git a/pid/util.cpp b/pid/util.cpp index 9d666ef..a5936b0 100644 --- a/pid/util.cpp +++ b/pid/util.cpp @@ -34,6 +34,8 @@ void initializePIDStruct(ec::pid_info_t* info, const ec::pidinfo& initial) info->out_lim.max = initial.out_lim.max; info->slew_neg = initial.slew_neg; info->slew_pos = initial.slew_pos; + info->negativeHysteresis = initial.negativeHysteresis; + info->positiveHysteresis = initial.positiveHysteresis; } void dumpPIDStruct(ec::pid_info_t* info) |

