2014-10-16 06:31:49 +00:00
|
|
|
import re
|
2014-10-16 07:46:04 +00:00
|
|
|
import time
|
2014-10-23 04:46:35 +00:00
|
|
|
import random
|
2014-10-16 06:18:47 +00:00
|
|
|
import datetime
|
2014-10-16 07:46:04 +00:00
|
|
|
import logging
|
|
|
|
import threading
|
2014-10-21 21:21:43 +00:00
|
|
|
from collections import deque, namedtuple
|
2014-11-30 04:51:32 +00:00
|
|
|
from math import isnan
|
2014-10-16 06:18:47 +00:00
|
|
|
|
2014-10-16 07:46:04 +00:00
|
|
|
logger = logging.getLogger("thermo")
|
|
|
|
|
2014-10-16 06:18:47 +00:00
|
|
|
def temp_to_cone(temp):
|
|
|
|
"""Convert the current temperature to cone value using linear interpolation"""
|
|
|
|
cones = [600,614,635,683,717,747,792,804,838,852,884,894,900,923,955,984,999,1046,1060,1101,1120,1137,1154,1162,1168,1186,1196,1222,1240,1263,1280,1305,1315,1326,1346]
|
|
|
|
names = [str(i).replace('-', '0') for i in range(-22,0)] + [str(i) for i in range(1, 14)]
|
|
|
|
for i in range(len(cones)-1):
|
|
|
|
low, high = cones[i], cones[i+1]
|
|
|
|
if low <= temp < high:
|
|
|
|
frac = (temp - low) / float(high - low)
|
|
|
|
return names[i]+'.%d'%int(frac*10)
|
|
|
|
return "13+"
|
|
|
|
|
2014-10-21 21:21:43 +00:00
|
|
|
tempsample = namedtuple("tempsample", ['time', 'temp'])
|
|
|
|
|
2014-10-22 19:11:46 +00:00
|
|
|
class MAX31850(object):
|
|
|
|
def __init__(self, name="3b-000000182b57", smooth_window=4):
|
2014-10-16 06:18:47 +00:00
|
|
|
self.device = "/sys/bus/w1/devices/%s/w1_slave"%name
|
2014-10-23 04:46:35 +00:00
|
|
|
self.history = deque(maxlen=smooth_window)
|
2014-10-22 19:11:46 +00:00
|
|
|
self.last = None
|
2014-10-16 06:18:47 +00:00
|
|
|
|
|
|
|
def _read_temp(self):
|
|
|
|
with open(self.device, 'r') as f:
|
|
|
|
lines = f.readlines()
|
|
|
|
|
|
|
|
while lines[0].strip()[-3:] != 'YES':
|
|
|
|
time.sleep(0.2)
|
|
|
|
with open(self.device, 'r') as f:
|
|
|
|
lines = f.readlines()
|
|
|
|
|
|
|
|
match = re.match(r'^[0-9a-f\s]{27}t=(\d+)$', lines[1])
|
|
|
|
if match is not None:
|
|
|
|
return float(match.group(1)) / 1000.0
|
|
|
|
|
2014-10-22 19:11:46 +00:00
|
|
|
def get(self):
|
|
|
|
"""Blocking call to retrieve latest temperature sample"""
|
2014-10-23 04:46:35 +00:00
|
|
|
self.history.append(self._read_temp())
|
2014-10-22 19:11:46 +00:00
|
|
|
self.last = time.time()
|
|
|
|
return self.temperature
|
|
|
|
|
|
|
|
@property
|
|
|
|
def temperature(self):
|
|
|
|
if self.last is None or time.time() - self.last > 5:
|
|
|
|
return self.get()
|
|
|
|
|
|
|
|
return tempsample(self.last, sum(self.history) / float(len(self.history)))
|
|
|
|
|
|
|
|
class Simulate(object):
|
2014-11-30 04:27:48 +00:00
|
|
|
def __init__(self, regulator, smooth_window=120):
|
2014-10-22 19:11:46 +00:00
|
|
|
self.regulator = regulator
|
2014-10-23 04:46:35 +00:00
|
|
|
self.history = deque(maxlen=smooth_window)
|
|
|
|
self.last = None
|
2014-10-22 19:11:46 +00:00
|
|
|
|
2014-10-23 04:46:35 +00:00
|
|
|
def _read_temp(self):
|
2014-11-29 17:04:33 +00:00
|
|
|
time.sleep(.25)
|
2014-10-23 04:46:35 +00:00
|
|
|
return max([self.regulator.output, 0]) * 1000. + 15+random.gauss(0,.2)
|
|
|
|
|
|
|
|
def get(self):
|
|
|
|
self.history.append(self._read_temp())
|
|
|
|
self.last = time.time()
|
2014-10-22 19:11:46 +00:00
|
|
|
return self.temperature
|
2014-10-16 06:44:12 +00:00
|
|
|
|
2014-10-16 06:18:47 +00:00
|
|
|
@property
|
|
|
|
def temperature(self):
|
2014-10-23 04:46:35 +00:00
|
|
|
if self.last is None or time.time() - self.last > 5:
|
|
|
|
return self.get()
|
|
|
|
|
|
|
|
return tempsample(self.last, sum(self.history) / float(len(self.history)))
|
2014-10-22 19:11:46 +00:00
|
|
|
|
2014-11-29 17:04:33 +00:00
|
|
|
class Breakout(object):
|
2014-11-30 04:58:58 +00:00
|
|
|
def __init__(self, addr, smooth_window=16):
|
2014-11-29 17:04:33 +00:00
|
|
|
import breakout
|
|
|
|
self.device = breakout.Breakout(addr)
|
2014-11-30 04:59:43 +00:00
|
|
|
self.history = deque(maxlen=smooth_window)
|
2014-11-30 04:58:58 +00:00
|
|
|
self.last = None
|
2014-11-29 17:04:33 +00:00
|
|
|
|
|
|
|
def get(self):
|
|
|
|
time.sleep(.25)
|
2014-11-30 04:58:58 +00:00
|
|
|
temp = self.device.temperature
|
2014-12-17 06:34:47 +00:00
|
|
|
if not isnan(temp) and len(self.history) < 1 or abs(temp - self.history[-1]) < 15 or (time.time() - self.last) > 5:
|
|
|
|
self.last = time.time()
|
2014-11-30 04:58:58 +00:00
|
|
|
self.history.append(temp)
|
|
|
|
return self.temperature
|
2014-11-29 17:04:33 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def temperature(self):
|
2014-11-30 04:58:58 +00:00
|
|
|
if self.last is None or time.time() - self.last > 5:
|
|
|
|
return self.get()
|
|
|
|
|
|
|
|
return tempsample(self.last, sum(self.history) / float(len(self.history)))
|
2014-11-29 17:04:33 +00:00
|
|
|
|
2014-10-22 19:11:46 +00:00
|
|
|
class Monitor(threading.Thread):
|
|
|
|
def __init__(self, cls=MAX31850, **kwargs):
|
|
|
|
self.therm = cls(**kwargs)
|
|
|
|
self.running = True
|
|
|
|
|
|
|
|
from Adafruit_alphanumeric import AlphaScroller
|
|
|
|
self.display = AlphaScroller(interval=.4)
|
|
|
|
self.display.start()
|
|
|
|
self.display.hide()
|
2014-10-16 06:18:47 +00:00
|
|
|
|
|
|
|
def run(self):
|
2014-10-16 07:08:05 +00:00
|
|
|
while self.running:
|
2014-10-22 19:11:46 +00:00
|
|
|
_, temp = self.therm.get()
|
|
|
|
|
|
|
|
if temp > 50:
|
|
|
|
if not self.display.shown:
|
|
|
|
self.display.show()
|
|
|
|
fahr = temp * 9. / 5. + 32.
|
|
|
|
text = list('%0.0f'%temp) + ['degree'] + list('C %0.0f'%fahr)+['degree'] + list("F")
|
|
|
|
if 600 <= temp:
|
|
|
|
text += [' ', ' ', 'cone']+list(temp_to_cone(temp))
|
|
|
|
self.display.set_text(text, reset=False)
|
|
|
|
elif self.display.shown:
|
|
|
|
self.display.hide()
|
|
|
|
|
|
|
|
def stop(self):
|
|
|
|
self.running = False
|
|
|
|
self.display.stop()
|
|
|
|
|
2014-10-16 06:31:49 +00:00
|
|
|
|
|
|
|
if __name__ == "__main__":
|
2014-10-22 19:11:46 +00:00
|
|
|
monitor = Monitor()
|
2014-11-29 18:59:24 +00:00
|
|
|
monitor.start()
|