main/automation.c

changeset 77
66c77497d86d
parent 75
224851e81117
child 78
b58e0c9897e1
equal deleted inserted replaced
76:3ff381bfa469 77:66c77497d86d
102 102
103 switch (Main_Screen) { 103 switch (Main_Screen) {
104 case MAIN_AUTO_INIT1: 104 case MAIN_AUTO_INIT1:
105 log_msg(TAG, "Automation startup"); 105 log_msg(TAG, "Automation startup");
106 #ifdef CONFIG_TEMP_SENSORS_SIMULATOR 106 #ifdef CONFIG_TEMP_SENSORS_SIMULATOR
107 Fake_MLT = recipe.MashStep[0].Temperature - 10; 107 Fake_MLT = recipe.MashStep[0].Step_temp - 10;
108 Fake_HLT = recipe.SpargeTemp - 15; 108 Fake_HLT = recipe.SpargeTemp - 15;
109 if (xSemaphoreTake(xSemaphoreDS18B20, 10) == pdTRUE) { 109 if (xSemaphoreTake(xSemaphoreDS18B20, 10) == pdTRUE) {
110 ds18b20_state->mlt_temperature = ((int)(Fake_MLT * 16)) / 16.0; 110 ds18b20_state->mlt_temperature = ((int)(Fake_MLT * 16)) / 16.0;
111 ds18b20_state->hlt_temperature = ((int)(Fake_HLT * 16)) / 16.0; 111 ds18b20_state->hlt_temperature = ((int)(Fake_HLT * 16)) / 16.0;
112 xSemaphoreGive(xSemaphoreDS18B20); 112 xSemaphoreGive(xSemaphoreDS18B20);
113 } 113 }
114 #endif 114 #endif
115 for (int i = 0; i < 7; i++) { 115 if (recipe.Mashsteps > 1)
116 if (recipe.MashStep[i].Resttime) 116 LastMashStep = recipe.Mashsteps - 2;
117 LastMashStep = i; 117 else
118 } 118 LastMashStep = 0;
119 log_msg(TAG, "Last mash step %d", LastMashStep); 119 log_msg(TAG, "Last mash step %d", LastMashStep);
120 120
121 // Check for a crashed session. 121 // Check for a crashed session.
122 if (runtime.AutoModeStarted) { 122 if (runtime.AutoModeStarted) {
123 TopMessage((char *)"Brouwen hervatten?"); 123 TopMessage((char *)"Brouwen hervatten?");
176 runtime.StageResume = MAIN_AUTO_INIT1; 176 runtime.StageResume = MAIN_AUTO_INIT1;
177 runtime.StageTimeLeft = 0; 177 runtime.StageTimeLeft = 0;
178 runtime.HopAddition = 0; 178 runtime.HopAddition = 0;
179 runtime.Logfile[0] = '\0'; 179 runtime.Logfile[0] = '\0';
180 runtime.PumpCooling = false; 180 runtime.PumpCooling = false;
181 runtime.MashStep = 0;
182 runtime.MaltAdded = false;
181 write_runtime(); 183 write_runtime();
182 power_MLT = power_HLT = counts = 0; 184 power_MLT = power_HLT = counts = 0;
183 log_clean(); 185 log_clean();
184 vTaskDelay(250 / portTICK_PERIOD_MS); // Allow some time 186 vTaskDelay(250 / portTICK_PERIOD_MS); // Allow some time
185 break; 187 break;
198 MLT_info(71, 26, false); 200 MLT_info(71, 26, false);
199 HLT_info(71,150, false, false); 201 HLT_info(71,150, false, false);
200 } 202 }
201 break; 203 break;
202 204
203 case MAIN_AUTO_MASH_IN: 205 case MAIN_AUTO_MASH:
204 case MAIN_AUTO_MASH_1: 206 if (runtime.MashStep == 0) {
205 case MAIN_AUTO_MASH_2:
206 case MAIN_AUTO_MASH_3:
207 case MAIN_AUTO_MASH_4:
208 case MAIN_AUTO_MASH_5:
209 case MAIN_AUTO_MASH_6:
210 case MAIN_AUTO_MASH_OUT:
211 if (Main_Screen == MAIN_AUTO_MASH_IN) {
212 MinMash = 38.0; 207 MinMash = 38.0;
213 MaxMash = recipe.MashStep[1].Temperature + 10.0; 208 MaxMash = recipe.MashStep[0].Step_temp+ 10.0;
214 TimeBrewing = 0; 209 TimeBrewing = 0;
215 runtime.TimeBrewing = 0; 210 runtime.TimeBrewing = 0;
216 if (System_TimeOk) { 211 if (System_TimeOk) {
217 time(&now); 212 time(&now);
218 localtime_r(&now, &timeinfo); 213 localtime_r(&now, &timeinfo);
221 } else { 216 } else {
222 log_begin((time_t)0); 217 log_begin((time_t)0);
223 runtime.BrewStart = (time_t)0; 218 runtime.BrewStart = (time_t)0;
224 } 219 }
225 updateRuntime = true; 220 updateRuntime = true;
226 } else if (Main_Screen == MAIN_AUTO_MASH_OUT) { 221 } else if (runtime.MashStep == (recipe.Mashsteps - 1)) {
227 MinMash = 75.0; 222 MinMash = 75.0;
228 MaxMash = 80.0; 223 MaxMash = 80.0;
229 } else { 224 } else {
230 MinMash = recipe.MashStep[Main_Screen - MAIN_AUTO_MASH_IN - 1].Temperature; 225 MinMash = recipe.MashStep[runtime.MashStep - 1].Step_temp;
231 if (recipe.MashStep[Main_Screen - MAIN_AUTO_MASH_IN + 1].Resttime) { 226 MaxMash = recipe.MashStep[runtime.MashStep + 1].Step_temp;
232 MaxMash = recipe.MashStep[Main_Screen - MAIN_AUTO_MASH_IN + 1].Temperature; 227 if (MaxMash >= 75.0)
233 } else { 228 MaxMash = 74.75;
234 MaxMash = 75.0;
235 }
236 } 229 }
237 MashState = Sub_Screen = MASH_NONE; 230 MashState = Sub_Screen = MASH_NONE;
238 snprintf(msg, 63, "{\"main\":\"%d\",\"sub\":\"%d\",\"timer\":\"\"}", Main_Screen, Sub_Screen); 231 snprintf(msg, 63, "{\"main\":\"%d\",\"sub\":\"%d\",\"step\":\"%d\",\"timer\":\"\"}", Main_Screen, Sub_Screen, runtime.MashStep);
239 ws_server_send_text_clients((char *)"/ws", msg, strlen(msg)); 232 ws_server_send_text_clients((char *)"/ws", msg, strlen(msg));
233 ESP_LOGI(TAG, "%s", msg);
240 pumpTime = 0; 234 pumpTime = 0;
241 pumpRest = false; 235 pumpRest = false;
242 runtime.StageResume = Main_Screen; 236 runtime.StageResume = Main_Screen;
243 updateRuntime = true; 237 updateRuntime = true;
244 TopMessage((char *)"Maischen"); 238 TopMessage((char *)"Maischen");
444 TFT_setFont(DEFAULT_FONT, NULL); 438 TFT_setFont(DEFAULT_FONT, NULL);
445 ShowText(2,y,(char *)"Installatie", equipment.Name); 439 ShowText(2,y,(char *)"Installatie", equipment.Name);
446 y += 16; 440 y += 16;
447 ShowText(2,y,(char *)"Recept", recipe.Name); 441 ShowText(2,y,(char *)"Recept", recipe.Name);
448 y += 16; 442 y += 16;
449 ShowFloat(2, y, (char *)"Maisch in", (char *)" C", recipe.MashStep[0].Temperature, 2); 443 ShowFloat(2, y, (char *)"Maisch in", (char *)" C", recipe.MashStep[0].Infuse_temp, 3);
450 ShowFloat(162, y, (char *)"Spoelwater", (char *)" C", recipe.SpargeTemp, 2); 444 ShowFloat(162, y, (char *)"Spoelwater", (char *)" C", recipe.SpargeTemp, 2);
451 y += 16; 445 y += 16;
452 _fg = TFT_WHITE; 446 _fg = TFT_WHITE;
453 TFT_print((char *)"Maisch stap", 2, y); 447 TFT_print((char *)"Maisch stap", 2, y);
454 TFT_print((char *)"T", 200, y); 448 TFT_print((char *)"T", 200, y);
455 TFT_print((char *)"Temp.", 220, y); 449 TFT_print((char *)"Temp.", 220, y);
456 TFT_print((char *)"Rust", 280, y); 450 TFT_print((char *)"Rust", 280, y);
457 _fg = TFT_YELLOW; 451 _fg = TFT_YELLOW;
458 y += 16; 452 y += 16;
459 for (int i = 1; i < 8; i++) { 453 for (int i = 0; i < recipe.Mashsteps; i++) {
460 if (recipe.MashStep[i].Resttime) { 454 TFT_print(recipe.MashStep[i].Name, 2, y);
461 TFT_print(recipe.MashStep[i].Name, 2, y); 455 if (recipe.MashStep[i].Type < 3)
462 strcpy(tmp, mashTypes[recipe.MashStep[i].Type]); 456 strcpy(tmp, mashTypes[recipe.MashStep[i].Type]);
463 tmp[1] = '\0'; 457 else
464 TFT_print(tmp, 200, y); 458 tmp[0] = '?';
465 sprintf(tmp, "%.2f", recipe.MashStep[i].Temperature); 459 tmp[1] = '\0';
466 TFT_print(tmp, 220, y); 460 TFT_print(tmp, 200, y);
467 sprintf(tmp, "%2d m", recipe.MashStep[i].Resttime); 461 sprintf(tmp, "%.2f", recipe.MashStep[i].Step_temp);
468 TFT_print(tmp, 280, y); 462 TFT_print(tmp, 220, y);
469 y += 16; 463 sprintf(tmp, "%2d m", recipe.MashStep[i].Step_time);
470 } 464 TFT_print(tmp, 280, y);
465 y += 16;
471 } 466 }
472 ShowInteger(2, y, (char *)"Kooktijd", (char *)" min", recipe.BoilTime); 467 ShowInteger(2, y, (char *)"Kooktijd", (char *)" min", recipe.BoilTime);
473 ShowFloat(162, y, (char *)"Koel tot", (char *)" C", recipe.CoolTemp, 2); 468 ShowFloat(162, y, (char *)"Koel tot", (char *)" C", recipe.CoolTemp, 2);
474 if (recipe.BoilTime) { 469 if (recipe.BoilTime) {
475 y += 16; 470 y += 16;
587 * available Mash rest times, asume 0.5 degrees/minute 582 * available Mash rest times, asume 0.5 degrees/minute
588 * heat capacity during mash. 583 * heat capacity during mash.
589 */ 584 */
590 int AvailableTime = 0; 585 int AvailableTime = 0;
591 for (int i = 1; i < 6; i++) // Only normal Mash steps 586 for (int i = 1; i < 6; i++) // Only normal Mash steps
592 AvailableTime += recipe.MashStep[i].Resttime; 587 AvailableTime += recipe.MashStep[i].Step_time;
593 if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { 588 if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) {
594 driver_state->hlt_sp = recipe.SpargeTemp - ((AvailableTime / 2) + 2); 589 driver_state->hlt_sp = recipe.SpargeTemp - ((AvailableTime / 2) + 2);
595 log_msg(TAG, "HLT preheat set to %4.2f", driver_state->hlt_sp); 590 log_msg(TAG, "HLT preheat set to %4.2f", driver_state->hlt_sp);
596 xSemaphoreGive(xSemaphoreDriver); 591 xSemaphoreGive(xSemaphoreDriver);
597 } 592 }
604 Main_Screen = MAIN_AUTO_HEATUP; 599 Main_Screen = MAIN_AUTO_HEATUP;
605 break; 600 break;
606 601
607 case MAIN_AUTO_HEATUP: 602 case MAIN_AUTO_HEATUP:
608 if (! runtime.UseHLT) { // Skip if HLT is off 603 if (! runtime.UseHLT) { // Skip if HLT is off
609 Main_Screen = MAIN_AUTO_MASH_IN; 604 Main_Screen = MAIN_AUTO_MASH;
610 break; 605 break;
611 } 606 }
612 607
613 MLT_info(71, 26, true); 608 MLT_info(71, 26, true);
614 HLT_info(71,150, true, false); 609 HLT_info(71,150, true, false);
615 if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { 610 if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) {
616 if (driver_state->hlt_pv >= driver_state->hlt_sp) { 611 if (driver_state->hlt_pv >= driver_state->hlt_sp) {
617 Main_Screen = MAIN_AUTO_MASH_IN; 612 Main_Screen = MAIN_AUTO_MASH;
618 driver_state->hlt_sp = recipe.SpargeTemp; // Set final setpoint 613 driver_state->hlt_sp = recipe.SpargeTemp; // Set final setpoint
619 log_msg(TAG, "HLT preheat done"); 614 log_msg(TAG, "HLT preheat done");
620 } 615 }
621 xSemaphoreGive(xSemaphoreDriver); 616 xSemaphoreGive(xSemaphoreDriver);
622 } 617 }
623 break; 618 break;
624 619
625 case MAIN_AUTO_MASH_IN: 620 case MAIN_AUTO_MASH:
626 case MAIN_AUTO_MASH_1:
627 case MAIN_AUTO_MASH_2:
628 case MAIN_AUTO_MASH_3:
629 case MAIN_AUTO_MASH_4:
630 case MAIN_AUTO_MASH_5:
631 case MAIN_AUTO_MASH_6:
632 case MAIN_AUTO_MASH_OUT:
633 temp_MLT = 0.0; 621 temp_MLT = 0.0;
634 if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { 622 if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) {
635 temp_MLT = driver_state->mlt_pv; 623 temp_MLT = driver_state->mlt_pv;
636 624
637 if (MashState == MASH_ADD || MashState == MASH_REMOVE) { 625 if (MashState == MASH_ADD || MashState == MASH_REMOVE || MashState == MASH_INFUSE) {
638 driver_state->pump_run = 0; 626 driver_state->pump_run = 0;
639 } else if (MashState != MASH_NONE) { 627 } else if (MashState != MASH_NONE) {
640 if (Main_Screen == MAIN_AUTO_MASH_IN) { 628 if (runtime.MashStep == 0) {
641 driver_state->pump_run = (equipment.PumpPreMash && ! pumpRest) ? 1 : 0; 629 driver_state->pump_run = (equipment.PumpPreMash && ! pumpRest) ? 1 : 0;
642 } else if (Main_Screen == MAIN_AUTO_MASH_OUT) { 630 } else if (runtime.MashStep == (recipe.Mashsteps -1)) {
643 driver_state->pump_run = (equipment.PumpMashOut && ! pumpRest) ? 1 : 0; 631 driver_state->pump_run = (equipment.PumpMashOut && ! pumpRest) ? 1 : 0;
644 } else { 632 } else {
645 driver_state->pump_run = (equipment.PumpOnMash && ! pumpRest) ? 1 : 0; 633 driver_state->pump_run = (equipment.PumpOnMash && ! pumpRest) ? 1 : 0;
646 } 634 }
647 } 635 }
648 xSemaphoreGive(xSemaphoreDriver); 636 xSemaphoreGive(xSemaphoreDriver);
649 } 637 }
650 if (MashState == MASH_NONE) { 638 if (MashState == MASH_NONE) {
651 stageTemp = recipe.MashStep[Main_Screen - MAIN_AUTO_MASH_IN].Temperature; 639 if (runtime.MashStep == 0 && ! runtime.MaltAdded && recipe.MashStep[0].Infuse_temp) {
652 stageTime = recipe.MashStep[Main_Screen - MAIN_AUTO_MASH_IN].Resttime; 640 stageTemp = recipe.MashStep[0].Infuse_temp;
641 } else {
642 stageTemp = recipe.MashStep[runtime.MashStep].Step_temp;
643 }
644 stageTime = recipe.MashStep[runtime.MashStep].Step_time;
653 TempReached = false; 645 TempReached = false;
654 if (stageTime == 0) {
655 ESP_LOGI(TAG, "Mash step %d skipped", Main_Screen - MAIN_AUTO_MASH_IN);
656 Main_Screen++;
657 break;
658 }
659 if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { 646 if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) {
660 driver_state->mlt_sp = stageTemp; 647 driver_state->mlt_sp = stageTemp;
661 driver_state->mlt_mode = MLT_MODE_PID; 648 driver_state->mlt_mode = MLT_MODE_PID;
662 xSemaphoreGive(xSemaphoreDriver); 649 xSemaphoreGive(xSemaphoreDriver);
663 } 650 }
664 MashState = Sub_Screen = MASH_WAITTEMP; 651 MashState = Sub_Screen = MASH_WAITTEMP;
665 snprintf(msg, 255, "{\"main\":\"%d\",\"sub\":\"%d\",\"timer\":\"\"}", Main_Screen, Sub_Screen); 652 ESP_LOGI(TAG, "** Step %d Stage %d Malt %s", runtime.MashStep, MashState, runtime.MaltAdded ? (char *)"yes":(char *)"no");
653 snprintf(msg, 255, "{\"main\":\"%d\",\"sub\":\"%d\",\"step\":\"%d\",\"timer\":\"\"}", Main_Screen, Sub_Screen, runtime.MashStep);
666 ws_server_send_text_clients((char *)"/ws", msg, strlen(msg)); 654 ws_server_send_text_clients((char *)"/ws", msg, strlen(msg));
667 log_msg(TAG, "Mash step %d type: %s time: %d sp: %4.2f sv: %4.3f", 655 log_msg(TAG, "Mash step %d type: %s time: %d sp: %6.4f sv: %6.4f",
668 Main_Screen - MAIN_AUTO_MASH_IN, mashTypes[recipe.MashStep[Main_Screen - MAIN_AUTO_MASH_IN].Type], 656 runtime.MashStep, mashTypes[recipe.MashStep[runtime.MashStep].Type],
669 stageTime, stageTemp, temp_MLT); 657 stageTime, stageTemp, temp_MLT);
670 658
671 if (Main_Screen > MAIN_AUTO_MASH_IN) { 659 if (runtime.MashStep) {
672 // Do not annotate before the log is open. 660 // Do not annotate before the log is open.
673 if (Main_Screen == MAIN_AUTO_MASH_OUT) { 661 if (runtime.MashStep == (recipe.Mashsteps -1)) {
674 log_annotation(ANNOTATION_STAGE, (char *)"Uitmaischen"); 662 log_annotation(ANNOTATION_STAGE, (char *)"Uitmaischen");
675 } else { 663 } else {
676 sprintf(logline, "Maisch: %d", Main_Screen - MAIN_AUTO_MASH_IN); 664 sprintf(logline, "Maisch: %d", runtime.MashStep);
677 log_annotation(ANNOTATION_STAGE, logline); 665 log_annotation(ANNOTATION_STAGE, logline);
678 } 666 }
679 } 667 }
680 668
681 if (strlen(recipe.MashStep[Main_Screen - MAIN_AUTO_MASH_IN].Name)) { 669 if (! runtime.MaltAdded) {
682 TopMessage(recipe.MashStep[Main_Screen - MAIN_AUTO_MASH_IN].Name); 670 TopMessage((char *)"Opwarmen MLT");
671 } else if (strlen(recipe.MashStep[runtime.MashStep].Name)) {
672 TopMessage(recipe.MashStep[runtime.MashStep].Name);
683 } else { 673 } else {
684 sprintf(temp_buf, "Maisch stap #%d", Main_Screen - MAIN_AUTO_MASH_IN); 674 sprintf(temp_buf, "Maisch stap #%d", runtime.MashStep);
685 TopMessage(temp_buf); 675 TopMessage(temp_buf);
686 } 676 }
687 if ((Main_Screen > MAIN_AUTO_MASH_IN) && (Main_Screen < MAIN_AUTO_MASH_OUT) && 677 if (runtime.MashStep && (runtime.MashStep < recipe.Mashsteps) && (recipe.MashStep[runtime.MashStep].Type != MASHTYPE_TEMPERATURE)) {
688 (recipe.MashStep[Main_Screen - MAIN_AUTO_MASH_IN].Type == MASHTYPE_INFUSION)) { 678 TFT_fillRect(0, 120, 320, 50, TFT_BLACK);
679 Buttons_Clear();
689 Buttons_Add( 5,120, 60, 40, (char *)"Halt", 0); 680 Buttons_Add( 5,120, 60, 40, (char *)"Halt", 0);
690 Buttons[0].dark = true; 681 Buttons[0].dark = true;
691 Buttons_Add(255,120, 60, 40, (char *)"Ok", 1); 682 Buttons_Add(255,120, 60, 40, (char *)"Ok", 1);
692 Buttons_Show(); 683 Buttons_Show();
693 _fg = TFT_WHITE; 684 _fg = TFT_WHITE;
694 _bg = TFT_BLACK; 685 _bg = TFT_BLACK;
695 TFT_setFont(DEJAVU18_FONT, NULL); 686 TFT_setFont(DEJAVU18_FONT, NULL);
696 sprintf(temp_buf, "Infuse %.1f L/%.1f C", recipe.MashStep[Main_Screen - MAIN_AUTO_MASH_IN].Infusion_amount, 687 if (recipe.MashStep[runtime.MashStep].Type == MASHTYPE_INFUSION) {
697 recipe.MashStep[Main_Screen - MAIN_AUTO_MASH_IN].Infusion_temp); 688 sprintf(temp_buf, "Infusie %.1f L/%.1f C", recipe.MashStep[runtime.MashStep].Infuse_amount,
689 recipe.MashStep[runtime.MashStep].Infuse_temp);
690 MashState = Sub_Screen = MASH_INFUSE;
691 log_msg(TAG, "Mash infusion prompt");
692 } else if (recipe.MashStep[runtime.MashStep].Type == MASHTYPE_DECOCTION) {
693 sprintf(temp_buf, "Decoctie %.1f Liter", recipe.MashStep[runtime.MashStep].Infuse_amount);
694 MashState = Sub_Screen = MASH_DECOCT;
695 log_msg(TAG, "Mash decoction prompt");
696 }
698 TFT_print(temp_buf, CENTER, 135); 697 TFT_print(temp_buf, CENTER, 135);
699 SoundPlay(SOUND_Prompt); 698 SoundPlay(SOUND_Prompt);
700 MashState = Sub_Screen = MASH_INFUSE; 699 snprintf(msg, 255, "{\"main\":\"%d\",\"sub\":\"%d\",\"step\":\"%d\",\"timer\":\"%s\"}",
701 snprintf(msg, 255, "{\"main\":\"%d\",\"sub\":\"%d\",\"timer\":\"%s\"}", Main_Screen, Sub_Screen, temp_buf); 700 Main_Screen, Sub_Screen, runtime.MashStep, temp_buf);
702 ws_server_send_text_clients((char *)"/ws", msg, strlen(msg)); 701 ws_server_send_text_clients((char *)"/ws", msg, strlen(msg));
703 if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { 702 if (recipe.MashStep[runtime.MashStep].Type == MASHTYPE_INFUSION) {
704 // No heating during the infusion. 703 if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) {
705 driver_state->mlt_sp = stageTemp; 704 // No heating during the infusion.
706 driver_state->mlt_mode = MLT_MODE_OFF; 705 driver_state->mlt_sp = stageTemp;
707 xSemaphoreGive(xSemaphoreDriver); 706 driver_state->mlt_mode = MLT_MODE_OFF;
707 xSemaphoreGive(xSemaphoreDriver);
708 }
708 } 709 }
709 log_msg(TAG, "Mash infusion prompt");
710 } else { 710 } else {
711 Buttons_Add( 5, 30, 60, 40, (char *)"+sp", 0); 711 Buttons_Add( 5, 30, 60, 40, (char *)"+sp", 0);
712 Buttons_Add(255, 30, 60, 40, (char *)"-sp", 1); 712 Buttons_Add(255, 30, 60, 40, (char *)"-sp", 1);
713 Buttons_Show(); 713 Buttons_Show();
714 } 714 }
720 } 720 }
721 if ((temp_MLT >= stageTemp) && (Steady > 10)) { 721 if ((temp_MLT >= stageTemp) && (Steady > 10)) {
722 SoundPlay(SOUND_TempReached); 722 SoundPlay(SOUND_TempReached);
723 TempReached = true; 723 TempReached = true;
724 MashState = Sub_Screen = MASH_REST; 724 MashState = Sub_Screen = MASH_REST;
725 snprintf(msg, 63, "{\"main\":\"%d\",\"sub\":\"%d\",\"timer\":\"\"}", Main_Screen, Sub_Screen); 725 ESP_LOGI(TAG, "** Step %d Stage %d Malt %s", runtime.MashStep, MashState, runtime.MaltAdded ? (char *)"yes":(char *)"no");
726 snprintf(msg, 63, "{\"main\":\"%d\",\"sub\":\"%d\",\"step\":\"%d\",\"timer\":\"\"}", Main_Screen, Sub_Screen, runtime.MashStep);
726 ws_server_send_text_clients((char *)"/ws", msg, strlen(msg)); 727 ws_server_send_text_clients((char *)"/ws", msg, strlen(msg));
727 if (Main_Screen == MAIN_AUTO_MASH_IN) { 728 if (! runtime.MaltAdded && runtime.MashStep == 0) {
728 TimerSet(0); 729 TimerSet(0);
729 } else { 730 } else {
730 if (Resume && (runtime.StageTimeLeft < stageTime)) 731 if (Resume && (runtime.StageTimeLeft < stageTime))
731 TimerSet(runtime.StageTimeLeft * 60); 732 TimerSet(runtime.StageTimeLeft * 60);
732 else 733 else
733 TimerSet(stageTime * 60); 734 TimerSet(stageTime * 60);
734 } 735 }
735 Resume = false; 736 Resume = false;
736 runtime.StageTimeLeft = TimeLeft / 60; 737 runtime.StageTimeLeft = TimeLeft / 60;
737 updateRuntime = true; 738 updateRuntime = true;
738 log_msg(TAG, "Mash step %d temperature reached, rest %d minutes", Main_Screen - MAIN_AUTO_MASH_IN, TimeLeft / 60); 739 log_msg(TAG, "Mash step %d temperature reached, rest %d minutes", runtime.MashStep, TimeLeft / 60);
739 Buttons_Clear(); 740 Buttons_Clear();
740 Buttons_Add( 0, 120, 60, 40, (char *)"+1m", 0); 741 Buttons_Add( 0, 120, 60, 40, (char *)"+1m", 0);
741 Buttons_Add(260, 120, 60, 40, (char *)"-1m", 1); 742 Buttons_Add(260, 120, 60, 40, (char *)"-1m", 1);
742 Buttons_Show(); 743 Buttons_Show();
743 } 744 }
758 759
759 } else if (MashState == MASH_REST) { 760 } else if (MashState == MASH_REST) {
760 /* 761 /*
761 * Mash step rest time and pump control 762 * Mash step rest time and pump control
762 */ 763 */
763 if (((Main_Screen == MAIN_AUTO_MASH_OUT) && equipment.PumpMashOut) || 764 if (((runtime.MashStep == (recipe.Mashsteps -1)) && equipment.PumpMashOut) ||
764 ((Main_Screen != MAIN_AUTO_MASH_OUT) && equipment.PumpOnMash)) { 765 ((runtime.MashStep < recipe.Mashsteps) && equipment.PumpOnMash)) {
765 float DeltaTemp = equipment.PumpRest * stageTemp / 120; // Maximum temperature drop before heating again. 766 float DeltaTemp = equipment.PumpRest * stageTemp / 120; // Maximum temperature drop before heating again.
766 if (pumpTime >= (equipment.PumpCycle + equipment.PumpRest) || ((stageTemp - temp_MLT) > DeltaTemp)) { 767 if (pumpTime >= (equipment.PumpCycle + equipment.PumpRest) || ((stageTemp - temp_MLT) > DeltaTemp)) {
767 pumpTime = 0; 768 pumpTime = 0;
768 } 769 }
769 if (pumpTime >= equipment.PumpCycle) { 770 if (pumpTime >= equipment.PumpCycle) {
793 default: break; 794 default: break;
794 } 795 }
795 } 796 }
796 797
797 if (TimeLeft == 0) { 798 if (TimeLeft == 0) {
799 ESP_LOGI(TAG, "** Step %d Stage %d Malt %s", runtime.MashStep, MashState, runtime.MaltAdded ? (char *)"yes":(char *)"no");
798 runtime.StageTimeLeft = 0; 800 runtime.StageTimeLeft = 0;
799 updateRuntime = true; 801 updateRuntime = true;
800 if ((Main_Screen == MAIN_AUTO_MASH_IN) && config.AskAdd) { 802 if (runtime.MashStep == 0 && ! runtime.MaltAdded && config.AskAdd) {
801 /* 803 /*
802 * Add Mash prompt. 804 * Add Mash prompt.
803 */ 805 */
806 stageTemp = recipe.MashStep[runtime.MashStep].Step_temp; // Set normal step temperature
807 if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) {
808 driver_state->mlt_sp = stageTemp;
809 xSemaphoreGive(xSemaphoreDriver);
810 }
804 log_annotation(ANNOTATION_EVENT, (char *)"Mout storten"); 811 log_annotation(ANNOTATION_EVENT, (char *)"Mout storten");
812 TFT_fillRect(0, 120, 320, 50, TFT_BLACK);
805 Buttons_Clear(); 813 Buttons_Clear();
806 Buttons_Add( 5,120, 60, 40, (char *)"Halt", 0); 814 Buttons_Add( 5,120, 60, 40, (char *)"Halt", 0);
807 Buttons[0].dark = true; 815 Buttons[0].dark = true;
808 Buttons_Add(255,120, 60, 40, (char *)"Ok", 1); 816 Buttons_Add(255,120, 60, 40, (char *)"Ok", 1);
809 Buttons_Show(); 817 Buttons_Show();
811 _bg = TFT_BLACK; 819 _bg = TFT_BLACK;
812 TFT_setFont(DEJAVU24_FONT, NULL); 820 TFT_setFont(DEJAVU24_FONT, NULL);
813 TFT_print((char *)"Mout storten?", CENTER, 135); 821 TFT_print((char *)"Mout storten?", CENTER, 135);
814 SoundPlay(SOUND_Prompt); 822 SoundPlay(SOUND_Prompt);
815 MashState = Sub_Screen = MASH_ADD; 823 MashState = Sub_Screen = MASH_ADD;
816 snprintf(msg, 63, "{\"main\":\"%d\",\"sub\":\"%d\",\"timer\":\"Mout storten?\"}", Main_Screen, Sub_Screen); 824 snprintf(msg, 63, "{\"main\":\"%d\",\"sub\":\"%d\",\"step\":\"%d\",\"timer\":\"Mout storten?\"}",
825 Main_Screen, Sub_Screen, runtime.MashStep);
817 ws_server_send_text_clients((char *)"/ws", msg, strlen(msg)); 826 ws_server_send_text_clients((char *)"/ws", msg, strlen(msg));
818 log_msg(TAG, "Mash add prompt"); 827 log_msg(TAG, "Mash add prompt");
819 break; 828 break;
820 } 829 }
821 if (((Main_Screen - MAIN_AUTO_MASH_IN) == LastMashStep) && config.AskIodine) { 830 if ((runtime.MashStep == LastMashStep) && config.AskIodine) {
822 /* 831 /*
823 * Iodone test prompt. 832 * Iodone test prompt.
824 */ 833 */
825 log_annotation(ANNOTATION_EVENT, (char *)"Jodium test"); 834 log_annotation(ANNOTATION_EVENT, (char *)"Jodium test");
826 TFT_fillRect(0, 120, 320, 50, TFT_BLACK); 835 TFT_fillRect(0, 120, 320, 50, TFT_BLACK);
835 TFT_print((char *)"Jodium test?", CENTER, 127); 844 TFT_print((char *)"Jodium test?", CENTER, 127);
836 SoundPlay(SOUND_Prompt); 845 SoundPlay(SOUND_Prompt);
837 beeped = false; 846 beeped = false;
838 TimerSet(config.IodineTime * 60); 847 TimerSet(config.IodineTime * 60);
839 MashState = Sub_Screen = MASH_IODINE; 848 MashState = Sub_Screen = MASH_IODINE;
840 snprintf(msg, 63, "{\"main\":\"%d\",\"sub\":\"%d\",\"timer\":\"Jodium test?\"}", Main_Screen, Sub_Screen); 849 ESP_LOGI(TAG, "** Step %d Stage %d Malt %s", runtime.MashStep, MashState, runtime.MaltAdded ? (char *)"yes":(char *)"no");
850 snprintf(msg, 63, "{\"main\":\"%d\",\"sub\":\"%d\",\"step\":\"%d\",\"timer\":\"Jodium test?\"}",
851 Main_Screen, Sub_Screen, runtime.MashStep);
841 ws_server_send_text_clients((char *)"/ws", msg, strlen(msg)); 852 ws_server_send_text_clients((char *)"/ws", msg, strlen(msg));
842 log_msg(TAG, "Mash iodine test prompt"); 853 log_msg(TAG, "Mash iodine test prompt");
843 break; 854 break;
844 } 855 }
845 if ((Main_Screen == MAIN_AUTO_MASH_OUT) && config.AskRemove) { 856 if ((runtime.MashStep == (recipe.Mashsteps - 1)) && config.AskRemove) {
846 /* 857 /*
847 * Mash remove prompt. 858 * Mash remove prompt.
848 */ 859 */
849 log_annotation(ANNOTATION_EVENT, (char *)"Mout verwijderen"); 860 log_annotation(ANNOTATION_EVENT, (char *)"Mout verwijderen");
850 TFT_fillRect(0, 120, 320, 50, TFT_BLACK); 861 TFT_fillRect(0, 120, 320, 50, TFT_BLACK);
857 _bg = TFT_BLACK; 868 _bg = TFT_BLACK;
858 TFT_setFont(DEJAVU18_FONT, NULL); 869 TFT_setFont(DEJAVU18_FONT, NULL);
859 TFT_print((char *)"Mout verwijderen?", CENTER, 135); 870 TFT_print((char *)"Mout verwijderen?", CENTER, 135);
860 SoundPlay(SOUND_Prompt); 871 SoundPlay(SOUND_Prompt);
861 MashState = Sub_Screen = MASH_REMOVE; 872 MashState = Sub_Screen = MASH_REMOVE;
862 snprintf(msg, 63, "{\"main\":\"%d\",\"sub\":\"%d\",\"timer\":\"Mout verwijderen?\"}", Main_Screen, Sub_Screen); 873 ESP_LOGI(TAG, "** Step %d Stage %d Malt %s", runtime.MashStep, MashState, runtime.MaltAdded ? (char *)"yes":(char *)"no");
874 snprintf(msg, 127, "{\"main\":\"%d\",\"sub\":\"%d\",\"step\":\"%d\",\"timer\":\"Mout verwijderen?\"}",
875 Main_Screen, Sub_Screen, runtime.MashStep);
863 ws_server_send_text_clients((char *)"/ws", msg, strlen(msg)); 876 ws_server_send_text_clients((char *)"/ws", msg, strlen(msg));
864 log_msg(TAG, "Mash remove prompt"); 877 log_msg(TAG, "Mash remove prompt");
865 break; 878 break;
866 } 879 }
867 if (Main_Screen != MAIN_AUTO_ABORT) 880 if (Main_Screen != MAIN_AUTO_ABORT) {
868 Main_Screen++; 881 runtime.MashStep++;
882 MashState = Sub_Screen = MASH_NONE;
883 if (runtime.MashStep == recipe.Mashsteps)
884 Main_Screen = MAIN_AUTO_TOBOIL;
885 updateRuntime = true;
886 }
869 TempReached = false; 887 TempReached = false;
870 } else { 888 } else {
871 TimerShow(TimeLeft, 65, 122); 889 TimerShow(TimeLeft, 65, 122);
872 if (NewMinute) { 890 if (NewMinute) {
873 runtime.StageTimeLeft = TimeLeft / 60; 891 runtime.StageTimeLeft = TimeLeft / 60;
886 } 904 }
887 } 905 }
888 switch (Buttons_Scan()) { 906 switch (Buttons_Scan()) {
889 case 0: Main_Screen = MAIN_AUTO_ABORT; 907 case 0: Main_Screen = MAIN_AUTO_ABORT;
890 break; 908 break;
891 case 1: Main_Screen++; 909 case 1: //Main_Screen++;
910 if (MashState == MASH_ADD) {
911 MashState = Sub_Screen = MASH_NONE;
912 runtime.MaltAdded = true;
913 updateRuntime = true;
914 } else if (MashState == MASH_IODINE) {
915 MashState = Sub_Screen = MASH_NONE;
916 runtime.MashStep++;
917 if (runtime.MashStep == recipe.Mashsteps)
918 Main_Screen = MAIN_AUTO_TOBOIL;
919 updateRuntime = true;
920 } else if (MashState == MASH_REMOVE) {
921 Main_Screen = MAIN_AUTO_TOBOIL;
922 }
923 TFT_fillRect(0, 120, 320, 50, TFT_BLACK);
924 Buttons_Clear();
925 ESP_LOGI(TAG, "** Step %d Stage %d Malt %s", runtime.MashStep, MashState, runtime.MaltAdded ? (char *)"yes":(char *)"no");
892 break; 926 break;
893 default: break; 927 default: break;
894 } 928 }
895 if (MashState == MASH_IODINE && TimeLeft == 0) { 929 if (MashState == MASH_IODINE && TimeLeft == 0) {
896 Main_Screen++; 930 MashState = Sub_Screen = MASH_NONE;
897 } 931 runtime.MashStep++;
898 } else if (MashState == MASH_INFUSE) { 932 if (runtime.MashStep == recipe.Mashsteps)
933 Main_Screen = MAIN_AUTO_TOBOIL;
934 updateRuntime = true;
935 TFT_fillRect(0, 120, 320, 50, TFT_BLACK);
936 Buttons_Clear();
937 }
938 } else if (MashState == MASH_INFUSE || MashState == MASH_DECOCT) {
899 switch (Buttons_Scan()) { 939 switch (Buttons_Scan()) {
900 case 0: Main_Screen = MAIN_AUTO_ABORT; 940 case 0: Main_Screen = MAIN_AUTO_ABORT;
901 break; 941 break;
902 case 1: MashState = Sub_Screen = MASH_WAITTEMP; 942 case 1:
903 snprintf(msg, 63, "{\"main\":\"%d\",\"sub\":\"%d\",\"timer\":\"\"}", Main_Screen, Sub_Screen); 943 #ifdef CONFIG_TEMP_SENSORS_SIMULATOR
904 ws_server_send_text_clients((char *)"/ws", msg, strlen(msg)); 944 if (MashState == MASH_DECOCT) {
945 Fake_MLT = recipe.MashStep[runtime.MashStep].Step_temp - 0.72; // Fake the decoction amt.
946 if (xSemaphoreTake(xSemaphoreDS18B20, 10) == pdTRUE) {
947 ds18b20_state->mlt_temperature = ((int)(Fake_MLT * 16)) / 16.0;
948 xSemaphoreGive(xSemaphoreDS18B20);
949 }
950 }
951 #endif
905 if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { 952 if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) {
906 // Start PID again. 953 // Start PID again.
907 driver_state->mlt_sp = stageTemp; 954 driver_state->mlt_sp = stageTemp;
908 driver_state->mlt_mode = MLT_MODE_PID; 955 driver_state->mlt_mode = MLT_MODE_PID;
909 xSemaphoreGive(xSemaphoreDriver); 956 xSemaphoreGive(xSemaphoreDriver);
910 } 957 }
958 TFT_fillRect(0, 120, 320, 50, TFT_BLACK);
911 Buttons_Clear(); 959 Buttons_Clear();
912 Buttons_Add( 5, 30, 60, 40, (char *)"+sp", 0); 960 Buttons_Add( 5, 30, 60, 40, (char *)"+sp", 0);
913 Buttons_Add(255, 30, 60, 40, (char *)"-sp", 1); 961 Buttons_Add(255, 30, 60, 40, (char *)"-sp", 1);
914 Buttons_Show(); 962 Buttons_Show();
915 TFT_fillRect(65, 120, 190, 40, TFT_BLACK); 963 TFT_fillRect(65, 120, 190, 40, TFT_BLACK);
916 log_annotation(ANNOTATION_EVENT, (char *)"Eind infusie"); 964 if (MashState == MASH_INFUSE) {
965 log_msg(TAG, "Eind infusie");
966 log_annotation(ANNOTATION_EVENT, (char *)"Eind infusie");
967 } else {
968 log_msg(TAG, "Eind decoctie");
969 log_annotation(ANNOTATION_EVENT, (char *)"Eind decoctie");
970 }
971 MashState = Sub_Screen = MASH_WAITTEMP;
972 snprintf(msg, 63, "{\"main\":\"%d\",\"sub\":\"%d\",\"step\":\"%d\",\"timer\":\"\"}",
973 Main_Screen, Sub_Screen, runtime.MashStep);
974 ws_server_send_text_clients((char *)"/ws", msg, strlen(msg));
917 break; 975 break;
918 default: break; 976 default: break;
919 } 977 }
920 } /* MashState */ 978 } /* MashState */
921 MLT_info(71, 26, true); 979 MLT_info(71, 26, true);

mercurial