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 e2ab839..4c38e3e 100644 --- a/lib/oven.py +++ b/lib/oven.py @@ -128,7 +128,8 @@ class TempSensorReal(TempSensor): except Exception: log.exception("problem reading temp") time.sleep(sleeptime) - self.temperature = sum(temps)/len(temps) + if len(temps) > 0: + self.temperature = sum(temps)/len(temps) class Oven(threading.Thread): '''parent oven class. this has all the common code @@ -411,7 +412,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 @@ -424,9 +430,6 @@ class PID(): if output < 0: output = 0 - #if output > 1: - # output = 1 - output = float(output / window_size) self.pidstats = { @@ -445,11 +448,14 @@ class PID(): 'pid': out4logs, 'out': 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 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