Extend control support to refrigerator, modify recipes accordingly.

Also, update yogurt recipe to support freezer
master
Nicolò Balzarotti 2023-02-25 10:56:13 +01:00
parent c29b3d49cf
commit 256df00325
3 changed files with 53 additions and 44 deletions

View File

@ -7,6 +7,13 @@ class FixedDutyCycle(controllers.Controller):
self.start = kwargs.pop('start_time', perf_counter()) self.start = kwargs.pop('start_time', perf_counter())
self.period = kwargs.pop('period') self.period = kwargs.pop('period')
self.set_duty(kwargs.pop('duty_perc')) self.set_duty(kwargs.pop('duty_perc'))
operator = kwargs.pop('operator', '<')
functions = {
'<': lambda (a, b): a < b,
'>': lambda (a, b): a > b,
'==': lambda (a, b): a == b,
}
self.operator = functions[operator]
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.last_time = None self.last_time = None
self.total_failed_read = 0 self.total_failed_read = 0
@ -42,7 +49,7 @@ class FixedDutyCycle(controllers.Controller):
return False return False
self.failed_read = 0 self.failed_read = 0
return (self.timepoint() < self.duty) if ( return (self.timepoint() < self.duty) if (
self.input < self.target) else False self.operator(self.input, self.target)) else False
# 0. refractary_period is fixed (e.g. 30s, depends on the hardware) # 0. refractary_period is fixed (e.g. 30s, depends on the hardware)
@ -57,9 +64,10 @@ class FixedDutyCycle(controllers.Controller):
# HOW LONG MUST BE THE HISTORY? # HOW LONG MUST BE THE HISTORY?
def fixed_duty_wrapper(args): def fixed_duty_wrapper(args):
name, duty, period = stringify(args.car, quote=False), args.cdr.car, args.cdr.cdr.car name, duty, period, op = stringify(
print('name, duty, period', name, duty*100, period) args.car, quote=False), args.cdr.car, args.cdr.cdr.car, args.cdr.cdr.cdr.car
print('name, duty, period, operation', name, duty*100, period, op)
return (name, FixedDutyCycle( return (name, FixedDutyCycle(
target=None, # reach_period_s=60*60, target=None, # reach_period_s=60*60,
duty_perc=duty*100, period=period, duty_perc=duty*100, period=period,
start_time=perf_counter())) start_time=perf_counter(), operator=op))

View File

@ -10,7 +10,7 @@ from actuators import actuators
from utils import consumption_diff, consumption_to_string, stohms from utils import consumption_diff, consumption_to_string, stohms
MY_GLOBAL_ENV = ( MY_GLOBAL_ENV = (
_('make-duty-controller', 3, fixed_duty_wrapper, _('make-duty-controller', 4, fixed_duty_wrapper,
_('format-time', 1, lambda x: stohms(x.car), _('format-time', 1, lambda x: stohms(x.car),
GLOBAL_ENV))) GLOBAL_ENV)))

View File

@ -3,8 +3,8 @@
"name": "Koji Rice (MISO)", "name": "Koji Rice (MISO)",
"description": "Tiene riso alla temperatura e umidità giuste per il koji", "description": "Tiene riso alla temperatura e umidità giuste per il koji",
"controllers": [ "controllers": [
"(make-duty-controller \"heater\" 0.40 60)", "(make-duty-controller \"heater\" 0.40 60 '<)",
"(make-duty-controller \"humidifier\" 0.80 100)" "(make-duty-controller \"humidifier\" 0.10 100 '<)"
], ],
"phases": [ "phases": [
{ {
@ -62,7 +62,7 @@
"name": "Tepache", "name": "Tepache",
"description": "Tiene il tepache a ~23 gradi", "description": "Tiene il tepache a ~23 gradi",
"controllers": [ "controllers": [
"(make-duty-controller \"heater\" 0.20 120)" "(make-duty-controller \"heater\" 0.20 120 '<)"
], ],
"phases": [ "phases": [
{ {
@ -78,7 +78,7 @@
"name": "Stracchino", "name": "Stracchino",
"description": "Tiene lo stracchino a ~35 gradi per 24 ore", "description": "Tiene lo stracchino a ~35 gradi per 24 ore",
"controllers": [ "controllers": [
"(make-duty-controller \"heater\" 0.80 120)" "(make-duty-controller \"heater\" 0.80 120 '<)"
], ],
"phases": [ "phases": [
{ {
@ -90,48 +90,49 @@
} }
] ]
}, },
{ {
"name": "Yogurt", "name": "Yogurt",
"description": "Pastorizza lo yogurt a 82 gradi, lascia raffreddare per fare l'inoculo, mantiene a 42 gradi fino a che è pronto.", "description": "Lascia raffreddare lo yogurt per fare l'inoculo, mantiene a 42 gradi fino a che è pronto, e poi porta a 4 gradi.",
"controllers": [ "controllers": [
"(make-duty-controller \"heater\" 0.20 120)" "(make-duty-controller \"heater\" 0.20 120 '<)"
], "(make-duty-controller \"freezer\" 0.20 120 '>)"
"phases": [ ],
{ "phases": [
"name": "Riscalda", {
"description": "Preheat yogurt to 82°C", "name": "Cool",
"exit_condition": "(and (>= (get-sensor \"T_food\") 81.5)\n(> (time-in-this-phase) (minutes 15)))", "description": "Cool to 46°C",
"on_load": "(begin (set-controller \"heater\" \"T_food\")\n(set-target \"T_food\" 82.0))", "exit_condition": "(and (< (get-sensor \"T_food\") 46.0)\n(> (get-sensor \"T_food\") 42.0))",
"on_exit": "#t" "on_load": "(begin (set-controller \"heater\" \"T_food\") (set-target \"T_food\" 46.0) (set-controller \"freezer\" \"T_ext\") (set-target \"T_ext\" 46.0))",
"on_exit": "#t"
}, },
{ {
"name": "Cool", "name": "Inoculate (backslopping)",
"description": "Cool to 46°C", "description": "Add 50ml Yogurt",
"exit_condition": "(and (< (get-sensor \"T_food\") 46.0)\n(> (get-sensor \"T_food\") 42.0))", "exit_condition": "(manual-intervention \"Inocula 50g di yogurt\" '((\"Fatto\" #t)))",
"on_load": "(set-target \"T_food\" 46.0)", "on_load": "(notify \"Inoculate 50g of yogurt NOW!\")",
"on_exit": "#t" "on_exit": "(notify (concat \"Inoculated at \" (now)))"
}, },
{ {
"name": "Inoculate (backslopping)", "name": "Hold",
"description": "Add 50ml Yogurt", "description": "Keep at 42°C for 3h",
"exit_condition": "(manual-intervention \"Inocula 50g di yogurt\" '((\"Fatto\" #t)))", "exit_condition": "(> (time-in-this-phase) (hours 3))",
"on_load": "(notify \"Inoculate 50g of yogurt NOW!\")", "on_load": "(begin (set-target \"T_food\" 41.0) (set-target \"T_ext\" 41.0))",
"on_exit": "(notify (concat \"Inoculated at \" (now)))" "on_exit": "(notify \"You can remove the yogurt from the heater\")"
}, },
{ {
"name": "Hold", "name": "Refrigerate",
"description": "Keep at 42°C for 3h", "description": "Lower temperature to 4gradi",
"exit_condition": "(> (time-in-this-phase) (hours 3))", "exit_condition": "#f",
"on_load": "(set-target \"T_food\" 41.0)", "on_load": "(begin (set-target \"T_food\" 4.0) (set-target \"T_ext\" 4.0))",
"on_exit": "(notify \"You can remove the yogurt from the heater\")" "on_exit": "(notify \"You can remove the yogurt from the heater\")"
} }
] ]
}, },
{ {
"name": "Nattō", "name": "Nattō",
"description": "FIXME", "description": "FIXME",
"controllers": [ "controllers": [
"(make-duty-controller \"heater\" 0.20 120)" "(make-duty-controller \"heater\" 0.20 120 '<)"
], ],
"phases": [] "phases": []
}, },
@ -139,7 +140,7 @@
"name": "Tempeh", "name": "Tempeh",
"description": "FIXME", "description": "FIXME",
"controllers": [ "controllers": [
"(make-duty-controller \"heater\" 0.20 120)" "(make-duty-controller \"heater\" 0.20 120 '<)"
], ],
"phases": [] "phases": []
}, },
@ -147,7 +148,7 @@
"name": "Gorgonzola", "name": "Gorgonzola",
"description": "FIXME", "description": "FIXME",
"controllers": [ "controllers": [
"(make-duty-controller \"heater\" 0.20 120)" "(make-duty-controller \"heater\" 0.20 120 '<)"
], ],
"phases": [] "phases": []
} }