brewco/brewco.c

changeset 473
fdd30e935079
parent 472
55bcbf92ecab
child 474
fe1c3e3e90dc
equal deleted inserted replaced
472:55bcbf92ecab 473:fdd30e935079
32 #include "devices.h" 32 #include "devices.h"
33 #include "keyboard.h" 33 #include "keyboard.h"
34 #include "simulator.h" 34 #include "simulator.h"
35 #include "prompt.h" 35 #include "prompt.h"
36 #include "setup.h" 36 #include "setup.h"
37 #include "logger.h"
37 38
38 39
39 40
40 int my_shutdown = FALSE; 41 int my_shutdown = FALSE;
41 int man_mlt_pump = 0; 42 int mlt_pump_state = 0;
42 43
43 double hltInput; /* HLT PID variables */ 44 double hltInput; /* HLT PID variables */
44 double hltOutput; 45 double hltOutput;
45 double hltSetpoint; 46 double hltSetpoint;
46 double mltInput; /* MLT PID variables */ 47 double mltInput; /* MLT PID variables */
137 my_shutdown = TRUE; 138 my_shutdown = TRUE;
138 } 139 }
139 140
140 141
141 142
142 void tempstatus(double hlttemp, double mlttemp) 143 void tempstatus(void)
143 { 144 {
144 char text[81]; 145 char text[81];
145 146
146 snprintf(text, 8, "%6.2f\001", hltInput); 147 snprintf(text, 8, "%6.2f\001", hltInput);
147 #ifdef HAVE_WIRINGPI_H 148 #ifdef HAVE_WIRINGPI_H
196 slcdPuts(slcdHandle, text); 197 slcdPuts(slcdHandle, text);
197 } 198 }
198 199
199 200
200 201
201 void automatic_brew(units_list *, brew_session *, a_recipe *, int); 202 /*
202 void automatic_brew(units_list *unit, brew_session *brew, a_recipe *recipe, int dosave) 203 * Third line during boil, only MLT status
204 */
205 void mltstatus(void)
203 { 206 {
204 int key, save = dosave; 207 char text[21];
205 208
206 // if (debug) 209 snprintf(text, 20, "MLT %3d%% %6.2f\002 ", (int)mltOutput, mltSetpoint);
207 // fprintf(stdout, "auto: step %d\n", brew->brewstep); 210 #ifdef HAVE_WIRINGPI_H
211 piLock(LOCK_LCD);
212 lcdPosition(lcdHandle, 0, 2);
213 lcdPuts(lcdHandle, text);
214 #endif
215 slcdPosition(slcdHandle, 0, 2);
216 slcdPuts(slcdHandle, text);
217 }
218
219
220
221 void timestatus(int row, int timeval)
222 {
223 char text[21];
224 int hours, mins, val = timeval;
225
226 hours = val / 3600;
227 val -= (hours * 3600);
228 mins = val / 60;
229 val -= (mins * 60);
230
231 snprintf(text, 20, " %02d:%02d:%02d ", hours, mins, val);
232 #ifdef HAVE_WIRINGPI_H
233 piLock(LOCK_LCD);
234 lcdPosition(lcdHandle, 0, row);
235 lcdPuts(lcdHandle, text);
236 #endif
237 slcdPosition(slcdHandle, 0, row);
238 slcdPuts(slcdHandle, text);
239 }
240
241
242
243 int set_HLT_heater(units_list *unit, int state, double val)
244 {
245 if (strcmp(unit->hlt_heater.uuid, (char *)"00000000-0000-0000-0000-000000000000") == 0)
246 return 0;
247
248 hltSetpoint = val;
249
250 if (state && (PID_getMode(unit->PID_hlt) == P_MANUAL)) {
251 hlt_status(1);
252 PID_setMode(unit->PID_hlt, P_AUTOMATIC);
253 return 1;
254 }
255 if (! state && (PID_getMode(unit->PID_hlt) == P_AUTOMATIC)) {
256 hlt_status(0);
257 PID_setMode(unit->PID_hlt, P_MANUAL);
258 return 1;
259 }
260
261 return 0;
262 }
263
264
265
266 int set_MLT_heater(units_list *unit, int state, double val)
267 {
268 if (strcmp(unit->mlt_heater.uuid, (char *)"00000000-0000-0000-0000-000000000000") == 0)
269 return 0;
270
271 mltSetpoint = val;
272
273 if (state && (PID_getMode(unit->PID_mlt) == P_MANUAL)) {
274 mlt_status(1);
275 PID_setMode(unit->PID_mlt, P_AUTOMATIC);
276 return 1;
277 }
278 if (! state && (PID_getMode(unit->PID_mlt) == P_AUTOMATIC)) {
279 mlt_status(0);
280 PID_setMode(unit->PID_mlt, P_MANUAL);
281 return 1;
282 }
283
284 return 0;
285 }
286
287
288
289 int set_MLT_pump(units_list *unit, int state)
290 {
291 if (strcmp(unit->mlt_pump.uuid, (char *)"00000000-0000-0000-0000-000000000000") == 0)
292 return 0;
293
294 if (state && ! mlt_pump_state) {
295 device_out(unit->mlt_pump.uuid, 1);
296 mlt_pump_state = 1;
297 return 1;
298 }
299 if (! state && mlt_pump_state) {
300 device_out(unit->mlt_pump.uuid, 0);
301 mlt_pump_state = 0;
302 return 1;
303 }
304
305 return 0;
306 }
307
308
309
310 void automatic_brew(units_list *, brew_session *, a_recipe *, int, int);
311 void automatic_brew(units_list *unit, brew_session *brew, a_recipe *recipe, int dosave, int seconds)
312 {
313 int key, save = dosave, i;
314 char data[128];
315 static int mash_fase = MASH_NA, hopstand = 0, last_step = -1, last_fase = -1, oldsec = 75, startdelay = 0;
208 316
209 switch (brew->brewstep) { 317 switch (brew->brewstep) {
210 case STEP_NA: if (debug) 318 case STEP_NA: if (debug)
211 fprintf(stdout, "auto: init recipe: %s-%s unit: %s\n", recipe->code, recipe->name, unit->name); 319 fprintf(stdout, "auto: init recipe: %s-%s unit: %s\n", recipe->code, recipe->name, unit->name);
212 syslog(LOG_NOTICE, "AUTO: starting new brew, recipe: %s-%s unit: %s", recipe->code, recipe->name, unit->name); 320 syslog(LOG_NOTICE, "AUTO: starting new brew, recipe: %s-%s unit: %s", recipe->code, recipe->name, unit->name);
321 brew->brewstep = STEP_BREWINIT;
322 break;
323
324 case STEP_BREWINIT: prompt(103, NULL); /* " AUTOMATIC MODE " */
325 prompt(207, NULL); /* " Delay start? " */
326 prompt(300, NULL); /* " " */
327 prompt(407, NULL); /* "--- --- No Yes " */
328 if (debug)
329 fprintf(stdout, "step brewinit\n");
330 key = keywait();
331 if (key == KEY_RETURN) {
332 brew->brewstep = STEP_WATERCHECK;
333 startdelay = 0;
334 syslog(LOG_NOTICE, "AUTO: brew initialize, direct start selected");
335 break;
336 }
337 if (key == KEY_ENTER) {
338 startdelay = 30;
339 editInteger(&startdelay, 10, 960, 10, (char *)"Start delay", (char *)"mins");
340 }
341 syslog(LOG_NOTICE, "AUTO: brew initialize");
342 brew->brewstep = STEP_WATERCHECK;
343 break;
344
345 case STEP_WATERCHECK: if (brew->brewstep != last_step) {
346 prompt(111, NULL); /* "AUTO --> Mash In " */
347 prompt(209, NULL); /* " Water Added? " */
348 prompt(300, NULL);
349 prompt(410, NULL); /* " Continue: Yes No " */
350 last_step = brew->brewstep;
351 }
352 slcdDummy(slcdHandle);
353 key = keycheck();
354 if (key == KEY_RETURN) {
355 brew->brewstep = STEP_PUMPPRIME;
356 syslog(LOG_NOTICE, "AUTO: confirmed water added");
357 }
358 if (key == KEY_ENTER) {
359 syslog(LOG_NOTICE, "AUTO: aborted water added");
360 brew->brewstep = STEP_CLEANUP;
361 }
362 break;
363
364 case STEP_PUMPPRIME: if (brew->brewstep != last_step) {
365 prompt(111, NULL); /* "AUTO --> Mash In " */
366 prompt(210, NULL); /* " Pump Prime " */
367 prompt(300, NULL); /* " " */
368 prompt(400, NULL); /* " " */
369 last_step = brew->brewstep;
370 }
371 brew->brewstep = STEP_WAITSTART;
372 break;
373
374 case STEP_WAITSTART: if (startdelay == 0) {
375 brew->brewstep = STEP_PREMASH;
376 break;
377 }
378 if (brew->brewstep != last_step) {
379 brew->timeout = startdelay * 60;
380 prompt(111, NULL); /* "AUTO --> Mash In " */
381 prompt(212, NULL); /* " To be started in " */
382 prompt(410, NULL); /* " Continue: Yes No " */
383 last_step = brew->brewstep;
384 }
385 if (oldsec != seconds) {
386 timestatus(2, brew->timeout);
387 brew->timeout--;
388 if (brew->timeout <= 0) {
389 syslog(LOG_NOTICE, "AUTO: delayed start time reached");
390 brew->brewstep = STEP_PREMASH;
391 }
392 oldsec = seconds;
393 }
394 slcdDummy(slcdHandle);
395 key = keycheck();
396 if (key == KEY_RETURN) {
397 syslog(LOG_NOTICE, "AUTO: delayed start skipped by user");
398 brew->brewstep = STEP_PREMASH;
399 }
400 break;
401
402 case STEP_PREMASH: if (brew->brewstep != last_step) {
403 prompt(111 + brew->mashstep, NULL); /* "AUTO --> [mashname] " */
404 prompt(300, NULL); /* " " */
405 prompt(418, NULL); /* "--- --- Pause --- " */
406 tempstatus();
407 hlt_status(1);
408 mlt_status(1);
409 pump_status(unit->pump_premash);
410 last_step = brew->brewstep;
411 }
412 initlog(brew->name);
413 if (set_HLT_heater(unit, 1, 85.0))
414 syslog(LOG_NOTICE, "AUTO: premash turn on HLT at %6.2f", hltSetpoint);
415 if (set_MLT_heater(unit, 1, recipe->mash[0].setpoint))
416 syslog(LOG_NOTICE, "AUTO: premash turn on MLT at %6.2f", mltSetpoint);
417 if (set_MLT_pump(unit, unit->pump_premash))
418 syslog(LOG_NOTICE, "AUTO: premash turn %s MLT pump", mlt_pump_state ? "on":"off");
419 brew->brewstep = STEP_MASHING;
420 brew->mashstep = 0;
421 mash_fase = MASH_NA;
422 save = TRUE;
423 break;
424
425 case STEP_MASHING: if (brew->brewstep != last_step) {
426 prompt(111 + brew->mashstep, NULL); /* "AUTO --> [mashname] " */
427 prompt(300, NULL); /* " " */
428 prompt(418, NULL); /* "--- --- Pause --- " */
429 tempstatus();
430 hlt_status(1);
431 mlt_status(1);
432 pump_status(unit->pump_onmash);
433 last_step = brew->brewstep;
434 }
435 if (set_HLT_heater(unit, 1, 85.0))
436 syslog(LOG_NOTICE, "AUTO: mash turn on HLT at %6.2f", hltSetpoint);
437 if (set_MLT_heater(unit, 1, recipe->mash[brew->mashstep].setpoint))
438 syslog(LOG_NOTICE, "AUTO: mash turn on MLT at %6.2f", mltSetpoint);
439 if ((mash_fase != MASH_REST) && set_MLT_pump(unit, unit->pump_onmash))
440 syslog(LOG_NOTICE, "AUTO: mash turn %s MLT pump", mlt_pump_state ? "on":"off");
441
442 switch (mash_fase) {
443 case MASH_NA: if (recipe->mash[brew->mashstep].skip) {
444 syslog(LOG_NOTICE, "AUTO: skipping mash step %d", brew->mashstep);
445 brew->mashstep++;
446 } else {
447 mltSetpoint = recipe->mash[brew->mashstep].setpoint;
448 brew->timeout = recipe->mash[brew->mashstep].duration * 60;
449 if ((brew->mashstep == 0) && ! unit->skip_add) {
450 mash_fase = MASH_PROMPT;
451 } else
452 mash_fase = MASH_HEATING;
453 syslog(LOG_NOTICE, "AUTO: mash step %d fase NA, setpoint %6.2f, duration %d",
454 brew->mashstep, mltSetpoint, brew->timeout);
455 }
456 if (brew->mashstep == 0) {
457 brew->starttime = time(NULL);
458 save = TRUE;
459 }
460 break;
461
462 case MASH_PROMPT: if (last_fase != mash_fase) {
463 prompt(111 + brew->mashstep, NULL); /* "AUTO --> [mashname] " */
464 prompt(219, NULL); /* " Mash added? " */
465 prompt(300, NULL);
466 prompt(410, NULL); /* " Continue: Yes No " */
467 last_fase = mash_fase;
468 }
469 slcdDummy(slcdHandle);
470 key = keycheck();
471 if (key == KEY_RETURN) {
472 mash_fase = MASH_HEATING;
473 syslog(LOG_NOTICE, "AUTO: confirmed mash added");
474 }
475 if (key == KEY_ENTER) {
476 syslog(LOG_NOTICE, "AUTO: aborted mash added");
477 brew->brewstep = STEP_CLEANUP;
478 brew->mashstep = 0;
479 }
480 break;
481
482 case MASH_IODINE: if (last_fase != mash_fase) {
483 prompt(118, NULL); /* "AUTO --> Mash Out " */
484 prompt(213, NULL); /* " Iodine test " */
485 timestatus(2, brew->timeout);
486 prompt(410, NULL); /* " Continue: Yes No " */
487 last_fase = mash_fase;
488 }
489 if (oldsec != seconds) {
490 brew->timeout--;
491 timestatus(2, brew->timeout);
492 if (brew->timeout <= 0) {
493 syslog(LOG_NOTICE, "AUTO: mash IODINE test timeout");
494 mash_fase = MASH_NA;
495 brew->mashstep++;
496 }
497 oldsec = seconds;
498 }
499 slcdDummy(slcdHandle);
500 key = keycheck();
501 if (key == KEY_RETURN) {
502 syslog(LOG_NOTICE, "AUTO: mash IODINE test confirmed");
503 mash_fase = MASH_NA;
504 brew->mashstep++;
505 }
506 if (key == KEY_ENTER) {
507 syslog(LOG_NOTICE, "AUTO: mash IODINE test declined");
508 mash_fase = MASH_REST;
509 brew->timeout = 600; /* Add 10 more minutes */
510 }
511 break;
512
513 case MASH_HEATING: if (last_fase != mash_fase) {
514 prompt(111 + brew->mashstep, NULL); /* "AUTO --> [mashname] " */
515 prompt(200, NULL);
516 prompt(300, NULL);
517 prompt(418, NULL); /* "--- --- Pause --- " */
518 hlt_status(1);
519 mlt_status(1);
520 pump_status(unit->pump_onmash);
521 last_fase = mash_fase;
522 }
523 if (oldsec != seconds) {
524 tempstatus();
525 percstatus((seconds / 2) % 4);
526 oldsec = seconds;
527 }
528 if (mltInput > mltSetpoint) {
529 syslog(LOG_NOTICE, "AUTO: mash step %d fase HEATING reached %6.2f", brew->mashstep, mltSetpoint);
530 mash_fase = MASH_REST;
531 }
532 break;
533
534 case MASH_REST: if (last_fase != mash_fase) {
535 prompt(111 + brew->mashstep, NULL); /* "AUTO --> [mashname] " */
536 prompt(300, NULL);
537 prompt(418, NULL); /* "--- --- Pause --- " */
538 hlt_status(1);
539 mlt_status(1);
540 pump_status(unit->pump_onmash);
541 last_fase = mash_fase;
542 }
543 if (oldsec != seconds) {
544 tempstatus();
545 timestatus(2, brew->timeout);
546 if (brew->mashstep == 7) {
547 /*
548 * During mash-out rest, allow the grain to sink
549 */
550 if (set_MLT_pump(unit, unit->pump_mashout))
551 syslog(LOG_NOTICE, "AUTO: mash-out turn %s MLT pump", mlt_pump_state ? "on":"off");
552 } else {
553 if (set_MLT_pump(unit, unit->pump_onmash))
554 syslog(LOG_NOTICE, "AUTO: mash turn %s MLT pump", mlt_pump_state ? "on":"off");
555 }
556 brew->timeout--;
557 if (brew->timeout <= 0) {
558 syslog(LOG_NOTICE, "AUTO: mash step %d fase REST done", brew->mashstep);
559 if ((brew->mashstep == 6) && ! unit->skip_iodine) {
560 mash_fase = MASH_IODINE;
561 brew->timeout = unit->iodine_time * 60;
562 } else if (brew->mashstep == 7) {
563 mash_fase = MASH_DONE;
564 } else {
565 mash_fase = MASH_NA;
566 brew->mashstep++;
567 }
568 }
569 oldsec = seconds;
570 }
571 break;
572
573 case MASH_DONE: syslog(LOG_NOTICE, "AUTO: mash step %d fase DONE", brew->mashstep);
574 if (set_MLT_heater(unit, 1, recipe->mash[7].setpoint))
575 syslog(LOG_NOTICE, "AUTO: mash done turn MLT off");
576 if (set_MLT_pump(unit, 0))
577 syslog(LOG_NOTICE, "AUTO: mash done turn %s MLT pump", mlt_pump_state ? "on":"off");
578 brew->mashstep = 0;
579 brew->brewstep = STEP_MASHREMOVE;
580 break;
581 }
582 break;
583
584 case STEP_MASHREMOVE: if (unit->skip_remove) {
585 syslog(LOG_NOTICE, "AUTO: skipping Mash remove");
586 brew->brewstep = STEP_PREBOIL;
587 } else {
588 if (brew->brewstep != last_step) {
589 prompt(118, NULL); /* "AUTO --> Mash Out " */
590 prompt(220, NULL); /* " Mash Removed? " */
591 prompt(300, NULL);
592 prompt(410, NULL); /* " Continue: Yes No " */
593 last_step = brew->brewstep;
594 }
595 slcdDummy(slcdHandle);
596 key = keycheck();
597 if (key == KEY_RETURN) {
598 syslog(LOG_NOTICE, "AUTO: Confirmed Mash removed");
599 brew->brewstep = STEP_PREBOIL;
600 }
601 }
602 break;
603
604 case STEP_PREBOIL: if (brew->brewstep != last_step) {
605 prompt(119, NULL); /* "AUTO --> Boil " */
606 prompt(200, NULL);
607 prompt(300, NULL);
608 tempstatus();
609 mltstatus();
610 prompt(418, NULL); /* "--- --- Pause --- " */
611 hlt_status(0);
612 mlt_status(1);
613 pump_status(unit->pump_onboil && (mltInput < unit->pump_stop));
614 last_step = brew->brewstep;
615 }
616 if (oldsec != seconds) {
617 tempstatus();
618 mltstatus();
619 oldsec = seconds;
620 }
621 if (set_HLT_heater(unit, 0, 10.0))
622 syslog(LOG_NOTICE, "AUTO: preboil turn off HLT");
623 if (set_MLT_heater(unit, 1, 100.0))
624 syslog(LOG_NOTICE, "AUTO: preboil turn on MLT to boil");
625 if (set_MLT_pump(unit, unit->pump_onboil && (mltInput < unit->pump_stop)))
626 syslog(LOG_NOTICE, "AUTO: preboil turn %s MLT pump", mlt_pump_state ? "on":"off");
627 if (mltInput > 99.2) {
628 syslog(LOG_NOTICE, "AUTO: reached boil temperature %.2f, start %d minutes boil", mltInput, recipe->boiltime);
629 brew->brewstep = STEP_BOILING;
630 brew->boiltimer = recipe->boiltime * 60;
631 }
632 break;
633
634 case STEP_BOILING: if (set_HLT_heater(unit, 0, 10.0))
635 syslog(LOG_NOTICE, "AUTO: boil turn off HLT");
636 if (set_MLT_heater(unit, 1, 100.0))
637 syslog(LOG_NOTICE, "AUTO: boil turn on MLT to boil");
638 if (set_MLT_pump(unit, unit->pump_onboil && (mltInput < unit->pump_stop)))
639 syslog(LOG_NOTICE, "AUTO: boil turn %s MLT pump", mlt_pump_state ? "on":"off");
640 if (brew->brewstep != last_step) {
641 prompt(119, NULL); /* "AUTO --> Boil " */
642 prompt(200, NULL);
643 prompt(300, NULL);
644 tempstatus();
645 mltstatus();
646 prompt(418, NULL); /* "--- --- Pause --- " */
647 hlt_status(0);
648 mlt_status(1);
649 pump_status(unit->pump_onboil && (mltInput < unit->pump_stop));
650 last_step = brew->brewstep;
651 }
652 if (oldsec != seconds) {
653 tempstatus();
654 if ((seconds / 2) % 4) {
655 timestatus(2, brew->boiltimer);
656 } else {
657 mltstatus();
658 }
659 if (brew->boiltimer >= 0) {
660 brew->boiltimer--;
661 } else {
662 brew->brewstep = STEP_BOILDONE;
663 syslog(LOG_NOTICE, "AUTO: boil is done");
664 }
665 oldsec = seconds;
666 }
667 break;
668
669 case STEP_BOILDONE: if (set_MLT_heater(unit, 0, 10.0))
670 syslog(LOG_NOTICE, "AUTO: after boil turn off MLT heater");
671 if (set_MLT_pump(unit, 0))
672 syslog(LOG_NOTICE, "AUTO: after boil turn %s MLT pump", mlt_pump_state ? "on":"off");
673 if (brew->brewstep != last_step) {
674 prompt(120, NULL); /* "AUTO --> Cooling " */
675 prompt(214, NULL); /* " START COOLING " */
676 prompt(300, NULL);
677 prompt(410, NULL); /* " Continue: Yes No " */
678 last_step = brew->brewstep;
679 }
680 slcdDummy(slcdHandle);
681 key = keycheck();
682 if (key == KEY_ENTER) {
683 brew->brewstep = STEP_CLEANUP;
684 syslog(LOG_NOTICE, "AUTO: user skipped cooling");
685 }
686 if (key == KEY_RETURN) {
687 brew->brewstep = STEP_COOLING;
688 syslog(LOG_NOTICE, "AUTO: user started cooling");
689 }
690 break;
691
692 case STEP_COOLING: for (i = 0; i < 3; i++) {
693 if ((recipe->hopstand[i].skip == 0) && (mltInput <= recipe->hopstand[i].max) && (mltInput >= recipe->hopstand[i].min)) {
694 brew->brewstep = STEP_HOPSTAND;
695 hopstand = i;
696 syslog(LOG_NOTICE, "AUTO: starting hopstand %d", i+1);
697 }
698 }
699 if (brew->brewstep == STEP_HOPSTAND)
700 break;
701 // hot whirlpool start at 85 degrees
702 // cold whirlpool start at 30 degrees
703
704 if (brew->brewstep != last_step) {
705 prompt(120, NULL); /* "AUTO --> Cooling " */
706 prompt(200, NULL);
707 tempstatus();
708 prompt(300, NULL);
709 prompt(418, NULL); /* "--- --- Pause --- " */
710 hlt_status(0);
711 mlt_status(0);
712 pump_status(0);
713 last_step = brew->brewstep;
714 }
715 if (oldsec != seconds) {
716 tempstatus();
717 oldsec = seconds;
718 }
719 if (mltInput <= recipe->coolto) {
720 syslog(LOG_NOTICE, "AUTO: cool temperture %.2f reached", recipe->coolto);
721 brew->brewstep = STEP_CLEANUP;
722 }
723 break;
724
725 case STEP_HOPSTAND: if (brew->brewstep != last_step) {
726 prompt(122 + hopstand, NULL); /* "AUTO --> Hopstand n " */
727 tempstatus();
728 timestatus(2, brew->timeout);
729 prompt(418, NULL); /* "--- --- Pause --- " */
730 brew->boiltimer = recipe->hopstand[hopstand].duration * 60;
731 last_step = brew->brewstep;
732 }
733
734 if (recipe->hopstand[hopstand].hold) {
735 if (set_MLT_heater(unit, 1, recipe->hopstand[hopstand].setpoint))
736 syslog(LOG_NOTICE, "AUTO: hopstand 1 turn on MLT at %6.2f", mltSetpoint);
737 }
738 if (set_MLT_pump(unit, 1))
739 syslog(LOG_NOTICE, "AUTO: hopstand 1 turn %s MLT pump", mlt_pump_state ? "on":"off");
740 if (oldsec != seconds) {
741 tempstatus();
742 timestatus(2, brew->timeout);
743 brew->boiltimer--;
744 if (brew->boiltimer <= 0) {
745 syslog(LOG_NOTICE, "AUTO: hopstand %d done", hopstand+1);
746 if (set_MLT_heater(unit, 0, 10.0))
747 syslog(LOG_NOTICE, "AUTO: hopstand 1 turn off MLT at %6.2f", mltSetpoint);
748 brew->brewstep = STEP_COOLING;
749 }
750 oldsec = seconds;
751 }
752 break;
753
754 case STEP_WHIRLPOOL: prompt(121, NULL); /* "AUTO --> Whirlpool " */
755 break;
756
757 case STEP_CLEANUP: if (brew->brewstep != last_step) {
758 prompt(101, NULL); /* " Brewco x.x.x " */
759 prompt(200, NULL); /* " " */
760 prompt(300, NULL); /* " " */
761 prompt(400, NULL); /* " " */
762 last_step = brew->brewstep;
763 }
764 syslog(LOG_NOTICE, "AUTO: cleanup");
765 if (set_HLT_heater(unit, 0, 10.0))
766 syslog(LOG_NOTICE, "AUTO: cleanup turn on HLT at %6.2f", hltSetpoint);
767 if (set_MLT_heater(unit, 0, 10.0))
768 syslog(LOG_NOTICE, "AUTO: cleanup turn on MLT at %6.2f", mltSetpoint);
769 if (set_MLT_pump(unit, 0))
770 syslog(LOG_NOTICE, "AUTO: cleanup turn %s MLT pump", mlt_pump_state ? "on":"off");
213 brew->brewstep = STEP_BREWDONE; 771 brew->brewstep = STEP_BREWDONE;
214 break; 772 break;
215 773
216 case STEP_BREWINIT: 774 case STEP_BREWDONE: if (brew->brewstep != last_step) {
217 break; 775 prompt(101, NULL); /* " Brewco x.x.x " */
218 case STEP_WATERCHECK: prompt(111, NULL); /* "AUTO --> Mash In " */ 776 prompt(200, NULL); /* " " */
219 prompt(209, NULL); /* " Water Added? " */ 777 prompt(301, NULL); /* " Finished " */
220 break; 778 prompt(408, NULL); /* "--- --- Ok --- " */
221 case STEP_PUMPPRIME: prompt(111, NULL); /* "AUTO --> Mash In " */ 779 last_step = brew->brewstep;
222 prompt(210, NULL); /* " Pump Prime " */ 780 }
223 break; 781 syslog(LOG_NOTICE, "AUTO: brew done");
224 case STEP_WAITSTART: prompt(111, NULL); /* "AUTO --> Mash In " */
225 prompt(212, NULL); /* " To be started in " */
226 break;
227 case STEP_PREMASH: prompt(111, NULL); /* "AUTO --> Mash In " */
228 /* Heatup until strike temp reached */
229 break;
230 case STEP_MASHING: switch (brew->mashstep) {
231 case 0: prompt(111, NULL);
232 break;
233 case 1: prompt(112, NULL);
234 break;
235 case 2: prompt(113, NULL);
236 break;
237 case 3: prompt(114, NULL);
238 break;
239 case 4: prompt(115, NULL);
240 break;
241 case 5: prompt(116, NULL);
242 break;
243 case 6: prompt(117, NULL);
244 break;
245 case 7: prompt(118, NULL);
246 break;
247 }
248 break;
249 case STEP_IODINE: prompt(118, NULL); /* "AUTO --> Mash Out " */
250 prompt(213, NULL); /* " Iodine test " */
251 break;
252 case STEP_MASHREMOVE: prompt(118, NULL); /* "AUTO --> Mash Out " */
253 break;
254 case STEP_PREBOIL:
255 break;
256 case STEP_BOILING: prompt(119, NULL); /* "AUTO --> Boil " */
257 break;
258 case STEP_BOILDONE:
259 break;
260 case STEP_HOPSTAND1:
261 break;
262 case STEP_COOLING1: prompt(120, NULL); /* "AUTO --> Cooling " */
263 prompt(214, NULL); /* " START COOLING " */
264 break;
265 case STEP_WHIRLPOOL1: prompt(121, NULL); /* "AUTO --> Whirlpool " */
266 break;
267 case STEP_COOLING2: prompt(120, NULL); /* "AUTO --> Cooling " */
268 break;
269 case STEP_HOPSTAND2:
270 break;
271 case STEP_COOLING3: prompt(120, NULL); /* "AUTO --> Cooling " */
272 break;
273 case STEP_HOPSTAND3:
274 break;
275 case STEP_COOLING: prompt(120, NULL); /* "AUTO --> Cooling " */
276 break;
277 case STEP_WHIRLPOOL: prompt(121, NULL); /* "AUTO --> Whirlpool " */
278 break;
279 case STEP_CLEANUP:
280 break;
281 case STEP_BREWDONE: syslog(LOG_NOTICE, "AUTO: brew done");
282 brew->brewstep = -1; 782 brew->brewstep = -1;
283 brew->endtime = time(NULL); 783 brew->endtime = time(NULL);
284 prompt(101, NULL); /* " Brewco x.x.x " */ 784 save = TRUE;
285 prompt(200, NULL); /* " " */
286 prompt(301, NULL); /* " Finished " */
287 prompt(408, NULL); /* "--- --- Ok --- " */
288 do { 785 do {
289 key = keywait(); 786 key = keywait();
290 } while (key != KEY_RETURN); 787 } while (key != KEY_RETURN);
291 /* 788 /*
292 * Rewrite the display 789 * Rewrite the display
293 */ 790 */
294 prompt(101, NULL); /* " Brewco x.x.x " */ 791 prompt(101, NULL); /* " Brewco x.x.x " */
295 prompt(300, NULL); /* " " */ 792 tempstatus();
296 prompt(401, NULL); /* "--- MAN AUTO SETUP" */ 793 prompt(300, NULL); /* " " */
297 break; 794 prompt(401, NULL); /* "--- MAN AUTO SETUP" */
298 } 795 break;
299 796 }
300 if (save) 797
798 if (save) {
799 snprintf(data, 127, "%d,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f", brew->brewstep,
800 hltInput, hltOutput, hltSetpoint, mltInput, mltOutput, mltSetpoint);
801 logger(brew->name, data);
301 wrsession(brew); 802 wrsession(brew);
803 }
302 } 804 }
303 805
304 806
305 807
306 void manual_prompt(void) 808 void manual_prompt(void)
342 manual = MANUAL_SELMLT; 844 manual = MANUAL_SELMLT;
343 manual_prompt(); 845 manual_prompt();
344 } 846 }
345 if (key == KEY_RETURN) { 847 if (key == KEY_RETURN) {
346 manual = MANUAL_NONE; 848 manual = MANUAL_NONE;
347 man_mlt_pump = 0; 849 mlt_pump_state = 0;
348 PID_setMode(unit->PID_mlt, P_MANUAL); 850 PID_setMode(unit->PID_mlt, P_MANUAL);
349 PID_setMode(unit->PID_hlt, P_MANUAL); 851 PID_setMode(unit->PID_hlt, P_MANUAL);
350 hlt_status(0); 852 hlt_status(0);
351 mlt_status(0); 853 mlt_status(0);
352 device_out(unit->mlt_pump.uuid, man_mlt_pump); 854 device_out(unit->mlt_pump.uuid, mlt_pump_state);
353 } 855 }
354 if (key == KEY_ENTER) { 856 if (key == KEY_ENTER) {
355 // TODO: prompt for water 857 // TODO: prompt for water
356 manual = MANUAL_HLT; 858 manual = MANUAL_HLT;
357 manual_prompt(); 859 manual_prompt();
363 manual = MANUAL_SELHLT; 865 manual = MANUAL_SELHLT;
364 manual_prompt(); 866 manual_prompt();
365 } 867 }
366 if (key == KEY_RETURN) { 868 if (key == KEY_RETURN) {
367 manual = MANUAL_NONE; 869 manual = MANUAL_NONE;
368 man_mlt_pump = 0; 870 mlt_pump_state = 0;
369 PID_setMode(unit->PID_mlt, P_MANUAL); 871 PID_setMode(unit->PID_mlt, P_MANUAL);
370 PID_setMode(unit->PID_hlt, P_MANUAL); 872 PID_setMode(unit->PID_hlt, P_MANUAL);
371 hlt_status(0); 873 hlt_status(0);
372 mlt_status(0); 874 mlt_status(0);
373 device_out(unit->mlt_pump.uuid, man_mlt_pump); 875 device_out(unit->mlt_pump.uuid, mlt_pump_state);
374 } 876 }
375 if (key == KEY_ENTER) { 877 if (key == KEY_ENTER) {
376 // TODO: prompt for water 878 // TODO: prompt for water
377 manual = MANUAL_MLT; 879 manual = MANUAL_MLT;
378 manual_prompt(); 880 manual_prompt();
379 } 881 }
380 break; 882 break;
381 case MANUAL_HLT: tempstatus(*unit->PID_hlt->myInput, *unit->PID_mlt->myInput); 883 case MANUAL_HLT: tempstatus();
382 percstatus((seconds / 2) % 4); 884 percstatus((seconds / 2) % 4);
383 885
384 slcdDummy(slcdHandle); 886 slcdDummy(slcdHandle);
385 key = keycheck(); 887 key = keycheck();
386 if (key == KEY_RETURN) { 888 if (key == KEY_RETURN) {
399 if (key == KEY_ESCAPE) { 901 if (key == KEY_ESCAPE) {
400 manual = MANUAL_SELHLT; 902 manual = MANUAL_SELHLT;
401 manual_prompt(); 903 manual_prompt();
402 } 904 }
403 break; 905 break;
404 case MANUAL_MLT: tempstatus(*unit->PID_hlt->myInput, *unit->PID_mlt->myInput); 906 case MANUAL_MLT: tempstatus();
405 percstatus((seconds / 2) % 4); 907 percstatus((seconds / 2) % 4);
406 908
407 slcdDummy(slcdHandle); 909 slcdDummy(slcdHandle);
408 key = keycheck(); 910 key = keycheck();
409 if (key == KEY_RETURN) { 911 if (key == KEY_RETURN) {
418 if ((key == KEY_DOWN) && (mltSetpoint > 10)) 920 if ((key == KEY_DOWN) && (mltSetpoint > 10))
419 mltSetpoint -= 1.0; 921 mltSetpoint -= 1.0;
420 if ((key == KEY_UP) && (mltSetpoint < 100)) 922 if ((key == KEY_UP) && (mltSetpoint < 100))
421 mltSetpoint += 1.0; 923 mltSetpoint += 1.0;
422 if (key == KEY_ENTER) { 924 if (key == KEY_ENTER) {
423 if (man_mlt_pump) 925 if (mlt_pump_state)
424 man_mlt_pump = 0; 926 set_MLT_pump(unit, 0);
425 else 927 else
426 man_mlt_pump = 1; 928 set_MLT_pump(unit, 1);
427 } 929 }
428 if (key == KEY_ESCAPE) { 930 if (key == KEY_ESCAPE) {
429 manual = MANUAL_SELMLT; 931 manual = MANUAL_SELMLT;
430 manual_prompt(); 932 manual_prompt();
431 } 933 }
432 device_out(unit->mlt_pump.uuid, man_mlt_pump); 934 device_out(unit->mlt_pump.uuid, mlt_pump_state);
433 break; 935 break;
434 } 936 }
435 937
436 return 0; 938 return 0;
437 } 939 }
625 * During automation there will be a state file: 1127 * During automation there will be a state file:
626 * ~/.brewco/var/brewing.xml 1128 * ~/.brewco/var/brewing.xml
627 * If this file is present, there has been a crash. 1129 * If this file is present, there has been a crash.
628 */ 1130 */
629 brew = (brew_session *)malloc(sizeof(brew_session)); 1131 brew = (brew_session *)malloc(sizeof(brew_session));
630 if (rdsession(brew) == 0) { 1132 rc = rdsession(brew);
631 } else { 1133 syslog(LOG_NOTICE, "rdsession: rc=%d", rc);
632 /* 1134 if (debug)
633 * No active brew session, make that permanent. 1135 fprintf(stdout, "rdsession: rc=%d\n", rc);
634 */ 1136
1137 char *mypath = xstrcpy(etcpath);
1138 mypath = xstrcat(mypath, (char *)"brewing.xml");
1139 if (rc == 0) {
1140 if (debug)
1141 fprintf(stdout, "Active brew session found\n");
1142 } else if (rc == -1) {
635 free(brew); 1143 free(brew);
636 brew = NULL; 1144 brew = NULL;
637 } 1145 if (debug)
1146 fprintf(stdout, "No active brew session found\n");
1147 } else {
1148 unlink(mypath);
1149 free(brew);
1150 brew = NULL;
1151 if (debug)
1152 fprintf(stdout, "Error brew session found\n");
1153 }
1154 free(mypath);
1155 mypath = NULL;
638 1156
639 do { 1157 do {
640 if (my_shutdown) { 1158 if (my_shutdown) {
641 run = 0; 1159 run = 0;
642 unit->hlt_heater.value = 0; 1160 unit->hlt_heater.value = 0;
675 /* 1193 /*
676 * Initialize PID's 1194 * Initialize PID's
677 */ 1195 */
678 hltInput = hltSetpoint = mltInput = mltSetpoint = 20.0; 1196 hltInput = hltSetpoint = mltInput = mltSetpoint = 20.0;
679 hltOutput = mltOutput = 0; 1197 hltOutput = mltOutput = 0;
680 PID_init(unit->PID_hlt, &hltInput, &hltOutput, &hltSetpoint, unit->PID_hlt->dispKd, unit->PID_hlt->dispKi, unit->PID_hlt->dispKd, unit->PID_hlt->Direction); 1198 PID_init(unit->PID_hlt, &hltInput, &hltOutput, &hltSetpoint, unit->PID_hlt->dispKp, unit->PID_hlt->dispKi, unit->PID_hlt->dispKd, unit->PID_hlt->Direction);
681 PID_setOutputLimits(unit->PID_hlt, 0, 100); 1199 PID_setOutputLimits(unit->PID_hlt, 0, 100);
682 PID_setSampleTime(unit->PID_hlt, unit->PID_hlt->SampleTime); 1200 PID_setSampleTime(unit->PID_hlt, unit->PID_hlt->SampleTime);
683 PID_init(unit->PID_mlt, &mltInput, &mltOutput, &mltSetpoint, unit->PID_mlt->dispKd, unit->PID_mlt->dispKi, unit->PID_mlt->dispKd, unit->PID_mlt->Direction); 1201 PID_init(unit->PID_mlt, &mltInput, &mltOutput, &mltSetpoint, unit->PID_mlt->dispKp, unit->PID_mlt->dispKi, unit->PID_mlt->dispKd, unit->PID_mlt->Direction);
684 PID_setOutputLimits(unit->PID_mlt, 0, 100); 1202 PID_setOutputLimits(unit->PID_mlt, 0, 100);
685 PID_setSampleTime(unit->PID_mlt, unit->PID_mlt->SampleTime); 1203 PID_setSampleTime(unit->PID_mlt, unit->PID_mlt->SampleTime);
686 hlt_status(0); 1204 hlt_status(0);
687 mlt_status(0); 1205 mlt_status(0);
688 1206
691 do_init = FALSE; 1209 do_init = FALSE;
692 nowmillis = perctimer = millis(); 1210 nowmillis = perctimer = millis();
693 percslot = 0; 1211 percslot = 0;
694 percfase = PERC_INIT; 1212 percfase = PERC_INIT;
695 dosave = 0; 1213 dosave = 0;
1214
1215 if (brew) {
1216 /*
1217 * Restore session
1218 */
1219 if (debug)
1220 fprintf(stdout, "loop_init: restoring brew session\n");
1221 for (recipe = recipes; recipe; recipe = recipe->next) {
1222 if (strcmp(recipe->uuid, brew->uuid_recipe) == 0) {
1223 break;
1224 }
1225 }
1226 if (debug)
1227 fprintf(stdout, "loop_init: brewstep=%d mashstep=%d recipe=%s\n", brew->brewstep, brew->mashstep, recipe->code);
1228 }
696 } 1229 }
697 1230
698 /* run_pause code here */ 1231 /* run_pause code here */
699 1232
700 /* 1233 /*
732 } else { 1265 } else {
733 percfase = PERC_REST; 1266 percfase = PERC_REST;
734 device_out(unit->hlt_heater.uuid, 0); 1267 device_out(unit->hlt_heater.uuid, 0);
735 device_out(unit->mlt_heater.uuid, 0); 1268 device_out(unit->mlt_heater.uuid, 0);
736 } 1269 }
737 if (debug) 1270 // if (debug)
738 fprintf(stdout, " perslot=%d MLT=%d%% HLT=%d%% fase=%d\n", percslot, MLTp, HLTp, percfase); 1271 // fprintf(stdout, " perslot=%d MLT=%d%% HLT=%d%% fase=%d\n", percslot, MLTp, HLTp, percfase);
739 } else if (percfase == PERC_MLT) { 1272 } else if (percfase == PERC_MLT) {
740 if (percslot > MLTp) { 1273 if (percslot > MLTp) {
741 device_out(unit->mlt_heater.uuid, 0); 1274 device_out(unit->mlt_heater.uuid, 0);
742 if (HLTp) { 1275 if (HLTp) {
743 device_out(unit->hlt_heater.uuid, 1); 1276 device_out(unit->hlt_heater.uuid, 1);
771 seconds = 0; 1304 seconds = 0;
772 minutes++; 1305 minutes++;
773 dosave = 1; 1306 dosave = 1;
774 } 1307 }
775 1308
776 //fprintf(stdout, "%d seconds %d minutes %ld millis\n", seconds, minutes, millis());
777
778 rc = device_in(unit->hlt_sensor.uuid, &temp); 1309 rc = device_in(unit->hlt_sensor.uuid, &temp);
779 if (rc == DEVPRESENT_YES) { 1310 if (rc == DEVPRESENT_YES) {
780 hltInput = temp / 1000.0; 1311 hltInput = temp / 1000.0;
781 unit->hlt_sensor.state = 0; 1312 unit->hlt_sensor.state = 0;
782 } else if (rc == DEVPRESENT_ERROR) { 1313 } else if (rc == DEVPRESENT_ERROR) {
804 1335
805 if (brew) { 1336 if (brew) {
806 /* 1337 /*
807 * Automate mode 1338 * Automate mode
808 */ 1339 */
809 automatic_brew(unit, brew, recipe, dosave); 1340 automatic_brew(unit, brew, recipe, dosave, seconds);
810 dosave = 0; 1341 dosave = 0;
811 if (brew->brewstep == -1) { 1342 if (brew->brewstep == -1) {
812 /* 1343 /*
813 * Save session and move it 1344 * Save session and move it
814 */ 1345 */
855 } 1386 }
856 } else { 1387 } else {
857 /* 1388 /*
858 * Not running. 1389 * Not running.
859 */ 1390 */
860 tempstatus(hltInput, mltInput); 1391 tempstatus();
861 key = keycheck(); 1392 key = keycheck();
862 if (key == KEY_ENTER) { 1393 if (key == KEY_ENTER) {
863 setup(); 1394 setup();
864 prompt(101, NULL); /* " Brewco x.x.x " */ 1395 prompt(101, NULL); /* " Brewco x.x.x " */
865 prompt(401, NULL); /* "--- MAN AUTO SETUP" */ 1396 prompt(401, NULL); /* "--- MAN AUTO SETUP" */

mercurial