adding pid_control_window parameter, removing stop_integral_windup parameter, fixed api bug
This commit is contained in:
parent
8a3cd4253e
commit
6e6c56d3a4
34
config.py
34
config.py
@ -13,7 +13,7 @@ log_format = '%(asctime)s %(levelname)s %(name)s: %(message)s'
|
||||
|
||||
### Server
|
||||
listening_ip = "0.0.0.0"
|
||||
listening_port = 8081
|
||||
listening_port = 8082
|
||||
|
||||
### Cost Estimate
|
||||
kwh_rate = 0.1319 # Rate in currency_type to calculate cost to run job
|
||||
@ -73,11 +73,8 @@ 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 close to the setpoint. This applies only to the integral.
|
||||
# this setting is deprecated and is no longer used. this happens by
|
||||
# default and is the expected behavior.
|
||||
stop_integral_windup = True
|
||||
|
||||
########################################################################
|
||||
@ -88,7 +85,7 @@ sim_t_env = 60.0 # deg C
|
||||
sim_c_heat = 100.0 # J/K heat capacity of heat element
|
||||
sim_c_oven = 5000.0 # J/K heat capacity of oven
|
||||
sim_p_heat = 5450.0 # W heating power of oven
|
||||
sim_R_o_nocool = 0.1 # K/W thermal resistance oven -> environment
|
||||
sim_R_o_nocool = 0.1 # K/W thermal resistance oven -> environment
|
||||
sim_R_o_cool = 0.05 # K/W " with cooling
|
||||
sim_R_ho_noair = 0.1 # K/W thermal resistance heat element -> oven
|
||||
sim_R_ho_air = 0.05 # K/W " with internal air circulation
|
||||
@ -112,18 +109,19 @@ time_scale_profile = "m" # s = Seconds | m = Minutes | h = Hours - Enter and vi
|
||||
# this should not replace you watching your kiln or use of a kiln-sitter
|
||||
emergency_shutoff_temp = 2264 #cone 7
|
||||
|
||||
# If the kiln cannot heat or cool fast enough and is off by more than
|
||||
# kiln_must_catch_up_max_error the entire schedule is shifted until
|
||||
# the desired temperature is reached. If your kiln cannot attain the
|
||||
# wanted temperature, the schedule will run forever. This is often used
|
||||
# for heating as fast as possible in a section of a kiln schedule/profile.
|
||||
# NOTE: every time the kiln goes outside the window around the set point
|
||||
# [by default 5 degrees above and five degrees below] the accumulated
|
||||
# intergral will be zeroed out. If this were not done, there could be
|
||||
# large build-ups of integral that makes it appear the system is not
|
||||
# operating.
|
||||
# If the current temperature is outside the pid control window,
|
||||
# delay the schedule until it does back inside. This allows for heating
|
||||
# and cooling as fast as possible and not continuing until temp is reached.
|
||||
kiln_must_catch_up = True
|
||||
kiln_must_catch_up_max_error = 5 #degrees
|
||||
|
||||
# This setting is required.
|
||||
# This setting defines the window within which PID control occurs.
|
||||
# Outside this window (N degrees below or above the current target)
|
||||
# the elements are either 100% on because the kiln is too cold
|
||||
# or 100% off because the kiln is too hot. No integral builds up
|
||||
# outside the window. The bigger you make the window, the more
|
||||
# integral you will accumulate.
|
||||
pid_control_window = 10 #degrees
|
||||
|
||||
# thermocouple offset
|
||||
# If you put your thermocouple in ice water and it reads 36F, you can
|
||||
|
||||
48
lib/oven.py
48
lib/oven.py
@ -197,12 +197,13 @@ class Oven(threading.Thread):
|
||||
log.info("Refusing to start profile - thermocouple unknown error")
|
||||
return
|
||||
|
||||
log.info("Running schedule %s" % profile.name)
|
||||
self.startat = startat * 60
|
||||
self.runtime = self.startat
|
||||
self.start_time = datetime.datetime.now() - datetime.timedelta(seconds=self.startat)
|
||||
self.profile = profile
|
||||
self.totaltime = profile.get_duration()
|
||||
self.state = "RUNNING"
|
||||
self.start_time = datetime.datetime.now()
|
||||
self.startat = startat * 60
|
||||
log.info("Running schedule %s starting at %d minutes" % (profile.name,startat))
|
||||
log.info("Starting")
|
||||
|
||||
def abort_run(self):
|
||||
@ -215,25 +216,23 @@ class Oven(threading.Thread):
|
||||
temp = self.board.temp_sensor.temperature + \
|
||||
config.thermocouple_offset
|
||||
# kiln too cold, wait for it to heat up
|
||||
if self.target - temp > config.kiln_must_catch_up_max_error:
|
||||
if self.target - temp > config.pid_control_window:
|
||||
log.info("kiln must catch up, too cold, shifting schedule")
|
||||
self.start_time = datetime.datetime.now() - datetime.timedelta(milliseconds = self.runtime * 1000)
|
||||
self.pid.iterm = 0
|
||||
# kiln too hot, wait for it to cool down
|
||||
if temp - self.target > config.kiln_must_catch_up_max_error:
|
||||
if temp - self.target > config.pid_control_window:
|
||||
log.info("kiln must catch up, too hot, shifting schedule")
|
||||
self.start_time = datetime.datetime.now() - datetime.timedelta(milliseconds = self.runtime * 1000)
|
||||
self.pid.iterm = 0
|
||||
|
||||
def update_runtime(self):
|
||||
|
||||
runtime_delta = datetime.datetime.now() - self.start_time
|
||||
if runtime_delta.total_seconds() < 0:
|
||||
runtime_delta = datetime.timedelta(0)
|
||||
|
||||
if self.startat > 0:
|
||||
self.runtime = self.startat + runtime_delta.total_seconds()
|
||||
else:
|
||||
self.runtime = runtime_delta.total_seconds()
|
||||
self.runtime = runtime_delta.total_seconds()
|
||||
|
||||
def update_target_temp(self):
|
||||
self.target = self.profile.get_target_temperature(self.runtime)
|
||||
@ -481,13 +480,24 @@ class PID():
|
||||
window_size = 100
|
||||
|
||||
error = float(setpoint - ispoint)
|
||||
|
||||
if self.ki > 0:
|
||||
if config.stop_integral_windup == True:
|
||||
if abs(self.kp * error) < window_size:
|
||||
self.iterm += (error * timeDelta * (1/self.ki))
|
||||
else:
|
||||
self.iterm += (error * timeDelta * (1/self.ki))
|
||||
|
||||
# this removes the need for config.stop_integral_windup
|
||||
# it turns the controller into a binary on/off switch
|
||||
# any time it's outside the window defined by
|
||||
# config.pid_control_window
|
||||
if error < (-1 * config.pid_control_window):
|
||||
log.info("kiln outside pid control window, max cooling")
|
||||
self.lastErr = error
|
||||
self.lastNow = now
|
||||
return 0
|
||||
if error > (1 * config.pid_control_window):
|
||||
log.info("kiln outside pid control window, max heating")
|
||||
self.lastErr = error
|
||||
self.lastNow = now
|
||||
return 1
|
||||
|
||||
icomp = (error * timeDelta * (1/self.ki))
|
||||
self.iterm += (error * timeDelta * (1/self.ki))
|
||||
|
||||
dErr = (error - self.lastErr) / timeDelta
|
||||
output = self.kp * error + self.iterm + self.kd * dErr
|
||||
@ -524,9 +534,11 @@ class PID():
|
||||
# ((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,
|
||||
log.info("pid actuals pid=%0.2f p=%0.2f i=%0.2f d=%0.2f icomp=%0.2f error=%0.2f" % (out4logs,
|
||||
self.kp * error,
|
||||
self.iterm,
|
||||
self.kd * dErr))
|
||||
self.kd * dErr,
|
||||
icomp,
|
||||
error))
|
||||
|
||||
return output
|
||||
|
||||
Loading…
Reference in New Issue
Block a user