From 7356fa3b36c99a49855cdd9cb8bb6c20d824ca6b Mon Sep 17 00:00:00 2001 From: Sebastian Steuer Date: Fri, 29 Nov 2013 23:27:30 +0100 Subject: [PATCH] oven controls heat/cool/air --- oven.py | 96 +++++++++++++++++++++++++--------- storage/profiles/leadfree.json | 1 - 2 files changed, 72 insertions(+), 25 deletions(-) delete mode 100644 storage/profiles/leadfree.json diff --git a/oven.py b/oven.py index 4fed503..2124d32 100644 --- a/oven.py +++ b/oven.py @@ -4,21 +4,24 @@ log = logging.getLogger(__name__) try: from max31855 import MAX31855, MAX31855Error - sensor_dummy = False + sensor_available = True except ImportError: log.warning("Could not initialize temperature sensor, using dummy values!") - sensor_dummy = True + sensor_available = False GPIO_HEAT = 11 +GPIO_COOL = 10 +GPIO_AIR = 9 try: import RPi.GPIO as GPIO GPIO.setmode(GPIO.BCM) GPIO.setup(GPIO_HEAT, GPIO.OUT) - no_gpio = False + GPIO.setup(GPIO_HEAT, GPIO.OUT) + gpio_available = True except ImportError: log.warning("Could not initialize GPIOs, oven operation will only be simulated!") - no_gpio = True + gpio_available = False class Oven (threading.Thread): STATE_IDLE = "IDLE" @@ -38,10 +41,10 @@ class Oven (threading.Thread): self.runtime = 0 self.totaltime = 0 self.target = 0 - self.power = 0.0 self.state = Oven.STATE_IDLE - if not no_gpio: - GPIO.output(GPIO_HEAT, GPIO.HIGH) + self.set_heat(False) + self.set_cool(False) + self.set_air(False) def run_profile(self, profile): log.info("Running profile %s"%profile.name) @@ -58,28 +61,61 @@ class Oven (threading.Thread): while True: if self.state == Oven.STATE_RUNNING: 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) - if self.temp_sensor.temperature < self.target: - self.power = 1.0 - if not no_gpio: - GPIO.output(GPIO_HEAT, GPIO.LOW) + if self.profile.is_rising(self.runtime): + self.set_cool(False) + self.set_heat(self.temp_sensor.temperature < self.target) else: - self.power = 0.0 - if not no_gpio: - GPIO.output(GPIO_HEAT, GPIO.HIGH) + self.set_heat(False) + self.set_cool(self.temp_sensor.temperature > self.target) + + self.set_air(self.temp_sensor.temperature<180) + if self.runtime >= self.totaltime: self.reset() 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): state = { 'runtime': self.runtime, 'temperature': self.temp_sensor.temperature, 'target': self.target, 'state': self.state, - 'power': self.power, + 'heat': self.heat, + 'cool': self.cool, + 'air' : self.air, 'totaltime': self.totaltime } return state @@ -92,7 +128,7 @@ class TempSensor(threading.Thread): self.temperature = 0 self.oven = oven - if not sensor_dummy: + if sensor_available: cs_pin = 27 clock_pin = 22 data_pin = 17 @@ -101,11 +137,11 @@ class TempSensor(threading.Thread): def run(self): while True: - if not sensor_dummy: + if sensor_available: self.temperature = self.thermocouple.get() else: 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) time.sleep(0.5) @@ -118,11 +154,11 @@ class Profile(): def get_duration(self): 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(): - return 0 - + return (None,None) + prev_point = None next_point = None @@ -131,7 +167,19 @@ class Profile(): prev_point = self.data[i-1] next_point = self.data[i] 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]) temp = prev_point[1] + (time - prev_point[0]) * incl return temp diff --git a/storage/profiles/leadfree.json b/storage/profiles/leadfree.json deleted file mode 100644 index befec85..0000000 --- a/storage/profiles/leadfree.json +++ /dev/null @@ -1 +0,0 @@ -{"type": "profile", "data": [[0, 20], [88.73784772617847, 221.87500000000003], [217.18696241866536, 69.06250000000001], [300, 0]], "name": "leadfree"} \ No newline at end of file