oven controls heat/cool/air

This commit is contained in:
Sebastian Steuer 2013-11-29 23:27:30 +01:00
parent 1975664b0d
commit 7356fa3b36
2 changed files with 72 additions and 25 deletions

96
oven.py
View File

@ -4,21 +4,24 @@ log = logging.getLogger(__name__)
try: try:
from max31855 import MAX31855, MAX31855Error from max31855 import MAX31855, MAX31855Error
sensor_dummy = False sensor_available = True
except ImportError: except ImportError:
log.warning("Could not initialize temperature sensor, using dummy values!") log.warning("Could not initialize temperature sensor, using dummy values!")
sensor_dummy = True sensor_available = False
GPIO_HEAT = 11 GPIO_HEAT = 11
GPIO_COOL = 10
GPIO_AIR = 9
try: try:
import RPi.GPIO as GPIO import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM) GPIO.setmode(GPIO.BCM)
GPIO.setup(GPIO_HEAT, GPIO.OUT) GPIO.setup(GPIO_HEAT, GPIO.OUT)
no_gpio = False GPIO.setup(GPIO_HEAT, GPIO.OUT)
gpio_available = True
except ImportError: except ImportError:
log.warning("Could not initialize GPIOs, oven operation will only be simulated!") log.warning("Could not initialize GPIOs, oven operation will only be simulated!")
no_gpio = True gpio_available = False
class Oven (threading.Thread): class Oven (threading.Thread):
STATE_IDLE = "IDLE" STATE_IDLE = "IDLE"
@ -38,10 +41,10 @@ class Oven (threading.Thread):
self.runtime = 0 self.runtime = 0
self.totaltime = 0 self.totaltime = 0
self.target = 0 self.target = 0
self.power = 0.0
self.state = Oven.STATE_IDLE self.state = Oven.STATE_IDLE
if not no_gpio: self.set_heat(False)
GPIO.output(GPIO_HEAT, GPIO.HIGH) self.set_cool(False)
self.set_air(False)
def run_profile(self, profile): def run_profile(self, profile):
log.info("Running profile %s"%profile.name) log.info("Running profile %s"%profile.name)
@ -58,28 +61,61 @@ class Oven (threading.Thread):
while True: while True:
if self.state == Oven.STATE_RUNNING: if self.state == Oven.STATE_RUNNING:
self.runtime = (datetime.datetime.now() - self.start_time).total_seconds() self.runtime = (datetime.datetime.now() - self.start_time).total_seconds()
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)) log.info("running at %.1f deg C (Target: %.1f) , heat %.2f, cool %.2f, air %.2f (%.1fs/%.0f)"%(self.temp_sensor.temperature,self.target,self.heat,self.cool,self.air,self.runtime,self.totaltime))
self.target = self.profile.get_target_temperature(self.runtime) self.target = self.profile.get_target_temperature(self.runtime)
if self.temp_sensor.temperature < self.target: if self.profile.is_rising(self.runtime):
self.power = 1.0 self.set_cool(False)
if not no_gpio: self.set_heat(self.temp_sensor.temperature < self.target)
GPIO.output(GPIO_HEAT, GPIO.LOW)
else: else:
self.power = 0.0 self.set_heat(False)
if not no_gpio: self.set_cool(self.temp_sensor.temperature > self.target)
GPIO.output(GPIO_HEAT, GPIO.HIGH)
self.set_air(self.temp_sensor.temperature<180)
if self.runtime >= self.totaltime: if self.runtime >= self.totaltime:
self.reset() self.reset()
time.sleep(0.5) time.sleep(0.5)
def set_heat(self,value):
if value:
self.heat = 1.0
if gpio_available:
GPIO.output(GPIO_HEAT, GPIO.LOW)
else:
self.heat = 0.0
if gpio_available:
GPIO.output(GPIO_HEAT, GPIO.HIGH)
def set_cool(self,value):
if value:
self.cool = 1.0
if gpio_available:
GPIO.output(GPIO_COOL, GPIO.LOW)
else:
self.cool = 0.0
if gpio_available:
GPIO.output(GPIO_COOL, GPIO.HIGH)
def set_air(self,value):
if value:
self.air = 1.0
if gpio_available:
GPIO.output(GPIO_COOL, GPIO.LOW)
else:
self.air = 0.0
if gpio_available:
GPIO.output(GPIO_COOL, GPIO.HIGH)
def get_state(self): def get_state(self):
state = { state = {
'runtime': self.runtime, 'runtime': self.runtime,
'temperature': self.temp_sensor.temperature, 'temperature': self.temp_sensor.temperature,
'target': self.target, 'target': self.target,
'state': self.state, 'state': self.state,
'power': self.power, 'heat': self.heat,
'cool': self.cool,
'air' : self.air,
'totaltime': self.totaltime 'totaltime': self.totaltime
} }
return state return state
@ -92,7 +128,7 @@ class TempSensor(threading.Thread):
self.temperature = 0 self.temperature = 0
self.oven = oven self.oven = oven
if not sensor_dummy: if sensor_available:
cs_pin = 27 cs_pin = 27
clock_pin = 22 clock_pin = 22
data_pin = 17 data_pin = 17
@ -101,11 +137,11 @@ class TempSensor(threading.Thread):
def run(self): def run(self):
while True: while True:
if not sensor_dummy: if sensor_available:
self.temperature = self.thermocouple.get() self.temperature = self.thermocouple.get()
else: else:
time_delta = (20.0 - self.temperature)/40 time_delta = (20.0 - self.temperature)/40
power_delta = 8.0*self.oven.power power_delta = 8.0*self.oven.heat
self.temperature += (time_delta+power_delta) self.temperature += (time_delta+power_delta)
time.sleep(0.5) time.sleep(0.5)
@ -118,11 +154,11 @@ class Profile():
def get_duration(self): def get_duration(self):
return max([t for (t,x) in self.data]) return max([t for (t,x) in self.data])
def get_target_temperature(self,time): def get_surrounding_points(self,time):
if time > self.get_duration(): if time > self.get_duration():
return 0 return (None,None)
prev_point = None prev_point = None
next_point = None next_point = None
@ -131,7 +167,19 @@ class Profile():
prev_point = self.data[i-1] prev_point = self.data[i-1]
next_point = self.data[i] next_point = self.data[i]
break break
return (prev_point,next_point)
def is_rising(self,time):
(prev_point,next_point) = self.get_surrounding_points(time)
return prev_point[1] < next_point[1]
def get_target_temperature(self,time):
if time > self.get_duration():
return 0
(prev_point,next_point) = self.get_surrounding_points(time)
incl = float(next_point[1] - prev_point[1]) / float(next_point[0] - prev_point[0]) incl = float(next_point[1] - prev_point[1]) / float(next_point[0] - prev_point[0])
temp = prev_point[1] + (time - prev_point[0]) * incl temp = prev_point[1] + (time - prev_point[0]) * incl
return temp return temp

View File

@ -1 +0,0 @@
{"type": "profile", "data": [[0, 20], [88.73784772617847, 221.87500000000003], [217.18696241866536, 69.06250000000001], [300, 0]], "name": "leadfree"}