From d60cc535d0b18d66b0ae8f4784e5bde4e74d82c9 Mon Sep 17 00:00:00 2001 From: Jason Bruce Date: Fri, 30 Apr 2021 20:27:19 -0400 Subject: [PATCH] adding support to prevent integral windup --- config.py | 13 +++++++++++++ lib/oven.py | 22 ++++++++++++++-------- 2 files changed, 27 insertions(+), 8 deletions(-) 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/lib/oven.py b/lib/oven.py index 5d0f0ef..da6f2d4 100644 --- a/lib/oven.py +++ b/lib/oven.py @@ -410,7 +410,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 @@ -423,15 +428,16 @@ class PID(): if output < 0: output = 0 - #if output > 1: - # output = 1 - output = float(output / window_size) 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 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