summaryrefslogtreecommitdiffstats
path: root/pid
diff options
context:
space:
mode:
authorJames Feist <james.feist@linux.intel.com>2019-01-31 15:52:22 -0800
committerJames Feist <james.feist@linux.intel.com>2019-02-05 11:30:05 -0800
commit572c43dab62f9e207781b96e7e48b7b38ca024e5 (patch)
tree137db460c1d23e7a620a78b8a8cf8dd86891eeb8 /pid
parent1738e2a2b705f64e0c823b095b504dfe397a87ab (diff)
downloadphosphor-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.hpp4
-rw-r--r--pid/pidcontroller.cpp36
-rw-r--r--pid/pidcontroller.hpp6
-rw-r--r--pid/util.cpp2
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)
OpenPOWER on IntegriCloud