kilnController/oven.py

137 wiersze
4.1 KiB
Python
Czysty Zwykły widok Historia

2013-11-24 16:57:12 +00:00
import threading,time,random,datetime,logging,json
2013-11-23 22:50:59 +00:00
2013-11-23 21:25:20 +00:00
log = logging.getLogger(__name__)
2013-11-23 23:36:10 +00:00
try:
from max31855 import MAX31855, MAX31855Error
sensor_dummy = False
except ImportError:
log.warning("Could not initialize temperature sensor, using dummy values!")
sensor_dummy = True
2013-11-23 21:25:20 +00:00
class Oven (threading.Thread):
STATE_IDLE = "IDLE"
2013-11-23 21:25:20 +00:00
STATE_RUNNING = "RUNNING"
STATE_ABORT = "ABORT"
STATE_ERROR = "ERROR"
2013-11-23 22:40:46 +00:00
2013-11-23 21:25:20 +00:00
def __init__(self):
threading.Thread.__init__(self)
self.daemon = True
2013-11-23 21:25:20 +00:00
self.profile = None
self.start_time = 0
2013-11-23 23:30:06 +00:00
self.runtime = 0
self.totaltime = 0
2013-11-24 17:35:08 +00:00
self.target = 0
2013-11-23 21:25:20 +00:00
self.power = 0.0
self.state = Oven.STATE_IDLE
self.temp_sensor = TempSensor(self)
self.temp_sensor.start()
2013-11-24 14:20:38 +00:00
self.start()
2013-11-23 22:40:46 +00:00
2013-11-23 21:25:20 +00:00
def run_profile(self, profile):
2013-11-24 17:35:08 +00:00
log.info("Running profile %s"%profile.name)
2013-11-23 21:25:20 +00:00
self.profile = profile
2013-11-24 19:40:09 +00:00
self.totaltime = profile.get_duration()
2013-11-23 21:25:20 +00:00
self.state = Oven.STATE_RUNNING
self.start_time = datetime.datetime.now()
log.info("Starting")
2013-11-23 22:40:46 +00:00
2013-11-23 21:25:20 +00:00
def abort_run(self):
self.state = Oven.STATE_ABORT
2013-11-23 22:40:46 +00:00
2013-11-23 21:25:20 +00:00
def run(self):
while True:
if self.state == Oven.STATE_RUNNING:
2013-11-23 23:30:06 +00:00
self.runtime = (datetime.datetime.now() - self.start_time).total_seconds()
2013-11-24 17:54:29 +00:00
log.info("running at %.1f deg C (Target: %.1f) , power %.2f (%.1fs/%.0f)"%(self.temp_sensor.temperature,self.target,self.power,self.runtime,self.totaltime))
2013-11-24 17:35:08 +00:00
self.target = self.profile.get_target_temperature(self.runtime)
if self.temp_sensor.temperature < self.target:
2013-11-23 21:25:20 +00:00
self.power = 1.0
else:
self.power = 0.0
if self.runtime >= self.totaltime:
2013-11-23 23:30:06 +00:00
self.power = 0.0
2013-11-24 19:40:09 +00:00
self.runtime = 0
2013-11-23 23:30:06 +00:00
self.state = Oven.STATE_IDLE
2013-11-23 21:25:20 +00:00
elif self.state == Oven.STATE_ABORT:
self.power = 0.0
2013-11-24 19:40:09 +00:00
self.runtime = 0
2013-11-23 21:25:20 +00:00
self.state = Oven.STATE_IDLE
time.sleep(1)
2013-11-23 22:40:46 +00:00
2013-11-23 21:25:20 +00:00
def get_state(self):
2013-11-23 23:30:06 +00:00
2013-11-23 21:25:20 +00:00
state = {
2013-11-23 23:30:06 +00:00
'runtime': self.runtime,
2013-11-23 21:25:20 +00:00
'temperature': self.temp_sensor.temperature,
2013-11-24 17:35:08 +00:00
'target': self.target,
2013-11-23 21:25:20 +00:00
'state': self.state,
'power': self.power,
'totaltime': self.totaltime
2013-11-23 21:25:20 +00:00
}
return state
2013-11-23 22:40:46 +00:00
2013-11-23 21:25:20 +00:00
class TempSensor(threading.Thread):
def __init__(self,oven):
threading.Thread.__init__(self)
self.daemon = True
2013-11-23 21:25:20 +00:00
self.temperature = 0
self.oven = oven
2013-11-23 22:50:59 +00:00
2013-11-23 23:36:10 +00:00
if not sensor_dummy:
2013-11-23 22:50:59 +00:00
cs_pin = 27
clock_pin = 22
data_pin = 17
units = "c"
self.thermocouple = MAX31855(cs_pin, clock_pin, data_pin, units)
2013-11-23 22:40:46 +00:00
2013-11-23 21:25:20 +00:00
def run(self):
while True:
2013-11-23 23:36:10 +00:00
if not sensor_dummy:
2013-11-23 22:50:59 +00:00
self.temperature = self.thermocouple.get()
else:
time_delta = (20.0 - self.temperature)/40
power_delta = 8.0*self.oven.power
self.temperature += (time_delta+power_delta)
2013-11-23 21:25:20 +00:00
time.sleep(1)
2013-11-23 22:40:46 +00:00
2013-11-24 16:57:12 +00:00
class Profile():
def __init__(self,json_data):
obj = json.loads(json_data)
self.name = obj["name"]
2013-11-24 17:35:08 +00:00
self.data = sorted(obj["data"])
2013-11-24 16:57:12 +00:00
def get_duration(self):
return max([t for (t,x) in self.data])
2013-11-24 17:35:08 +00:00
def get_target_temperature(self,time):
if time > self.get_duration():
return 0
prev_point = None
next_point = None
for i in range(len(self.data)):
2013-11-24 17:54:29 +00:00
if time < self.data[i][0]:
prev_point = self.data[i-1]
next_point = self.data[i]
2013-11-24 17:35:08 +00:00
break
2013-11-24 17:54:29 +00:00
incl = float(next_point[1] - prev_point[1]) / float(next_point[0] - prev_point[0])
2013-11-24 17:35:08 +00:00
temp = prev_point[1] + (time - prev_point[0]) * incl
return temp
2013-11-23 21:25:20 +00:00
if __name__ == "__main__":
2013-11-24 16:57:12 +00:00
#my_oven = Oven()
#my_oven.run_profile("abc")
with open("storage/profiles/lead.json",'r') as f:
p = Profile(f.read())
print p.get_duration()
2013-11-23 22:40:46 +00:00