diff --git a/config.py b/config.py index 293aed7..10d3a24 100644 --- a/config.py +++ b/config.py @@ -62,6 +62,19 @@ pid_ki = 200 # Integral pid_kd = 200 # Derivative +######################################################################## +# +# Initial heating and Integral Windup +# +# During initial heating, if the temperature is constantly under the +# setpoint,large amounts of Integral can accumulate. This accumulation +# causes the kiln to run above the setpoint for potentially a long +# period of time. These settings allow integral accumulation only when +# the temperature is within stop_integral_windup_margin percent below +# or above the setpoint. This applies only to the integral. +stop_integral_windup = True +stop_integral_windup_margin = 10 + ######################################################################## # # Simulation parameters diff --git a/docs/pid_tuning.md b/docs/pid_tuning.md index 1a0f613..c90ad9f 100644 --- a/docs/pid_tuning.md +++ b/docs/pid_tuning.md @@ -50,5 +50,5 @@ Now, run the test schedule again and see how well it works. Expect some oversho * only change one value at a time, then test it. * If there is too much overshoot, decrease pid_kp. -* If the temp is always below the set point, increase pid_ki. +* If the temp is always below the set point, decrease pid_ki (which increases the integral action). * if the above does not work, try the Ziegler / Nichols method https://blog.opticontrols.com/archives/477 diff --git a/lib/oven.py b/lib/oven.py index 141997d..e8c0c30 100644 --- a/lib/oven.py +++ b/lib/oven.py @@ -429,7 +429,12 @@ class PID(): error = float(setpoint - ispoint) if self.ki > 0: - self.iterm += (error * timeDelta * (1/self.ki)) + if config.stop_integral_windup == True: + margin = setpoint * config.stop_integral_windup_margin/100 + if (abs(error) <= abs(margin)): + self.iterm += (error * timeDelta * (1/self.ki)) + else: + self.iterm += (error * timeDelta * (1/self.ki)) dErr = (error - self.lastErr) / timeDelta output = self.kp * error + self.iterm + self.kd * dErr @@ -442,11 +447,16 @@ class PID(): if output < 0: output = 0 - #if output > 1: - # output = 1 - output = float(output / window_size) - log.info("pid temp==%0.2f set=%0.2f err=%0.2f p=%0.2f i=%0.2f d=%0.2f pid=%0.2f out=%0.2f" % (ispoint, setpoint, error, self.kp * error, self.iterm, self.kd * dErr, out4logs, output)) + if out4logs > 0: +# log.info("pid percents pid=%0.2f p=%0.2f i=%0.2f d=%0.2f" % (out4logs, +# ((self.kp * error)/out4logs)*100, +# (self.iterm/out4logs)*100, +# ((self.kd * dErr)/out4logs)*100)) + log.info("pid actuals pid=%0.2f p=%0.2f i=%0.2f d=%0.2f" % (out4logs, + self.kp * error, + self.iterm, + self.kd * dErr)) return output