oven controls heat/cool/air
This commit is contained in:
parent
1975664b0d
commit
7356fa3b36
96
oven.py
96
oven.py
@ -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
|
||||||
|
|||||||
@ -1 +0,0 @@
|
|||||||
{"type": "profile", "data": [[0, 20], [88.73784772617847, 221.87500000000003], [217.18696241866536, 69.06250000000001], [300, 0]], "name": "leadfree"}
|
|
||||||
Loading…
Reference in New Issue
Block a user