Implemented infusion mash.

Fri, 26 Oct 2018 21:23:46 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Fri, 26 Oct 2018 21:23:46 +0200
changeset 19
49e2960d4642
parent 18
5d4a40fe9967
child 20
3fd5e0fc075f

Implemented infusion mash.

README.md file | annotate | diff | comparison | revisions
main/automation.c file | annotate | diff | comparison | revisions
main/buttons.c file | annotate | diff | comparison | revisions
main/buttons.h file | annotate | diff | comparison | revisions
main/config.c file | annotate | diff | comparison | revisions
main/config.h file | annotate | diff | comparison | revisions
main/files.h file | annotate | diff | comparison | revisions
main/recipes.c file | annotate | diff | comparison | revisions
--- a/README.md	Fri Oct 26 13:29:14 2018 +0200
+++ b/README.md	Fri Oct 26 21:23:46 2018 +0200
@@ -64,5 +64,4 @@
 TODO:
       - Praktijktest.
       - Nosleep js code toevoegen.
-      - Bij infusie (en decoctie?) maisch stappen een prompt.
 
--- a/main/automation.c	Fri Oct 26 13:29:14 2018 +0200
+++ b/main/automation.c	Fri Oct 26 21:23:46 2018 +0200
@@ -53,6 +53,8 @@
 extern float                    Fake_HLT;
 #endif
 
+extern const char 		*mashTypes[];
+
 static const char		*TAG = "automation";
 
 
@@ -393,21 +395,26 @@
 		y += 16;
 		_fg = TFT_WHITE;
 		TFT_print("Maisch stap", 2, y);
-		TFT_print("Temp.", 200, y);
-		TFT_print("Rust", 260, y);
+		TFT_print("T", 200, y);
+		TFT_print("Temp.", 220, y);
+		TFT_print("Rust", 280, y);
 		_fg = TFT_YELLOW;
 		y += 16;
 		for (int i = 1; i < 8; i++) {
 		    if (recipe.MashStep[i].Resttime) {
 			TFT_print(recipe.MashStep[i].Name, 2, y);
-			sprintf(tmp, "%.2f", recipe.MashStep[i].Temperature);
+			strcpy(tmp, mashTypes[recipe.MashStep[i].Type]);
+			tmp[1] = '\0';
 			TFT_print(tmp, 200, y);
-			sprintf(tmp, "%2d min", recipe.MashStep[i].Resttime);
-			TFT_print(tmp, 260, y);
+			sprintf(tmp, "%.2f", recipe.MashStep[i].Temperature);
+			TFT_print(tmp, 220, y);
+			sprintf(tmp, "%2d m", recipe.MashStep[i].Resttime);
+			TFT_print(tmp, 280, y);
 			y += 16;
 		    }
 		}
-		ShowInteger(2, y, "Kooktijd", " miniuten", recipe.BoilTime);
+		ShowInteger(2, y, "Kooktijd", " min", recipe.BoilTime);
+		ShowFloat(162, y, "Koel tot", " C", recipe.CoolTemp, 2);
 		y += 16;
 		if (recipe.Additions) {
 		    _fg = TFT_YELLOW;
@@ -427,7 +434,6 @@
 		    TFT_print("Geen hop toevoegingen.", 2, y);
 		}
 		y += 16;
-		ShowFloat(2, y, "Koelen tot", " C", recipe.CoolTemp, 2);
 		if (recipe.Whirlpool9) {
 		    ShowInteger(2, y, "Whirlpool 88..100 graden", " minuten", recipe.Whirlpool9);
 		    y += 16;
@@ -593,8 +599,9 @@
                         xSemaphoreGive(xSemaphoreDriver);
                     }
                     MashState = MASH_WAITTEMP;
-                    ESP_LOGI(TAG, "Mash step %d time: %d temp: %4.1f  min: %4.1f max: %4.1f",
-                                    Main_Screen - MAIN_AUTO_MASH_IN, stageTime, stageTemp, MinMash, MaxMash);
+                    ESP_LOGI(TAG, "Mash step %d type: %s time: %d temp: %4.1f  min: %4.1f max: %4.1f",
+				    Main_Screen - MAIN_AUTO_MASH_IN, mashTypes[recipe.MashStep[Main_Screen - MAIN_AUTO_MASH_IN].Type],
+                                    stageTime, stageTemp, MinMash, MaxMash);
 
 		    if (Main_Screen > MAIN_AUTO_MASH_IN) {
 			// Do not annotate before the log is open.
@@ -612,9 +619,32 @@
                         sprintf(temp_buf, "Maisch stap #%d", Main_Screen - MAIN_AUTO_MASH_IN);
                         TopMessage(temp_buf);
                     }
-                    Buttons_Add(  5,  30, 60, 40, "+sp",   0);
-                    Buttons_Add(255,  30, 60, 40, "-sp",   1);
-                    Buttons_Show();
+		    if ((Main_Screen > MAIN_AUTO_MASH_IN) && (Main_Screen < MAIN_AUTO_MASH_OUT) && 
+			 (recipe.MashStep[Main_Screen - MAIN_AUTO_MASH_IN].Type == MASHTYPE_INFUSION)) {
+			Buttons_Add(  5,120, 60, 40, "Halt", 0);
+			Buttons[0].dark = true;
+			Buttons_Add(255,120, 60, 40, "Ok",   1);
+			Buttons_Show();
+			_fg = TFT_WHITE;
+			_bg = TFT_BLACK;
+			TFT_setFont(DEJAVU18_FONT, NULL);
+			sprintf(temp_buf, "Infuse %.1f L/%.1f C", recipe.MashStep[Main_Screen - MAIN_AUTO_MASH_IN].Infusion_amount,
+					recipe.MashStep[Main_Screen - MAIN_AUTO_MASH_IN].Infusion_temp);
+			TFT_print(temp_buf, CENTER, 135);
+			SoundPlay(SOUND_Prompt);
+			MashState = MASH_INFUSE;
+			if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) {
+			    // No heating during the infusion.
+			    driver_state->mlt_sp = stageTemp;
+			    driver_state->mlt_mode = MLT_MODE_OFF;
+			    xSemaphoreGive(xSemaphoreDriver);
+			}
+			ESP_LOGI(TAG, "Mash infusion prompt");
+		    } else {
+			Buttons_Add(  5,  30, 60, 40, "+sp",   0);
+			Buttons_Add(255,  30, 60, 40, "-sp",   1);
+                    	Buttons_Show();
+		    }
 
                 } else if (MashState == MASH_WAITTEMP) {
                     pumpRest = false;
@@ -817,6 +847,25 @@
 				    break;
 			default:    break;
 		    }
+		} else if (MashState == MASH_INFUSE) {
+		    switch (Buttons_Scan()) {
+			case 0:     Main_Screen = MAIN_AUTO_ABORT;
+				    break;
+			case 1:	    MashState = MASH_WAITTEMP;
+				    if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) {
+					// Start PID again.
+					driver_state->mlt_sp = stageTemp;
+					driver_state->mlt_mode = MLT_MODE_PID;
+					xSemaphoreGive(xSemaphoreDriver);
+				    }
+				    Buttons_Clear();
+			    	    Buttons_Add(  5,  30, 60, 40, "+sp",   0);
+				    Buttons_Add(255,  30, 60, 40, "-sp",   1);
+				    Buttons_Show();
+				    TFT_fillRect(65, 120, 190, 40, TFT_BLACK);
+				    break;
+			default:    break;
+		    }
                 } /* MashState */
                 MLT_info(71, 26, true);
                 if (_UseHLT) {
--- a/main/buttons.c	Fri Oct 26 13:29:14 2018 +0200
+++ b/main/buttons.c	Fri Oct 26 21:23:46 2018 +0200
@@ -13,6 +13,9 @@
 extern uint16_t			VNC_pointer_x;		///< Mouse coordinate X
 extern uint16_t			VNC_pointer_y;		///< Mouse coordinate Y
 
+const char 			*mashTypes[] = { "Infusion", "Temperature", "Decoction" };
+const char			*SSR2Types[] = { "Uit", "HLT of MLT", "HLT en MLT", "Idle" };
+
 
 #define	EDIT_TYPE_TEXT		0			///< Editor type is text
 #define	EDIT_TYPE_INT		1			///< Editor type is integer
@@ -55,7 +58,7 @@
     Buttons[order].w = w;
     Buttons[order].h = h;
     strncpy(Buttons[order].text, txt, 11);
-    Buttons[order].dark = Buttons[order].small = false;
+    Buttons[order].dark = Buttons[order].small = Buttons[order].lock = false;
 }
 
 
@@ -610,23 +613,9 @@
 {
     _fg = TFT_LIGHTGREY;
     TFT_print("SSR2 ", x, y);
-   _fg = TFT_YELLOW;
-   TFT_clearStringRect(TFT_X, TFT_Y, "HLT en MLT");
-
-   switch (val) {
-	case SSR2_OFF:		TFT_print("Uit", LASTX, LASTY);
-				break;
-	case SSR2_HLT_SHARE:	TFT_print("HLT of MLT", LASTX, LASTY);
-				break;
-
-	case SSR2_HLT_IND:	TFT_print("HLT en MLT", LASTX, LASTY);
-				break;
-
-	case SSR2_ON_IDLE:	TFT_print("Idle", LASTX, LASTY);
-				break;
-
-	default:		TFT_print("N/A", LASTX, LASTY);
-   }
+    _fg = TFT_YELLOW;
+    TFT_clearStringRect(TFT_X, TFT_Y, "HLT en MLT");
+    TFT_print((char *)SSR2Types[val], LASTX, LASTY);
 }
 
 
@@ -945,24 +934,25 @@
     TFT_fillScreen(_bg);
     TFT_resetclipwin();
     TopMessage("Wijzigen");
-    TFT_setFont(DEFAULT_FONT, NULL);
-    ShowSSR2(2, 28, value);
 
     Buttons_Clear();
-    Buttons_Add( 20,  60,120, 40, "Uit", 0);
-    Buttons_Add(180,  60,120, 40, "HLT of MLT",  1);
-    Buttons_Add( 20, 130,120, 40, "HLT en MLT",  2);
-    Buttons_Add(180, 130,120, 40, "Idle",  3);
+    Buttons_Add( 20,  60,120, 40, (char *)SSR2Types[0], 0);
+    Buttons_Add(180,  60,120, 40, (char *)SSR2Types[1], 1);
+    Buttons_Add( 20, 130,120, 40, (char *)SSR2Types[2], 2);
+    Buttons_Add(180, 130,120, 40, (char *)SSR2Types[3], 3);
     Buttons_Add(120, 200, 80, 40, "Ok",  4);
+    Buttons[4].dark = true;
+    Buttons[value].lock = true;
     Buttons_Show();
 
     while (loop) {
 	key = Buttons_Scan();
 
 	if (key >= 0 && key <= 3) {
+	    Buttons[value].lock = false;
 	    value = key;
-	    TFT_setFont(DEFAULT_FONT, NULL);
-	    ShowSSR2(2, 28, value);
+	    Buttons[value].lock = true;
+	    Buttons_Show();
 	} else if (key == 4) {
 	    loop = false;
 	}
@@ -973,6 +963,45 @@
 
 
 
+void EditMashType(uint8_t *val)
+{
+    bool        loop = true;
+    int		value = (int)*val;
+    int         key;
+
+    _bg = TFT_BLACK;
+    TFT_fillScreen(_bg);
+    TFT_resetclipwin();
+    TopMessage("Wijzigen");
+
+    Buttons_Clear();
+    Buttons_Add( 80,  40,160, 40, (char *)mashTypes[0], 0);
+    Buttons_Add( 80,  90,160, 40, (char *)mashTypes[1], 1);
+    Buttons_Add( 80, 140,160, 40, (char *)mashTypes[2], 2);
+    Buttons_Add(120, 200, 80, 40, "Ok",  3);
+    Buttons[3].dark = true;
+    Buttons[value].lock = true;
+    Buttons_Show();
+
+    while (loop) {
+	key = Buttons_Scan();
+
+	if (key >= 0 && key <= 2) {
+	    Buttons[value].lock = false;
+	    value = key;
+	    Buttons[value].lock = true;
+	    Buttons_Show();
+	} else if (key == 3) {
+	    loop = false;
+	}
+	vTaskDelay(20 / portTICK_PERIOD_MS);
+    }
+    Buttons[value].lock = false;
+    *val = (uint8_t)value;
+}
+
+
+
 int Confirm(char *top, char *ack, char *nak)
 {
     int		rc = false;
--- a/main/buttons.h	Fri Oct 26 13:29:14 2018 +0200
+++ b/main/buttons.h	Fri Oct 26 21:23:46 2018 +0200
@@ -225,6 +225,12 @@
 void EditSSR2(int *val);
 
 /**
+ * @brief Edit Mashtype value
+ * @param val The mash type
+ */
+void EditMashType(uint8_t *val);
+
+/**
  * @brief Confirm or not choice. Uses the whole screen.
  * @param top The top screen message.
  * @param ack The text for the ack button.
--- a/main/config.c	Fri Oct 26 13:29:14 2018 +0200
+++ b/main/config.c	Fri Oct 26 21:23:46 2018 +0200
@@ -431,13 +431,13 @@
 	recipe.MashStep[0].Infusion_amount = 15.0;
 	recipe.MashStep[0].Resttime = 1;
 	recipe.MashStep[0].Ramptime = 1;
+	for (int i = 1; i < 8; i++)
+	    recipe.MashStep[i].Type = MASHTYPE_TEMPERATURE;
 	sprintf(recipe.MashStep[1].Name, "Mash");
-	recipe.MashStep[1].Type = MASHTYPE_TEMPERATURE;
 	recipe.MashStep[1].Temperature = 67.0;
 	recipe.MashStep[1].Resttime = 75;
 	recipe.MashStep[1].Ramptime = 1;
 	sprintf(recipe.MashStep[7].Name, "Mash-out");
-	recipe.MashStep[7].Type = MASHTYPE_TEMPERATURE;
 	recipe.MashStep[7].Temperature = 78.0; 
 	recipe.MashStep[7].Resttime = 5;
 	recipe.MashStep[7].Ramptime = 11;
--- a/main/config.h	Fri Oct 26 13:29:14 2018 +0200
+++ b/main/config.h	Fri Oct 26 21:23:46 2018 +0200
@@ -83,6 +83,7 @@
 #define	VERSION		"0.2.5"		///< Application version
 
 
+
 /**
  * @brief Main mode different screens
  */
@@ -146,6 +147,7 @@
     MASH_ADD,				///< Add mash wait
     MASH_IODINE,			///< Wait iodine test
     MASH_REMOVE,			///< Wait mash remove
+    MASH_INFUSE,			///< Wait infusion prompt
 } MASH_TYPE;
 
 /**
--- a/main/files.h	Fri Oct 26 13:29:14 2018 +0200
+++ b/main/files.h	Fri Oct 26 21:23:46 2018 +0200
@@ -6,13 +6,13 @@
 #define _FILESS_H
 
 /**
- *  * @brief Files init fases.
- *   */
+ * @brief Files init fases.
+ */
 void Files_Init(void);
 
 /**
- *  * @brief Files loop screens. Bob-blocking.
- *   */
+ * @brief Files loop screens. Bob-blocking.
+ */
 void Files_Loop(void);
 
 #endif
--- a/main/recipes.c	Fri Oct 26 13:29:14 2018 +0200
+++ b/main/recipes.c	Fri Oct 26 21:23:46 2018 +0200
@@ -37,6 +37,8 @@
 size_t				offs;				///< Offset in buffer
 bool				overflow;			///< Overflow in buffer
 
+extern const char		*mashTypes[];
+
 
 
 /**
@@ -47,7 +49,6 @@
  */
 void Addition_Add(char *Name, uint8_t Type, uint16_t Time)
 {
-//    printf("Addition_Add(%s, %d, %d)\n", Name, Type, Time);
     if (! recipe.Additions) {
 	// No entries yet, add the first one.
     	sprintf(recipe.Addition[recipe.Additions].Name, "%s", Name);
@@ -69,7 +70,6 @@
     // A new entry and we already have some. Add it and keep the list sorted.
     for (int i = 0; i < recipe.Additions; i++) {
 	if (Time > recipe.Addition[i].Time) {
-//	    printf("Insert at %d\n", i);
 	    // Make room
 	    for (int j = i; j < recipe.Additions; j++) {
 		sprintf(recipe.Addition[j+1].Name, "%s", recipe.Addition[j].Name);
@@ -287,7 +287,6 @@
 	}
     }
     if ((_xml_depth == 5) && (strcmp("MASH_STEP", _xml_element[4]) == 0)) {
-//	printf("Flush End MASH_STEP %d %s\n", _xml_depth, _xml_add_name);
 	_xml_mashsteps++;
 	sprintf(recipe.MashStep[_xml_mashsteps].Name, "%s", _xml_add_name);
 	recipe.MashStep[_xml_mashsteps].Type = _xml_add_type;
@@ -350,7 +349,10 @@
     }
     recipe.CoolTemp = 20.0;
     sprintf(recipe.MashStep[0].Name, "Mash-in");
-    if (_xml_tun_temp > recipe.MashStep[1].Temperature) {
+    if ((recipe.MashStep[1].Type == MASHTYPE_INFUSION) && (recipe.MashStep[1].Infusion_temp > 0.0)) {
+	/* If next (first original) step is infusion, take that temperature. */
+	recipe.MashStep[0].Temperature = recipe.MashStep[1].Infusion_temp;
+    } else if (_xml_tun_temp > recipe.MashStep[1].Temperature) {
 	recipe.MashStep[0].Temperature = _xml_tun_temp;
     } else {
     	recipe.MashStep[0].Temperature = recipe.MashStep[1].Temperature + 1.25;
@@ -549,11 +551,9 @@
 			    for (int i = 1; i < 8; i++) {
 				if (recipe.MashStep[i].Resttime) {
 				    TFT_print(recipe.MashStep[i].Name, 2, y);
-				    switch (recipe.MashStep[i].Type) {
-					case MASHTYPE_INFUSION:		TFT_print("I", 200, y);	break;
-					case MASHTYPE_TEMPERATURE:	TFT_print("T", 200, y); break;
-					case MASHTYPE_DECOCTION:	TFT_print("D", 200, y); break;
-				    }
+				    strcpy(tmp, mashTypes[recipe.MashStep[i].Type]);
+				    tmp[1] = '\0';
+				    TFT_print(tmp, 200, y);
 				    sprintf(tmp, "%.2f", recipe.MashStep[i].Temperature);
 				    TFT_print(tmp, 220, y);
 				    sprintf(tmp, "%2d m", recipe.MashStep[i].Resttime);
@@ -622,6 +622,8 @@
 
 			    case 1:	memset(&recipe, 0, sizeof(recipe));
 					recipe.Version = 1;
+					for (int i = 1; i < 8; i++) 
+					    recipe.MashStep[i].Type = MASHTYPE_TEMPERATURE;
 					sprintf(recipe.Name, "Recipe %d", r_Records + 1);
 					sprintf(recipe.Code, "00%d", r_Records + 1);
 					sprintf(recipe.MashStep[0].Name, "Mash-in");
@@ -631,12 +633,10 @@
 					recipe.MashStep[0].Resttime = 1;
 					recipe.MashStep[0].Ramptime = 1;
 					sprintf(recipe.MashStep[1].Name, "Mash");
-					recipe.MashStep[1].Type = MASHTYPE_TEMPERATURE;
 					recipe.MashStep[1].Temperature = 67.0;
 					recipe.MashStep[1].Resttime = 75;
 					recipe.MashStep[1].Ramptime = 1;
 					sprintf(recipe.MashStep[7].Name, "Mash-out");
-					recipe.MashStep[7].Type = MASHTYPE_TEMPERATURE;
 					recipe.MashStep[7].Temperature = 78.0;
 					recipe.MashStep[7].Resttime = 5;
 					recipe.MashStep[7].Ramptime = 11;
@@ -715,6 +715,7 @@
 			for (int i = 1; i <= mashsteps; i++) {
 			    sprintf(tmp, "Maisch stap %d naam", i);
 			    EditText(tmp, recipe.MashStep[i].Name, 31);
+			    EditMashType(&recipe.MashStep[i].Type);
 			    sprintf(tmp, "Maisch stap %d temperatuur", i);
 			    if (i == 1)
 				mintemp = recipe.MashStep[0].Temperature - 5;
@@ -729,6 +730,15 @@
 			    } else {
 				recipe.MashStep[i].Ramptime = (int)(recipe.MashStep[i].Temperature - recipe.MashStep[i - 1].Temperature);
 			    }
+			    if (recipe.MashStep[i].Type == MASHTYPE_INFUSION) {
+				sprintf(tmp, "Stap %d infusie temperatuur", i);
+				mintemp = recipe.MashStep[i].Temperature;
+				EditFloat(tmp, &recipe.MashStep[i].Infusion_temp, mintemp, 100, 2);
+				sprintf(tmp, "Stap %d infusie volume", i);
+				EditFloat(tmp, &recipe.MashStep[i].Infusion_amount, 0.5, 1000.0, 2);
+			    } else {
+				recipe.MashStep[i].Infusion_temp = recipe.MashStep[i].Infusion_amount = 0.0;
+			    }
 			}
 			mintemp = recipe.MashStep[mashsteps].Temperature;
 			EditFloat("Uitmaischen temperatuur", &recipe.MashStep[7].Temperature, mintemp, 80, 2);

mercurial