kopia lustrzana https://github.com/jbruce12000/kiln-controller
adding restart profile functionality
rodzic
0e53f23083
commit
4db8e30515
22
config.py
22
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
|
||||
|
@ -65,7 +65,7 @@ sensor_time_wait = 2
|
|||
# your specific kiln. Note that the integral pid_ki is
|
||||
# inverted so that a smaller number means more integral action.
|
||||
pid_kp = 25 # Proportional 25,200,200
|
||||
pid_ki = 20 # Integral
|
||||
pid_ki = 10 # Integral
|
||||
pid_kd = 200 # Derivative
|
||||
|
||||
|
||||
|
@ -82,10 +82,10 @@ stop_integral_windup = True
|
|||
# Simulation parameters
|
||||
simulate = True
|
||||
sim_t_env = 60.0 # deg C
|
||||
sim_c_heat = 100.0 # J/K heat capacity of heat element
|
||||
sim_c_heat = 500.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.5 # 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
|
||||
|
@ -121,7 +121,7 @@ kiln_must_catch_up = True
|
|||
# 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
|
||||
pid_control_window = 5 #degrees
|
||||
|
||||
# thermocouple offset
|
||||
# If you put your thermocouple in ice water and it reads 36F, you can
|
||||
|
@ -151,3 +151,15 @@ ac_freq_50hz = False
|
|||
# - too many errors in a short period from thermocouple
|
||||
# and some people just want to ignore all of that and just log the emergencies but do not quit
|
||||
ignore_emergencies = False
|
||||
|
||||
########################################################################
|
||||
# automatic restarts - if you have a power brown-out and the raspberry pi
|
||||
# reboots, this restarts your kiln where it left off in the firing profile.
|
||||
# This only happens if power comes back before automatic_restart_window
|
||||
# is exceeded (in minutes). The kiln-controller.py process must start
|
||||
# automatically on boot-up for this to work.
|
||||
automatic_restarts = True
|
||||
automatic_restart_window = 15 # max minutes since power outage
|
||||
automatic_restart_state_file = "/tmp/kiln_controller_state.json"
|
||||
|
||||
|
||||
|
|
|
@ -42,6 +42,8 @@ else:
|
|||
log.info("this is a real kiln")
|
||||
oven = RealOven()
|
||||
ovenWatcher = OvenWatcher(oven)
|
||||
# this ovenwatcher is used in the oven class for restarts
|
||||
oven.set_ovenwatcher(ovenWatcher)
|
||||
|
||||
@app.route('/')
|
||||
def index():
|
||||
|
|
66
lib/oven.py
66
lib/oven.py
|
@ -5,6 +5,7 @@ import datetime
|
|||
import logging
|
||||
import json
|
||||
import config
|
||||
import os
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
@ -290,9 +291,72 @@ class Oven(threading.Thread):
|
|||
}
|
||||
return state
|
||||
|
||||
def save_state(self):
|
||||
with open(config.automatic_restart_state_file, 'w', encoding='utf-8') as f:
|
||||
json.dump(self.get_state(), f, ensure_ascii=False, indent=4)
|
||||
|
||||
def state_file_is_old(self):
|
||||
'''returns True is state files is older than 15 mins default
|
||||
False if younger
|
||||
True if state file cannot be opened or does not exist
|
||||
'''
|
||||
if os.path.isfile(config.automatic_restart_state_file):
|
||||
state_age = os.path.getmtime(config.automatic_restart_state_file)
|
||||
now = time.time()
|
||||
if((now - state_age)/60 <= config.automatic_restart_window):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def automatic_restart(self):
|
||||
'''takes one of two actions
|
||||
if RUNNING, saves state every duty cycle
|
||||
if IDLE, checks and then starts last known good profile where it died
|
||||
'''
|
||||
# check if automatic_restart setting is True
|
||||
if not config.automatic_restarts == True:
|
||||
return
|
||||
|
||||
if self.state == "RUNNING":
|
||||
# save state every duty cycle (2s by default)
|
||||
self.save_state()
|
||||
return
|
||||
|
||||
# check if within window (use file timestamp and setting)
|
||||
if self.state_file_is_old():
|
||||
log.info("restart not possible. outside restart window")
|
||||
return
|
||||
|
||||
# restart the last known profile where it died
|
||||
self.restart()
|
||||
|
||||
def restart(self):
|
||||
if os.path.isfile(config.automatic_restart_state_file):
|
||||
with open(config.automatic_restart_state_file) as infile: d = json.load(infile)
|
||||
else:
|
||||
log.info("restart not possible. no state file found.")
|
||||
return
|
||||
# check if last profile finished
|
||||
if d["totaltime"] - d["runtime"] > 60:
|
||||
startat = d["runtime"]/60
|
||||
filename = "%s.json" % (d["profile"])
|
||||
profile_path = os.path.abspath(os.path.join(os.path.dirname( __file__ ), '..', 'storage','profiles',filename))
|
||||
|
||||
log.info("restarting profile = %s at minute = %d" % (profile_path,startat))
|
||||
with open(profile_path) as infile:
|
||||
profile_json = json.dumps(json.load(infile))
|
||||
profile = Profile(profile_json)
|
||||
self.run_profile(profile,startat=startat)
|
||||
self.ovenwatcher.record(profile)
|
||||
|
||||
|
||||
def set_ovenwatcher(self,watcher):
|
||||
self.ovenwatcher = watcher
|
||||
|
||||
def run(self):
|
||||
while True:
|
||||
if self.state == "IDLE":
|
||||
self.automatic_restart()
|
||||
time.sleep(1)
|
||||
continue
|
||||
if self.state == "RUNNING":
|
||||
|
@ -302,7 +366,7 @@ class Oven(threading.Thread):
|
|||
self.heat_then_cool()
|
||||
self.reset_if_emergency()
|
||||
self.reset_if_schedule_ended()
|
||||
|
||||
self.automatic_restart()
|
||||
|
||||
class SimulatedOven(Oven):
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue