Mercurial > templog
comparison py/fridge.py @ 442:02318c9660cd
copied fridge logic from main.c
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Tue, 20 Nov 2012 22:03:10 +0800 |
parents | 31ac84425a2d |
children | 482d7852b511 |
comparison
equal
deleted
inserted
replaced
441:9fbeafc09845 | 442:02318c9660cd |
---|---|
1 # -*- coding: utf-8 -*- | |
1 from utils import L,W,E | 2 from utils import L,W,E |
2 import config | 3 import config |
3 | 4 |
4 class Fridge(object): | 5 class Fridge(object): |
6 | |
7 OVERSHOOT_MAX_DIV = 1800.0 # 30 mins | |
8 FRIDGE_AIR_MIN_RANGE = 4 # ÂșC | |
9 FRIDGE_AIR_MAX_RANGE = 4 | |
10 | |
5 def __init__(self): | 11 def __init__(self): |
6 self.setup_gpio() | 12 self.setup_gpio() |
7 self.wort_valid_clock = 0 | 13 self.wort_valid_clock = 0 |
14 self.fridge_on_clock = 0 | |
15 self.fridge_off_clock = 0 | |
8 | 16 |
9 def setup_gpio(self): | 17 def setup_gpio(self): |
10 fn = '%s/direction' % config.FRIDGE_GPIO | 18 dir_fn = '%s/direction' % config.FRIDGE_GPIO |
11 f = open(fn, 'w') | 19 with f = open(dir_fn, 'w'): |
12 f.write('low') | 20 f.write('low') |
13 f.close() | 21 val_fn = '%s/value' % config.FRIDGE_GPIO |
14 # .off() shouldn't do anything, but tests that "value" is writable | 22 self.value_file = f.open(val_fn, 'r+') |
15 self.off() | |
16 | 23 |
17 def turn(self, value): | 24 def turn(self, value): |
18 fn = '%s/value' % config.FRIDGE_GPIO | 25 self.value_file.seek(0) |
19 f = open(fn, 'w') | |
20 if value: | 26 if value: |
21 f.write('1') | 27 self.value_file.write('1') |
22 else: | 28 else: |
23 f.write('0') | 29 self.value_file.write('0') |
24 f.close() | 30 self.value_file.flush() |
25 | 31 |
26 def on(self): | 32 def on(self): |
27 self.turn(1) | 33 self.turn(True) |
28 | 34 |
29 def off(self): | 35 def off(self): |
30 self.turn(0) | 36 self.turn(False) |
31 | 37 |
32 def do(self): | 38 def is_on(self): |
39 self.value_file.seek(0) | |
40 buf = self.value_file.read().strip() | |
41 if buf == '0': | |
42 return False | |
43 if buf != '1': | |
44 E("Bad value read from gpio '%s': '%s'" | |
45 % (self.value_file.name, buf)) | |
46 return True | |
47 | |
48 def run(self, server): | |
49 | |
50 while True: | |
51 self.do(server) | |
52 gevent.sleep(config.FRIDGE_SLEEP) | |
53 | |
54 def do(self, server): | |
55 """ this is the main fridge control logic """ | |
33 wort, fridge, ambient = server.current_temps() | 56 wort, fridge, ambient = server.current_temps() |
34 | 57 |
35 if server.uptime() < config.FRIDGE_DELAY: | 58 fridge_min = params.fridge_setpoint - self.FRIDGE_AIR_MIN_RANGE |
59 fridge_max = params.fridge_setpoint + self.FRIDGE_AIR_MAX_RANGE | |
60 | |
61 wort_max = params.fridge_setpoint + params.fridge_difference | |
62 | |
63 off_time = server.now() - self.fridge_off_clock | |
64 | |
65 if off_time < config.FRIDGE_DELAY: | |
36 L("fridge skipping, too early") | 66 L("fridge skipping, too early") |
37 return | 67 return |
38 | 68 |
39 # handle broken wort sensor | 69 # handle broken wort sensor |
40 if wort is not None: | 70 if wort is not None: |
47 return | 77 return |
48 | 78 |
49 if fridge is None: | 79 if fridge is None: |
50 W("Invalid fridge sensor") | 80 W("Invalid fridge sensor") |
51 | 81 |
52 | 82 if self.is_on(): |
83 turn_off = False | |
84 on_time = server.now() - self.fridge_on_clock | |
53 | 85 |
54 | 86 overshoot = 0 |
87 if on_time > params.overshoot_delay: | |
88 overshoot = params.overshoot_factor \ | |
89 * min(self.OVERSHOOT_MAX_DIV, on_time) \ | |
90 / self.OVERSHOOT_MAX_DIV | |
91 L("on_time %(on_time)f, overshoot %(overshoot)f" % locals()) | |
55 | 92 |
56 | 93 if wort is not None: |
94 if (wort - overshoot) < params.fridge_setpoint: | |
95 L("wort has cooled enough") | |
96 turn_off = True | |
97 else: | |
98 # wort sensor is broken | |
99 if fridge is not None and last_fridge < fridge_min: | |
100 W("fridge off fallback") | |
101 turn_off = True | |
57 | 102 |
58 def run(self, server): | 103 if turn_off: |
59 self.server = server | 104 L("Turning fridge off") |
105 self.off() | |
106 self.fridge_off_clock = server.now() | |
60 | 107 |
61 while True: | 108 else: |
62 self.do() | 109 # fridge is off |
63 gevent.sleep(config.FRIDGE_SLEEP) | 110 turn_on = False |
111 if wort is not None: | |
112 if wort >= wort_max: | |
113 L("Wort is too hot") | |
114 turn_on = True | |
115 else: | |
116 # wort sensor is broken | |
117 if fridge is not None and fridge >= fridge_max: | |
118 W("frdge on fallback") | |
119 turn_on = True | |
120 | |
121 if turn_on: | |
122 L("Turning fridge on") | |
123 self.on() | |
124 fridge_on_clock = server.now() |