Tue, 07 May 2019 22:03:38 +0200
Finished websockets screens.
0 | 1 | /** |
2 | * @file automation.c | |
3 | * @brief Automation functions. | |
4 | */ | |
5 | ||
6 | #include "config.h" | |
7 | ||
1
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
8 | int BoilPower = 100; ///< Boil power 0..100% |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
9 | int LastMashStep = 0; ///< Last valid mash step |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
10 | char temp_buf[64]; ///< Temporary buffer |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
11 | char logline[128]; ///< Log line buffer |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
12 | char strftime_buf[64]; ///< Time buffer |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
13 | bool loop; ///< Loop flag |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
14 | bool CoolBeep = false; ///< Did beep during cooling |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
15 | bool Resume = false; ///< Resume brew flag |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
16 | bool pumpRest = false; ///< Pump is resting |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
17 | bool updateRuntime = false; ///< Update runtime record |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
18 | bool NewMinute = false; ///< We have a new minute |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
19 | bool TempReached = false; ///< Temperature is reached |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
20 | uint8_t MashState = MASH_NONE; ///< Mash states |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
21 | float temp_MLT; ///< MLT temperature |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
22 | float MinMash = 38.0; ///< Minimum edit value |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
23 | float MaxMash = 80.0; ///< Maximum edit value |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
24 | uint32_t power_MLT = 0; ///< MLT power |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
25 | uint32_t power_HLT = 0; ///< HLT power |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
26 | uint32_t counts = 0; ///< Counter for power average |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
27 | float stageTemp = 0.0; ///< Current stage temperature |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
28 | uint16_t stageTime = 0; ///< Current stage timer |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
29 | uint16_t TimeWhirlPool = 0; ///< Whirlpool timer |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
30 | uint32_t TimeLeft = 0; ///< Tie left in this stage |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
31 | uint32_t TimeSpent = 0; ///< Tota time spent |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
32 | uint32_t SecsCount = 0; ///< Seconds counter |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
33 | uint32_t pumpTime = 0; ///< Pump running time |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
34 | uint32_t TimeBrewing = 0; ///< Brewing time elapsed |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
35 | uint16_t Steady = 0; ///< Temperature is steady |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
36 | bool _NewMinute = false; ///< New minute slave flag |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
37 | bool _UseHLT = false; ///< Use HLT slave flag |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
38 | bool _Prompt = false; ///< Prompt display flag |
0 | 39 | |
1
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
40 | extern bool System_TimeOk; ///< System time is valid |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
41 | extern sButton Buttons[MAXBUTTONS]; ///< Buttons definitions |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
42 | extern int Main_Screen; ///< Current screen |
42 | 43 | extern int Sub_Screen; ///< Sub screen during mash |
1
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
44 | extern DS18B20_State *ds18b20_state; ///< DS18B20 state |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
45 | extern DRIVER_State *driver_state; ///< Relays driver state |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
46 | extern SemaphoreHandle_t xSemaphoreDS18B20; ///< DS18B20 lock semaphore |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
47 | extern SemaphoreHandle_t xSemaphoreDriver; ///< Relays driver lock semaphore |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
48 | extern double Output; ///< Cakculated outpout power |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
49 | extern time_t now; ///< Current time |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
50 | extern struct tm timeinfo; ///< Current time structure |
0 | 51 | |
52 | #ifdef CONFIG_TEMP_SENSORS_SIMULATOR | |
53 | extern float Fake_MLT; | |
54 | extern float Fake_HLT; | |
55 | #endif | |
56 | ||
19 | 57 | extern const char *mashTypes[]; |
58 | ||
0 | 59 | static const char *TAG = "automation"; |
60 | ||
61 | ||
62 | /* | |
63 | * Automation init function that only runs once when a | |
64 | * new screen is entered. | |
65 | */ | |
66 | bool Automation_Init(void) | |
67 | { | |
42 | 68 | char msg[64]; |
69 | ||
0 | 70 | switch (Main_Screen) { |
42 | 71 | case MAIN_AUTO_INIT1: |
0 | 72 | #ifdef CONFIG_TEMP_SENSORS_SIMULATOR |
73 | Fake_MLT = recipe.MashStep[0].Temperature - 10; | |
74 | Fake_HLT = recipe.SpargeTemp - 15; | |
75 | if (xSemaphoreTake(xSemaphoreDS18B20, 10) == pdTRUE) { | |
76 | ds18b20_state->mlt_temperature = ((int)(Fake_MLT * 16)) / 16.0; | |
77 | ds18b20_state->hlt_temperature = ((int)(Fake_HLT * 16)) / 16.0; | |
78 | xSemaphoreGive(xSemaphoreDS18B20); | |
79 | } | |
80 | #endif | |
81 | for (int i = 0; i < 7; i++) { | |
82 | if (recipe.MashStep[i].Resttime) | |
83 | LastMashStep = i; | |
84 | } | |
85 | ESP_LOGI(TAG, "Last mash step %d", LastMashStep); | |
86 | ||
87 | // Check for a crashed session. | |
88 | if (runtime.AutoModeStarted) { | |
89 | TopMessage("Brouwen hervatten?"); | |
90 | Buttons_Add( 40, 100, 80, 40, "Ja", 0); | |
91 | Buttons_Add(200, 100, 80, 40, "Nee", 1); | |
92 | Buttons_Show(); | |
93 | SoundPlay(SOUND_Prompt); | |
94 | loop = true; | |
95 | while (loop) { | |
96 | switch (Buttons_Scan()) { | |
97 | case 0: loop = false; | |
98 | Resume = true; | |
99 | Main_Screen = runtime.StageResume; | |
100 | TimeLeft = runtime.StageTimeLeft; | |
101 | TimeBrewing = runtime.TimeBrewing; | |
102 | _UseHLT = runtime.UseHLT; | |
103 | MashState = MASH_NONE; | |
104 | pumpTime = 0; | |
105 | pumpRest = false; | |
106 | if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
107 | driver_state->enable = true; | |
108 | if (_UseHLT) { | |
109 | driver_state->hlt_sp = recipe.SpargeTemp; | |
110 | driver_state->hlt_mode = HLT_MODE_BANG; | |
111 | } | |
112 | xSemaphoreGive(xSemaphoreDriver); | |
113 | } | |
114 | ESP_LOGI(TAG, "Resume brew screen %d, time left %d", Main_Screen, TimeLeft); | |
115 | log_begin((time_t)0); | |
116 | update_json(); | |
117 | log_annotation(ANNOTATION_SYSTEM, "Resume"); | |
118 | return true; | |
119 | break; | |
120 | ||
121 | case 1: loop = false; | |
122 | Resume = false; | |
123 | break; | |
124 | ||
125 | default: | |
126 | break; | |
127 | } | |
128 | vTaskDelay(50 / portTICK_PERIOD_MS); | |
129 | } | |
130 | Buttons_Clear(); | |
131 | TFT_fillScreen(_bg); | |
132 | } | |
133 | ||
134 | if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
135 | driver_state->enable = true; | |
136 | xSemaphoreGive(xSemaphoreDriver); | |
137 | } | |
138 | runtime.AutoModeStarted = true; | |
139 | runtime.UseHLT = _UseHLT = false; | |
140 | runtime.TimeBrewing = 0; | |
141 | TimeBrewing = 0; | |
42 | 142 | runtime.StageResume = MAIN_AUTO_INIT1; |
0 | 143 | runtime.StageTimeLeft = 0; |
144 | runtime.HopAddition = 0; | |
145 | runtime.Logfile[0] = '\0'; | |
146 | runtime.PumpCooling = false; | |
147 | write_runtime(); | |
148 | power_MLT = power_HLT = counts = 0; | |
149 | log_clean(); | |
150 | vTaskDelay(250 / portTICK_PERIOD_MS); // Allow some time | |
151 | break; | |
152 | ||
42 | 153 | case MAIN_AUTO_INIT2: |
0 | 154 | case MAIN_AUTO_DELAYSTART: |
155 | break; | |
156 | ||
157 | case MAIN_AUTO_HEATUP: | |
158 | if (runtime.UseHLT) { | |
159 | if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
160 | driver_state->hlt_mode = HLT_MODE_BANG; | |
161 | xSemaphoreGive(xSemaphoreDriver); | |
162 | } | |
163 | TopMessage("Spoelwater opwarmen"); | |
164 | MLT_info(71, 26, false); | |
165 | HLT_info(71,150, false, false); | |
166 | } | |
167 | break; | |
168 | ||
169 | case MAIN_AUTO_MASH_IN: | |
170 | case MAIN_AUTO_MASH_1: | |
171 | case MAIN_AUTO_MASH_2: | |
172 | case MAIN_AUTO_MASH_3: | |
173 | case MAIN_AUTO_MASH_4: | |
174 | case MAIN_AUTO_MASH_5: | |
175 | case MAIN_AUTO_MASH_6: | |
176 | case MAIN_AUTO_MASH_OUT: | |
177 | if (Main_Screen == MAIN_AUTO_MASH_IN) { | |
178 | MinMash = 38.0; | |
179 | MaxMash = recipe.MashStep[1].Temperature + 10.0; | |
180 | TimeBrewing = 0; | |
181 | runtime.TimeBrewing = 0; | |
182 | if (System_TimeOk) { | |
183 | time(&now); | |
184 | localtime_r(&now, &timeinfo); | |
185 | log_begin(now); | |
186 | runtime.BrewStart = now; | |
187 | } else { | |
188 | log_begin((time_t)0); | |
189 | runtime.BrewStart = (time_t)0; | |
190 | } | |
191 | updateRuntime = true; | |
192 | } else if (Main_Screen == MAIN_AUTO_MASH_OUT) { | |
193 | MinMash = 75.0; | |
194 | MaxMash = 80.0; | |
195 | } else { | |
196 | MinMash = recipe.MashStep[Main_Screen - MAIN_AUTO_MASH_IN - 1].Temperature; | |
197 | if (recipe.MashStep[Main_Screen - MAIN_AUTO_MASH_IN + 1].Resttime) { | |
198 | MaxMash = recipe.MashStep[Main_Screen - MAIN_AUTO_MASH_IN + 1].Temperature; | |
199 | } else { | |
200 | MaxMash = 75.0; | |
201 | } | |
202 | } | |
42 | 203 | MashState = Sub_Screen = MASH_NONE; |
204 | snprintf(msg, 63, "{\"main\":\"%d\",\"sub\":\"%d\",\"timer\":\"\"}", Main_Screen, Sub_Screen); | |
205 | ws_server_send_text_clients("/ws", msg, strlen(msg)); | |
0 | 206 | pumpTime = 0; |
207 | pumpRest = false; | |
208 | runtime.StageResume = Main_Screen; | |
209 | updateRuntime = true; | |
210 | TopMessage("Maischen"); | |
211 | MLT_info(71, 26, false); | |
212 | if (_UseHLT) { | |
213 | HLT_info(71,170, false, true); | |
214 | } | |
215 | break; | |
216 | ||
217 | case MAIN_AUTO_TOBOIL: | |
218 | if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
219 | driver_state->mlt_sp = stageTemp = config.BoilTemperature; | |
220 | driver_state->mlt_mode = MLT_MODE_EXT; | |
221 | driver_state->hlt_sp = 0.0; | |
222 | driver_state->hlt_mode = HLT_MODE_NONE; | |
223 | xSemaphoreGive(xSemaphoreDriver); | |
224 | } | |
225 | ||
226 | runtime.StageResume = Main_Screen; | |
227 | updateRuntime = true; | |
228 | TempReached = false; | |
229 | ||
230 | TopMessage("Naar koken"); | |
231 | MLT_info(71, 26, false); | |
232 | Buttons_Add( 5, 30, 60, 40, "+sp", 0); | |
233 | Buttons_Add(255, 30, 60, 40, "-sp", 1); | |
234 | Buttons_Show(); | |
235 | ESP_LOGI(TAG, "Mash done, going to boil."); | |
42 | 236 | Sub_Screen = 0; |
0 | 237 | break; |
238 | ||
239 | case MAIN_AUTO_BOILING: | |
240 | if (Resume) { | |
241 | TimeLeft = runtime.StageTimeLeft * 60; | |
242 | } else { | |
42 | 243 | // +1 minute for flameout and for a smooth transition. |
0 | 244 | runtime.StageTimeLeft = TimeLeft = (recipe.BoilTime * 60) + 60; |
245 | runtime.StageResume = Main_Screen; | |
246 | runtime.HopAddition = 0; | |
247 | } | |
248 | SecsCount = 0; | |
249 | ||
250 | if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
251 | driver_state->mlt_sp = stageTemp = config.BoilTemperature; | |
252 | driver_state->mlt_mode = MLT_MODE_EXT; | |
253 | xSemaphoreGive(xSemaphoreDriver); | |
254 | } | |
255 | SoundPlay(SOUND_TempReached); | |
256 | BoilPower = equipment.BoilPower; | |
257 | updateRuntime = true; | |
258 | TopMessage("Koken"); | |
259 | MLT_info(71, 26, false); | |
260 | Buttons_Add( 3, 30, 60, 40, "+sp", 0); | |
261 | Buttons_Add(257, 30, 60, 40, "-sp", 1); | |
262 | Buttons_Add( 3, 190, 60, 40, "+1m", 2); | |
263 | Buttons_Add(257, 190, 60, 40, "-1m", 3); | |
264 | Buttons_Show(); | |
265 | ESP_LOGI(TAG, "Boil temperature reached, boil %d minutes", (TimeLeft / 60) -1); | |
266 | log_annotation(ANNOTATION_STAGE, "Koken"); | |
42 | 267 | Sub_Screen = 0; |
0 | 268 | break; |
269 | ||
270 | case MAIN_AUTO_COOLING_H: | |
271 | case MAIN_AUTO_COOLING_M: | |
272 | case MAIN_AUTO_COOLING_C: | |
273 | TempReached = false; | |
274 | runtime.StageResume = Main_Screen; | |
275 | runtime.StageTimeLeft = 0; | |
276 | updateRuntime = true; | |
277 | if ((Main_Screen == MAIN_AUTO_COOLING_H) && (! recipe.Whirlpool7)) { | |
278 | // Skip cooling before whirlpool 74 degrees | |
279 | Main_Screen = MAIN_AUTO_COOLING_M; | |
280 | return true; //goto startover; | |
281 | } | |
282 | if ((Main_Screen == MAIN_AUTO_COOLING_M) && (! recipe.Whirlpool6)) { | |
283 | // Skip cooling before whirlpool 63 degrees. | |
284 | Main_Screen = MAIN_AUTO_COOLING_C; | |
285 | return true; //goto startover; | |
286 | } | |
287 | TopMessage("Start koelen?"); | |
288 | Buttons_Add( 40, 100, 80, 40, "Start", 0); | |
289 | Buttons_Add(200, 100, 80, 40, "Stop", 1); | |
290 | Buttons[1].dark = true; | |
291 | Buttons_Show(); | |
292 | SoundPlay(SOUND_Prompt); | |
293 | _Prompt = true; | |
294 | break; | |
295 | ||
296 | case MAIN_AUTO_WHIRLPOOL7: | |
297 | case MAIN_AUTO_WHIRLPOOL6: | |
298 | case MAIN_AUTO_WHIRLPOOL2: | |
299 | TempReached = true; | |
300 | runtime.StageResume = Main_Screen; | |
301 | updateRuntime = true; | |
302 | if ((Main_Screen == MAIN_AUTO_WHIRLPOOL9) && (! recipe.Whirlpool9)) { | |
303 | // Skip whirlpool 93 degrees. | |
304 | Main_Screen = MAIN_AUTO_COOLING_H; | |
305 | return true; //goto startover; | |
306 | } | |
307 | if ((Main_Screen == MAIN_AUTO_WHIRLPOOL7) && (! recipe.Whirlpool7)) { | |
308 | // Skip whirlpool 74 degrees. | |
309 | Main_Screen = MAIN_AUTO_COOLING_M; | |
310 | return true; //goto startover; | |
311 | } | |
312 | if ((Main_Screen == MAIN_AUTO_WHIRLPOOL6) && (! recipe.Whirlpool6)) { | |
313 | // Skip whirlpool 63 degrees. | |
314 | Main_Screen = MAIN_AUTO_COOLING_C; | |
315 | return true; //goto startover; | |
316 | } | |
317 | if ((Main_Screen == MAIN_AUTO_WHIRLPOOL2) && (! recipe.Whirlpool2)) { | |
318 | // Skip final whirlpool. | |
319 | Main_Screen = MAIN_AUTO_DONE; | |
320 | return true; //goto startover; | |
321 | } | |
322 | ||
323 | TopMessage("Start Whirlpool?"); | |
324 | Buttons_Add( 40, 100, 80, 40, "Start", 0); | |
325 | Buttons_Add(200, 100, 80, 40, "Stop", 1); | |
326 | Buttons[1].dark = true; | |
327 | Buttons_Show(); | |
328 | SoundPlay(SOUND_Prompt); | |
329 | _Prompt = true; | |
330 | break; | |
331 | ||
332 | case MAIN_AUTO_DONE: | |
333 | case MAIN_AUTO_ABORT: | |
334 | if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
335 | driver_state->enable = false; | |
336 | driver_state->mlt_mode = MLT_MODE_NONE; | |
337 | driver_state->mlt_sp = 0.0; | |
338 | driver_state->hlt_mode = HLT_MODE_NONE; | |
339 | driver_state->hlt_sp = 0.0; | |
340 | driver_state->pump_run = 0; | |
341 | xSemaphoreGive(xSemaphoreDriver); | |
342 | } | |
343 | _fg = TFT_YELLOW; | |
344 | TFT_setFont(DEJAVU24_FONT, NULL); | |
345 | if (Main_Screen == MAIN_AUTO_DONE) { | |
346 | TFT_print("Brouwen is gereed.", CENTER, CENTER); | |
347 | ESP_LOGI(TAG, "Brew is done"); | |
348 | SoundPlay(SOUND_End); | |
349 | } else { | |
350 | TFT_print("Brouwen is afgebroken.", CENTER, CENTER); | |
351 | ESP_LOGI(TAG, "Brew is aborted"); | |
352 | SoundPlay(SOUND_Warn); | |
353 | } | |
354 | log_close(); | |
355 | runtime.Logfile[0] = '\0'; | |
356 | runtime.BrewStart = (time_t)0; | |
357 | runtime.AutoModeStarted = false; | |
358 | runtime.StageResume = MAIN_MODE_FREE; | |
359 | runtime.PumpCooling = false; | |
360 | runtime.HopAddition = 0; | |
361 | runtime.TimeBrewing = 0; | |
362 | runtime.StageTimeLeft = 0; | |
363 | updateRuntime = true; | |
364 | Buttons_Add(130, 200, 60, 40, "Ok", 0); | |
365 | Buttons[0].dark = true; | |
366 | Buttons_Show(); | |
367 | break; | |
368 | ||
369 | default: | |
370 | break; | |
371 | } | |
372 | ||
373 | return false; | |
374 | } | |
375 | ||
376 | ||
377 | ||
378 | /* | |
379 | * Automation loop screens. Mostly non-blocking. | |
380 | */ | |
381 | bool Automation_Loop(void) | |
382 | { | |
383 | static bool beeped = false; | |
42 | 384 | char tmp[32], msg[256]; |
0 | 385 | uint16_t y; |
386 | ||
387 | switch (Main_Screen) { | |
388 | ||
42 | 389 | case MAIN_AUTO_INIT1: |
0 | 390 | /* |
391 | * Present selected equipment and recipe. | |
392 | */ | |
42 | 393 | Sub_Screen = 1; |
0 | 394 | read_recipe(config.RecipeRec); |
42 | 395 | snprintf(msg, 255, "{\"main\":\"%d\",\"sub\":\"%d\",\"timer\":\"\",\"brew1\":\"%s\",\"brew2\":\"%s\"}", |
396 | Main_Screen, Sub_Screen, equipment.Name, recipe.Name); | |
397 | ws_server_send_text_clients("/ws", msg, strlen(msg)); | |
0 | 398 | y = 28; |
399 | TopMessage("Automaat"); | |
400 | TFT_setFont(DEFAULT_FONT, NULL); | |
401 | ShowText(2,y,"Installatie", equipment.Name); | |
402 | y += 16; | |
403 | ShowText(2,y,"Recept", recipe.Name); | |
404 | y += 16; | |
405 | ShowFloat(2, y, "Maisch in", " C", recipe.MashStep[0].Temperature, 2); | |
406 | ShowFloat(162, y, "Spoelwater", " C", recipe.SpargeTemp, 2); | |
407 | y += 16; | |
408 | _fg = TFT_WHITE; | |
409 | TFT_print("Maisch stap", 2, y); | |
19 | 410 | TFT_print("T", 200, y); |
411 | TFT_print("Temp.", 220, y); | |
412 | TFT_print("Rust", 280, y); | |
0 | 413 | _fg = TFT_YELLOW; |
414 | y += 16; | |
415 | for (int i = 1; i < 8; i++) { | |
416 | if (recipe.MashStep[i].Resttime) { | |
417 | TFT_print(recipe.MashStep[i].Name, 2, y); | |
19 | 418 | strcpy(tmp, mashTypes[recipe.MashStep[i].Type]); |
419 | tmp[1] = '\0'; | |
0 | 420 | TFT_print(tmp, 200, y); |
19 | 421 | sprintf(tmp, "%.2f", recipe.MashStep[i].Temperature); |
422 | TFT_print(tmp, 220, y); | |
423 | sprintf(tmp, "%2d m", recipe.MashStep[i].Resttime); | |
424 | TFT_print(tmp, 280, y); | |
0 | 425 | y += 16; |
426 | } | |
427 | } | |
19 | 428 | ShowInteger(2, y, "Kooktijd", " min", recipe.BoilTime); |
429 | ShowFloat(162, y, "Koel tot", " C", recipe.CoolTemp, 2); | |
0 | 430 | y += 16; |
431 | if (recipe.Additions) { | |
432 | _fg = TFT_YELLOW; | |
433 | sprintf(tmp, "%d ", recipe.Additions); | |
434 | TFT_print(tmp, 2, y); | |
435 | _fg = TFT_WHITE; | |
436 | TFT_print("toevoegingen om", LASTX, y); | |
437 | _fg = TFT_YELLOW; | |
438 | for (int i = 1; i <= recipe.Additions; i++) { | |
439 | sprintf(tmp, " %d", recipe.Addition[i-1].Time); | |
440 | TFT_print(tmp, LASTX, y); | |
441 | } | |
442 | _fg = TFT_WHITE; | |
443 | TFT_print(" minuten", LASTX, y); | |
444 | } else { | |
445 | _fg = TFT_WHITE; | |
446 | TFT_print("Geen hop toevoegingen.", 2, y); | |
447 | } | |
448 | y += 16; | |
449 | if (recipe.Whirlpool9) { | |
450 | ShowInteger(2, y, "Whirlpool 88..100 graden", " minuten", recipe.Whirlpool9); | |
451 | y += 16; | |
452 | } | |
453 | if (recipe.Whirlpool7) { | |
454 | ShowInteger(2, y, "Whirlpool 71..77 graden", " minuten", recipe.Whirlpool7); | |
455 | y += 16; | |
456 | } | |
457 | if (recipe.Whirlpool6) { | |
458 | ShowInteger(2, y, "Whirlpool 60..66 graden", " minuten", recipe.Whirlpool6); | |
459 | y += 16; | |
460 | } | |
461 | if (recipe.Whirlpool2) { | |
462 | ShowInteger(2, y, "Whirlpool koud", " minuten", recipe.Whirlpool2); | |
463 | y += 16; | |
464 | } | |
465 | Buttons_Add( 0, 210, 70, 30, "Stop" , 0); | |
466 | Buttons_Add(250, 210, 70, 30, "Start" , 1); | |
467 | Buttons[0].dark = true; | |
468 | Buttons_Show(); | |
469 | loop = true; | |
470 | while (loop) { | |
471 | switch (Buttons_Scan()) { | |
472 | case 0: loop = false; | |
473 | Main_Screen = MAIN_AUTO_ABORT; | |
474 | break; | |
475 | ||
476 | case 1: loop = false; | |
42 | 477 | Main_Screen = MAIN_AUTO_INIT2; |
0 | 478 | break; |
479 | ||
480 | default: break; | |
481 | } | |
482 | vTaskDelay(20 / portTICK_PERIOD_MS); | |
483 | } | |
42 | 484 | Buttons_Clear(); |
485 | break; | |
0 | 486 | |
42 | 487 | case MAIN_AUTO_INIT2: |
0 | 488 | _UseHLT = false; |
489 | _bg = TFT_BLACK; | |
490 | TFT_fillScreen(_bg); | |
491 | TopMessage("Maisch water aanwezig?"); | |
492 | Buttons_Clear(); | |
493 | Buttons_Add( 40, 100, 80, 40, "Ja", 0); | |
494 | Buttons_Add(200, 100, 80, 40, "Nee", 1); | |
495 | Buttons_Show(); | |
496 | SoundPlay(SOUND_Prompt); | |
497 | loop = true; | |
498 | while (loop) { | |
499 | switch (Buttons_Scan()) { | |
500 | case 0: loop = false; | |
501 | break; | |
502 | ||
503 | case 1: loop = false; | |
504 | Main_Screen = MAIN_AUTO_ABORT; | |
505 | break; | |
506 | ||
507 | default: break; | |
508 | } | |
509 | vTaskDelay(20 / portTICK_PERIOD_MS); | |
510 | } | |
511 | if (Main_Screen == MAIN_AUTO_ABORT) | |
512 | break; | |
513 | ||
514 | if ((equipment.SSR2 == SSR2_HLT_SHARE) || (equipment.SSR2 == SSR2_HLT_IND)) { | |
515 | TopMessage("Spoelwater aanwezig?"); | |
516 | SoundPlay(SOUND_Prompt); | |
517 | loop = true; | |
518 | while (loop) { | |
519 | switch (Buttons_Scan()) { | |
520 | case 0: loop = false; | |
521 | _UseHLT = true; | |
522 | break; | |
523 | ||
524 | case 1: loop = false; | |
525 | break; | |
526 | ||
527 | default: break; | |
528 | } | |
529 | vTaskDelay(20 / portTICK_PERIOD_MS); | |
530 | } | |
531 | runtime.UseHLT = _UseHLT; | |
532 | } else { | |
533 | runtime.UseHLT = _UseHLT = false; | |
534 | } | |
535 | updateRuntime = true; | |
536 | if (_UseHLT) { | |
537 | /* | |
538 | * Calculate HLT setpoint for pre-heat. Substract the | |
539 | * available Mash rest times, asume 0.5 degrees/minute | |
540 | * heat capacity during mash. | |
541 | */ | |
542 | int AvailableTime = 0; | |
543 | for (int i = 1; i < 6; i++) // Only normal Mash steps | |
544 | AvailableTime += recipe.MashStep[i].Resttime; | |
545 | if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
546 | driver_state->hlt_sp = recipe.SpargeTemp - ((AvailableTime / 2) + 2); | |
547 | ESP_LOGI(TAG, "HLT preheat set to %4.1f", driver_state->hlt_sp); | |
548 | xSemaphoreGive(xSemaphoreDriver); | |
549 | } | |
550 | } | |
551 | Buttons_Clear(); | |
552 | Main_Screen = MAIN_AUTO_DELAYSTART; | |
553 | break; | |
554 | ||
555 | case MAIN_AUTO_DELAYSTART: | |
556 | Main_Screen = MAIN_AUTO_HEATUP; | |
557 | break; | |
558 | ||
559 | case MAIN_AUTO_HEATUP: | |
560 | if (! runtime.UseHLT) { // Skip if HLT is off | |
561 | Main_Screen = MAIN_AUTO_MASH_IN; | |
562 | break; | |
563 | } | |
564 | ||
565 | MLT_info(71, 26, true); | |
566 | HLT_info(71,150, true, false); | |
567 | if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
568 | if (driver_state->hlt_pv >= driver_state->hlt_sp) { | |
569 | Main_Screen = MAIN_AUTO_MASH_IN; | |
570 | driver_state->hlt_sp = recipe.SpargeTemp; // Set final setpoint | |
571 | } | |
572 | xSemaphoreGive(xSemaphoreDriver); | |
573 | } | |
574 | break; | |
575 | ||
576 | case MAIN_AUTO_MASH_IN: | |
577 | case MAIN_AUTO_MASH_1: | |
578 | case MAIN_AUTO_MASH_2: | |
579 | case MAIN_AUTO_MASH_3: | |
580 | case MAIN_AUTO_MASH_4: | |
581 | case MAIN_AUTO_MASH_5: | |
582 | case MAIN_AUTO_MASH_6: | |
583 | case MAIN_AUTO_MASH_OUT: | |
584 | temp_MLT = 0.0; | |
585 | if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
586 | temp_MLT = driver_state->mlt_pv; | |
587 | ||
588 | if (MashState == MASH_ADD || MashState == MASH_REMOVE) { | |
589 | driver_state->pump_run = 0; | |
590 | } else if (MashState != MASH_NONE) { | |
591 | if (Main_Screen == MAIN_AUTO_MASH_IN) { | |
592 | driver_state->pump_run = (equipment.PumpPreMash && ! pumpRest) ? 1 : 0; | |
593 | } else if (Main_Screen == MAIN_AUTO_MASH_OUT) { | |
594 | driver_state->pump_run = (equipment.PumpMashOut && ! pumpRest) ? 1 : 0; | |
595 | } else { | |
596 | driver_state->pump_run = (equipment.PumpOnMash && ! pumpRest) ? 1 : 0; | |
597 | } | |
598 | } | |
599 | xSemaphoreGive(xSemaphoreDriver); | |
600 | } | |
601 | if (MashState == MASH_NONE) { | |
602 | stageTemp = recipe.MashStep[Main_Screen - MAIN_AUTO_MASH_IN].Temperature; | |
603 | stageTime = recipe.MashStep[Main_Screen - MAIN_AUTO_MASH_IN].Resttime; | |
604 | TempReached = false; | |
605 | if (stageTime == 0) { | |
606 | ESP_LOGI(TAG, "Mash step %d skipped", Main_Screen - MAIN_AUTO_MASH_IN); | |
607 | Main_Screen++; | |
608 | break; | |
609 | } | |
610 | if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
611 | driver_state->mlt_sp = stageTemp; | |
612 | driver_state->mlt_mode = MLT_MODE_PID; | |
613 | xSemaphoreGive(xSemaphoreDriver); | |
614 | } | |
42 | 615 | MashState = Sub_Screen = MASH_WAITTEMP; |
616 | snprintf(msg, 63, "{\"main\":\"%d\",\"sub\":\"%d\",\"timer\":\"\"}", Main_Screen, Sub_Screen); | |
617 | ws_server_send_text_clients("/ws", msg, strlen(msg)); | |
19 | 618 | ESP_LOGI(TAG, "Mash step %d type: %s time: %d temp: %4.1f min: %4.1f max: %4.1f", |
619 | Main_Screen - MAIN_AUTO_MASH_IN, mashTypes[recipe.MashStep[Main_Screen - MAIN_AUTO_MASH_IN].Type], | |
620 | stageTime, stageTemp, MinMash, MaxMash); | |
0 | 621 | |
622 | if (Main_Screen > MAIN_AUTO_MASH_IN) { | |
623 | // Do not annotate before the log is open. | |
624 | if (Main_Screen == MAIN_AUTO_MASH_OUT) { | |
625 | log_annotation(ANNOTATION_STAGE, "Uitmaischen"); | |
626 | } else { | |
627 | sprintf(logline, "Maisch: %d", Main_Screen - MAIN_AUTO_MASH_IN); | |
628 | log_annotation(ANNOTATION_STAGE, logline); | |
629 | } | |
630 | } | |
631 | ||
632 | if (strlen(recipe.MashStep[Main_Screen - MAIN_AUTO_MASH_IN].Name)) { | |
633 | TopMessage(recipe.MashStep[Main_Screen - MAIN_AUTO_MASH_IN].Name); | |
634 | } else { | |
635 | sprintf(temp_buf, "Maisch stap #%d", Main_Screen - MAIN_AUTO_MASH_IN); | |
636 | TopMessage(temp_buf); | |
637 | } | |
19 | 638 | if ((Main_Screen > MAIN_AUTO_MASH_IN) && (Main_Screen < MAIN_AUTO_MASH_OUT) && |
639 | (recipe.MashStep[Main_Screen - MAIN_AUTO_MASH_IN].Type == MASHTYPE_INFUSION)) { | |
640 | Buttons_Add( 5,120, 60, 40, "Halt", 0); | |
641 | Buttons[0].dark = true; | |
642 | Buttons_Add(255,120, 60, 40, "Ok", 1); | |
643 | Buttons_Show(); | |
644 | _fg = TFT_WHITE; | |
645 | _bg = TFT_BLACK; | |
646 | TFT_setFont(DEJAVU18_FONT, NULL); | |
647 | sprintf(temp_buf, "Infuse %.1f L/%.1f C", recipe.MashStep[Main_Screen - MAIN_AUTO_MASH_IN].Infusion_amount, | |
648 | recipe.MashStep[Main_Screen - MAIN_AUTO_MASH_IN].Infusion_temp); | |
649 | TFT_print(temp_buf, CENTER, 135); | |
650 | SoundPlay(SOUND_Prompt); | |
42 | 651 | MashState = Sub_Screen = MASH_INFUSE; |
652 | snprintf(msg, 63, "{\"main\":\"%d\",\"sub\":\"%d\",\"timer\":\"%s\"}", Main_Screen, Sub_Screen, temp_buf); | |
653 | ws_server_send_text_clients("/ws", msg, strlen(msg)); | |
19 | 654 | if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { |
655 | // No heating during the infusion. | |
656 | driver_state->mlt_sp = stageTemp; | |
657 | driver_state->mlt_mode = MLT_MODE_OFF; | |
658 | xSemaphoreGive(xSemaphoreDriver); | |
659 | } | |
660 | ESP_LOGI(TAG, "Mash infusion prompt"); | |
661 | } else { | |
662 | Buttons_Add( 5, 30, 60, 40, "+sp", 0); | |
663 | Buttons_Add(255, 30, 60, 40, "-sp", 1); | |
664 | Buttons_Show(); | |
665 | } | |
0 | 666 | |
667 | } else if (MashState == MASH_WAITTEMP) { | |
668 | pumpRest = false; | |
669 | if (temp_MLT < stageTemp) { | |
670 | Steady = 0; | |
671 | } | |
672 | if ((temp_MLT >= stageTemp) && (Steady > 10)) { | |
673 | SoundPlay(SOUND_TempReached); | |
674 | TempReached = true; | |
42 | 675 | MashState = Sub_Screen = MASH_REST; |
676 | snprintf(msg, 63, "{\"main\":\"%d\",\"sub\":\"%d\",\"timer\":\"\"}", Main_Screen, Sub_Screen); | |
677 | ws_server_send_text_clients("/ws", msg, strlen(msg)); | |
0 | 678 | if (Main_Screen == MAIN_AUTO_MASH_IN) { |
679 | TimerSet(0); | |
680 | } else { | |
681 | if (Resume && (runtime.StageTimeLeft < stageTime)) | |
682 | TimerSet(runtime.StageTimeLeft * 60); | |
683 | else | |
684 | TimerSet(stageTime * 60); | |
685 | } | |
686 | Resume = false; | |
687 | runtime.StageTimeLeft = TimeLeft / 60; | |
688 | updateRuntime = true; | |
689 | ESP_LOGI(TAG, "Mash step %d temperature reached, rest time %d", Main_Screen - MAIN_AUTO_MASH_IN, TimeLeft / 60); | |
690 | Buttons_Clear(); | |
691 | Buttons_Add( 0, 120, 60, 40, "+1m", 0); | |
692 | Buttons_Add(260, 120, 60, 40, "-1m", 1); | |
693 | Buttons_Show(); | |
694 | } | |
695 | switch (Buttons_Scan()) { | |
696 | case 0: if (stageTemp < MaxMash) { | |
697 | stageTemp += 0.25; | |
698 | if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
699 | driver_state->mlt_sp = stageTemp; | |
700 | xSemaphoreGive(xSemaphoreDriver); | |
701 | } | |
702 | } | |
703 | break; | |
704 | ||
705 | case 1: if (stageTemp > MinMash) { | |
706 | stageTemp -= 0.25; | |
707 | if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
708 | driver_state->mlt_sp = stageTemp; | |
709 | xSemaphoreGive(xSemaphoreDriver); | |
710 | } | |
711 | } | |
712 | break; | |
713 | ||
714 | default: | |
715 | break; | |
716 | } | |
717 | if (NewMinute) | |
718 | updateRuntime = true; | |
719 | ||
720 | } else if (MashState == MASH_REST) { | |
721 | /* | |
722 | * Mash step rest time and pump control | |
723 | */ | |
724 | if (((Main_Screen == MAIN_AUTO_MASH_OUT) && equipment.PumpMashOut) || | |
725 | ((Main_Screen != MAIN_AUTO_MASH_OUT) && equipment.PumpOnMash)) { | |
726 | float DeltaTemp = equipment.PumpRest * stageTemp / 120; // Maximum temperature drop before heating again. | |
727 | if (pumpTime >= (equipment.PumpCycle + equipment.PumpRest) || ((stageTemp - temp_MLT) > DeltaTemp)) { | |
728 | pumpTime = 0; | |
729 | } | |
730 | if (pumpTime >= equipment.PumpCycle) { | |
731 | if (! pumpRest) { | |
732 | pumpRest = true; | |
733 | ESP_LOGI(TAG, "Pump rest"); | |
734 | } | |
735 | } else { | |
736 | if (pumpRest) { | |
737 | pumpRest = false; | |
738 | ESP_LOGI(TAG, "Pump start"); | |
739 | } | |
740 | } | |
741 | } | |
742 | if (TimeLeft) { | |
743 | switch (Buttons_Scan()) { | |
744 | case 0: TimeLeft += 60; | |
745 | runtime.StageTimeLeft = TimeLeft / 60; | |
746 | updateRuntime = true; | |
747 | break; | |
748 | ||
749 | case 1: if (TimeLeft < 60) | |
750 | TimeLeft = 0; | |
751 | else | |
752 | TimeLeft -= 60; | |
753 | runtime.StageTimeLeft = TimeLeft / 60; | |
754 | updateRuntime = true; | |
755 | break; | |
756 | ||
757 | default: break; | |
758 | } | |
759 | } | |
760 | ||
761 | if (TimeLeft == 0) { | |
762 | runtime.StageTimeLeft = TimeLeft / 60; | |
763 | updateRuntime = true; | |
764 | if ((Main_Screen == MAIN_AUTO_MASH_IN) && config.AskAdd) { | |
765 | /* | |
766 | * Add Mash prompt. | |
767 | */ | |
768 | log_annotation(ANNOTATION_EVENT, "Mout storten"); | |
769 | Buttons_Clear(); | |
770 | Buttons_Add( 5,120, 60, 40, "Halt", 0); | |
771 | Buttons[0].dark = true; | |
772 | Buttons_Add(255,120, 60, 40, "Ok", 1); | |
773 | Buttons_Show(); | |
774 | _fg = TFT_WHITE; | |
775 | _bg = TFT_BLACK; | |
776 | TFT_setFont(DEJAVU24_FONT, NULL); | |
777 | TFT_print("Mout storten?", CENTER, 135); | |
778 | SoundPlay(SOUND_Prompt); | |
42 | 779 | MashState = Sub_Screen = MASH_ADD; |
780 | snprintf(msg, 63, "{\"main\":\"%d\",\"sub\":\"%d\",\"timer\":\"Mout storten?\"}", Main_Screen, Sub_Screen); | |
781 | ws_server_send_text_clients("/ws", msg, strlen(msg)); | |
0 | 782 | ESP_LOGI(TAG, "Mash add prompt"); |
783 | break; | |
784 | } | |
785 | if (((Main_Screen - MAIN_AUTO_MASH_IN) == LastMashStep) && config.AskIodine) { | |
786 | /* | |
787 | * Iodone test prompt. | |
788 | */ | |
789 | log_annotation(ANNOTATION_EVENT, "Jodium test"); | |
790 | TFT_fillRect(0, 120, 320, 50, TFT_BLACK); | |
791 | Buttons_Clear(); | |
792 | Buttons_Add( 5,120, 60, 40, "Halt", 0); | |
793 | Buttons[0].dark = true; | |
794 | Buttons_Add(255,120, 60, 40, "Ok", 1); | |
795 | Buttons_Show(); | |
796 | _fg = TFT_WHITE; | |
797 | _bg = TFT_BLACK; | |
798 | TFT_setFont(DEJAVU24_FONT, NULL); | |
799 | TFT_print("Jodium test?", CENTER, 127); | |
800 | SoundPlay(SOUND_Prompt); | |
801 | beeped = false; | |
802 | TimerSet(config.IodineTime * 60); | |
42 | 803 | MashState = Sub_Screen = MASH_IODINE; |
804 | snprintf(msg, 63, "{\"main\":\"%d\",\"sub\":\"%d\",\"timer\":\"Jodium test?\"}", Main_Screen, Sub_Screen); | |
805 | ws_server_send_text_clients("/ws", msg, strlen(msg)); | |
0 | 806 | ESP_LOGI(TAG, "Mash iodine test prompt"); |
807 | break; | |
808 | } | |
809 | if ((Main_Screen == MAIN_AUTO_MASH_OUT) && config.AskRemove) { | |
810 | /* | |
811 | * Mash remove prompt. | |
812 | */ | |
813 | log_annotation(ANNOTATION_EVENT, "Mout verwijderen"); | |
814 | TFT_fillRect(0, 120, 320, 50, TFT_BLACK); | |
815 | Buttons_Clear(); | |
816 | Buttons_Add( 5,120, 60, 40, "Halt", 0); | |
817 | Buttons[0].dark = true; | |
818 | Buttons_Add(255,120, 60, 40, "Ok", 1); | |
819 | Buttons_Show(); | |
820 | _fg = TFT_WHITE; | |
821 | _bg = TFT_BLACK; | |
822 | TFT_setFont(DEJAVU18_FONT, NULL); | |
823 | TFT_print("Mout verwijderen?", CENTER, 135); | |
824 | SoundPlay(SOUND_Prompt); | |
42 | 825 | MashState = Sub_Screen = MASH_REMOVE; |
826 | snprintf(msg, 63, "{\"main\":\"%d\",\"sub\":\"%d\",\"timer\":\"Mout verwijderen?\"}", Main_Screen, Sub_Screen); | |
827 | ws_server_send_text_clients("/ws", msg, strlen(msg)); | |
0 | 828 | ESP_LOGI(TAG, "Mash remove prompt"); |
829 | break; | |
830 | } | |
831 | if (Main_Screen != MAIN_AUTO_ABORT) | |
832 | Main_Screen++; | |
833 | TempReached = false; | |
834 | } else { | |
835 | TimerShow(TimeLeft, 65, 122); | |
836 | if (NewMinute) { | |
837 | runtime.StageTimeLeft = TimeLeft / 60; | |
838 | updateRuntime = true; | |
839 | } | |
840 | } | |
841 | } else if (MashState == MASH_ADD) { | |
842 | switch (Buttons_Scan()) { | |
843 | case 0: Main_Screen = MAIN_AUTO_ABORT; | |
844 | break; | |
845 | case 1: Main_Screen++; | |
846 | break; | |
847 | default: break; | |
848 | } | |
849 | } else if (MashState == MASH_IODINE) { | |
850 | if (TimeSpent % 45 == 0) { | |
851 | if (! beeped) { | |
852 | SoundPlay(SOUND_Warn); | |
853 | beeped = true; | |
854 | } | |
855 | } else { | |
856 | beeped = false; | |
857 | } | |
858 | switch (Buttons_Scan()) { | |
859 | case 0: Main_Screen = MAIN_AUTO_ABORT; | |
860 | break; | |
861 | case 1: Main_Screen++; | |
862 | break; | |
863 | default: break; | |
864 | } | |
865 | if (TimeLeft == 0) { | |
866 | Main_Screen++; | |
867 | } | |
868 | } else if (MashState == MASH_REMOVE) { | |
869 | switch (Buttons_Scan()) { | |
870 | case 0: Main_Screen = MAIN_AUTO_ABORT; | |
871 | break; | |
872 | case 1: Main_Screen++; | |
873 | break; | |
874 | default: break; | |
875 | } | |
19 | 876 | } else if (MashState == MASH_INFUSE) { |
877 | switch (Buttons_Scan()) { | |
878 | case 0: Main_Screen = MAIN_AUTO_ABORT; | |
879 | break; | |
42 | 880 | case 1: MashState = Sub_Screen = MASH_WAITTEMP; |
881 | snprintf(msg, 63, "{\"main\":\"%d\",\"sub\":\"%d\",\"timer\":\"\"}", Main_Screen, Sub_Screen); | |
882 | ws_server_send_text_clients("/ws", msg, strlen(msg)); | |
19 | 883 | if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { |
884 | // Start PID again. | |
885 | driver_state->mlt_sp = stageTemp; | |
886 | driver_state->mlt_mode = MLT_MODE_PID; | |
887 | xSemaphoreGive(xSemaphoreDriver); | |
888 | } | |
889 | Buttons_Clear(); | |
890 | Buttons_Add( 5, 30, 60, 40, "+sp", 0); | |
891 | Buttons_Add(255, 30, 60, 40, "-sp", 1); | |
892 | Buttons_Show(); | |
893 | TFT_fillRect(65, 120, 190, 40, TFT_BLACK); | |
27
e82484ef9d12
Fixed placement of infusion event in the graph.
Michiel Broek <mbroek@mbse.eu>
parents:
26
diff
changeset
|
894 | log_annotation(ANNOTATION_EVENT, "Eind infusie"); |
19 | 895 | break; |
896 | default: break; | |
897 | } | |
0 | 898 | } /* MashState */ |
899 | MLT_info(71, 26, true); | |
900 | if (_UseHLT) { | |
901 | HLT_info(71, 170, true, true); | |
902 | } | |
903 | break; | |
904 | ||
905 | case MAIN_AUTO_TOBOIL: | |
906 | Output = 255; | |
907 | /* | |
908 | * Go to the boil temperature and wait until it is steady. | |
909 | */ | |
910 | if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
911 | if (driver_state->mlt_pv < stageTemp) { | |
912 | Steady = 0; | |
913 | } else { | |
914 | if (Steady > 10) { | |
915 | Main_Screen = MAIN_AUTO_BOILING; | |
916 | TempReached = true; | |
917 | } | |
918 | } | |
919 | driver_state->pump_run = (equipment.PumpOnBoil && (driver_state->mlt_pv < equipment.PumpMaxTemp)) ? 1 : 0; | |
920 | xSemaphoreGive(xSemaphoreDriver); | |
921 | } | |
922 | ||
923 | MLT_info(71, 26, true); | |
924 | switch (Buttons_Scan()) { | |
925 | case 0: if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
926 | driver_state->mlt_sp += 0.25; | |
927 | xSemaphoreGive(xSemaphoreDriver); | |
928 | } | |
929 | break; | |
930 | ||
931 | case 1: if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
932 | driver_state->mlt_sp -= 0.25; | |
933 | xSemaphoreGive(xSemaphoreDriver); | |
934 | } | |
935 | break; | |
936 | ||
937 | default: break; | |
938 | } | |
939 | if (Resume) | |
940 | Resume = false; | |
941 | break; | |
942 | ||
943 | case MAIN_AUTO_BOILING: | |
944 | if (Resume) | |
945 | Resume = false; | |
946 | if (NewMinute) { | |
947 | if ((runtime.HopAddition < recipe.Additions) && (TimeLeft <= ((recipe.Addition[runtime.HopAddition].Time * 60) + 60))) { | |
948 | ESP_LOGI(TAG, "Hop addition %d at %d minutes", runtime.HopAddition + 1, recipe.Addition[runtime.HopAddition].Time); | |
949 | TopMessage(recipe.Addition[runtime.HopAddition].Name); | |
26
373a33699605
Graph title includes beer code. Hop additions now only display the additions themselfes.
Michiel Broek <mbroek@mbse.eu>
parents:
24
diff
changeset
|
950 | log_annotation(ANNOTATION_EVENT, recipe.Addition[runtime.HopAddition].Name); |
0 | 951 | SoundPlay(SOUND_AddHop); |
952 | runtime.HopAddition++; | |
953 | } else { | |
954 | TopMessage("Koken"); | |
955 | } | |
956 | runtime.StageTimeLeft = TimeLeft / 60; | |
957 | updateRuntime = true; | |
958 | } | |
959 | if (TimeLeft < 60) { | |
960 | if (Output) { | |
961 | log_annotation(ANNOTATION_STAGE, "Vlamuit"); | |
962 | } | |
963 | // Flameout | |
964 | Output = 0; | |
965 | } else if (driver_state->mlt_pv >= stageTemp) { | |
966 | Output = (int)((BoilPower * 255.0) / 100.0); | |
967 | if (Buttons[4].x == -1) { | |
968 | Buttons_Add( 3,110, 60, 40, "+%", 4); | |
969 | Buttons_Add(257,110, 60, 40, "-%", 5); | |
970 | Buttons_Show(); | |
971 | } | |
972 | } else { | |
973 | Output = 255; | |
974 | if (Buttons[4].x != -1) { | |
975 | Buttons[4].x = Buttons[5].x = -1; | |
976 | Buttons_Show(); | |
977 | TFT_fillRect( 3,110, 60, 40, TFT_BLACK); | |
978 | TFT_fillRect(257,110, 60, 40, TFT_BLACK); | |
979 | } | |
980 | } | |
981 | ||
982 | MLT_info(71, 26, true); | |
983 | TimerShow(TimeLeft, 65, 190); | |
984 | ||
985 | switch (Buttons_Scan()) { | |
986 | case 0: if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
987 | driver_state->mlt_sp += 0.25; | |
988 | xSemaphoreGive(xSemaphoreDriver); | |
989 | } | |
990 | break; | |
991 | ||
992 | case 1: if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
993 | driver_state->mlt_sp -= 0.25; | |
994 | xSemaphoreGive(xSemaphoreDriver); | |
995 | } | |
996 | break; | |
997 | ||
998 | case 2: TimeLeft += 60; | |
999 | break; | |
1000 | ||
1001 | case 3: if (TimeLeft > 60) | |
1002 | TimeLeft -= 60; | |
1003 | else | |
1004 | TimeLeft = 0; | |
1005 | break; | |
1006 | ||
1007 | case 4: if (BoilPower < 100) | |
1008 | BoilPower++; | |
1009 | break; | |
1010 | ||
1011 | case 5: if (BoilPower > 0) | |
1012 | BoilPower--; | |
1013 | break; | |
1014 | ||
1015 | default: break; | |
1016 | } | |
1017 | ||
1018 | if (TimeLeft == 0) { | |
1019 | Main_Screen = MAIN_AUTO_WHIRLPOOL9; | |
1020 | ESP_LOGI(TAG, "Boil is ready"); | |
1021 | } | |
1022 | break; | |
1023 | ||
1024 | case MAIN_AUTO_COOLING_H: | |
1025 | case MAIN_AUTO_COOLING_M: | |
1026 | case MAIN_AUTO_COOLING_C: | |
1027 | if (_Prompt) { | |
1028 | /* | |
1029 | * Prompt mode | |
1030 | */ | |
1031 | switch (Buttons_Scan()) { | |
1032 | case 0: _Prompt = false; | |
1033 | Buttons_Clear(); | |
1034 | break; | |
1035 | case 1: Main_Screen = MAIN_AUTO_DONE; | |
1036 | Buttons_Clear(); | |
1037 | return true; //goto startover; | |
1038 | break; | |
1039 | default: | |
1040 | break; | |
1041 | } | |
1042 | ||
1043 | if (! _Prompt) { | |
1044 | /* | |
1045 | * Starting cooling, setup the screen. | |
1046 | */ | |
1047 | Buttons_Clear(); | |
1048 | TFT_fillScreen(_bg); | |
42 | 1049 | Sub_Screen = 1; |
0 | 1050 | if (Main_Screen == MAIN_AUTO_COOLING_H) { |
1051 | stageTemp = 77.0; | |
1052 | } else if (Main_Screen == MAIN_AUTO_COOLING_M) { | |
1053 | stageTemp = 66.0; | |
1054 | } else { | |
1055 | stageTemp = recipe.CoolTemp; | |
1056 | } | |
42 | 1057 | snprintf(msg, 63, "{\"main\":\"%d\",\"sub\":\"%d\",\"timer\":\"\"}", Main_Screen, Sub_Screen); |
1058 | ws_server_send_text_clients("/ws", msg, strlen(msg)); | |
0 | 1059 | CoolBeep = false; |
1060 | ESP_LOGI(TAG, "Start cooling from %6.2f to %4.1f", ds18b20_state->mlt_temperature, stageTemp); | |
1061 | if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
1062 | driver_state->mlt_mode = MLT_MODE_OFF; | |
1063 | driver_state->mlt_sp = stageTemp; | |
1064 | xSemaphoreGive(xSemaphoreDriver); | |
1065 | } | |
1066 | log_annotation(ANNOTATION_STAGE, "Koelen"); | |
1067 | TopMessage("Koelen"); | |
1068 | MLT_info(71, 26, false); | |
1069 | Buttons_Add( 5, 200, 60, 40, "Stop", 0); | |
1070 | Buttons[0].dark = true; | |
1071 | Buttons_Add( 5, 26, 60, 40, "+1", 1); | |
1072 | Buttons_Add(255, 26, 60, 40, "-1", 2); | |
1073 | /* | |
1074 | * The next key is not a mistake, but we need a key entry which | |
1075 | * will later become the pump key. The keyscan routine will find | |
1076 | * the original key if pressed. | |
1077 | */ | |
1078 | Buttons_Add(255, 26, 60, 40, "-1", 3); | |
1079 | Buttons_Show(); | |
1080 | } | |
1081 | } else { | |
1082 | /* | |
1083 | * Not in prompt mode. | |
1084 | */ | |
1085 | #ifdef CONFIG_TEMP_SENSORS_SIMULATOR | |
1086 | if (Fake_MLT > 12.0) { | |
1087 | if (driver_state->pump_run) | |
1088 | Fake_MLT -= 0.00025 * (Fake_MLT - 12.0); | |
1089 | else | |
1090 | Fake_MLT -= 0.00015 * (Fake_MLT - 12.0); | |
1091 | } | |
1092 | if (xSemaphoreTake(xSemaphoreDS18B20, 10) == pdTRUE) { | |
1093 | ds18b20_state->mlt_temperature = ((int)(Fake_MLT * 16)) / 16.0; | |
1094 | xSemaphoreGive(xSemaphoreDS18B20); | |
1095 | } | |
1096 | #endif | |
1097 | MLT_info(71, 26, true); | |
1098 | if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
1099 | /* | |
1100 | * If the pump safe temperature is reached, add the control button. | |
1101 | * Redefine key number 3 if it is at the position of key 2. | |
1102 | */ | |
1103 | if ((driver_state->mlt_pv < equipment.PumpMaxTemp) && (Buttons[3].x == Buttons[2].x) &&(Buttons[3].y == Buttons[2].y)) { | |
1104 | Buttons_Add(255, 200, 60, 40, "Pomp", 3); | |
1105 | Buttons_Show(); | |
1106 | } | |
1107 | xSemaphoreGive(xSemaphoreDriver); | |
1108 | } | |
1109 | switch (Buttons_Scan()) { | |
1110 | case 1: if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
1111 | if (Main_Screen == MAIN_AUTO_COOLING_H) { | |
1112 | if (driver_state->mlt_sp < 77.0) | |
1113 | driver_state->mlt_sp += 1.0; | |
1114 | } else if (Main_Screen == MAIN_AUTO_COOLING_M) { | |
1115 | if (driver_state->mlt_sp < 66.0) | |
1116 | driver_state->mlt_sp += 1.0; | |
1117 | } else if (Main_Screen == MAIN_AUTO_COOLING_C) { | |
1118 | if (driver_state->mlt_sp < 30.0) | |
1119 | driver_state->mlt_sp += 1.0; | |
1120 | } | |
1121 | xSemaphoreGive(xSemaphoreDriver); | |
1122 | } | |
1123 | break; | |
1124 | ||
1125 | case 0: Buttons_Add( 60, 150, 90, 40, "Stoppen", 4); | |
1126 | Buttons[4].dark = true; | |
1127 | Buttons_Add(170, 150, 90, 40, "Sorry", 5); | |
1128 | Buttons_Show(); | |
1129 | break; | |
1130 | ||
1131 | case 2: if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
1132 | if (Main_Screen == MAIN_AUTO_COOLING_H) { | |
1133 | if (driver_state->mlt_sp > 71.0) | |
1134 | driver_state->mlt_sp -= 1.0; | |
1135 | } else if (Main_Screen == MAIN_AUTO_COOLING_M) { | |
1136 | if (driver_state->mlt_sp > 60.0) | |
1137 | driver_state->mlt_sp -= 1.0; | |
1138 | } else if (Main_Screen == MAIN_AUTO_COOLING_C) { | |
1139 | if (driver_state->mlt_sp > 10.0) | |
1140 | driver_state->mlt_sp -= 1.0; | |
1141 | } | |
1142 | xSemaphoreGive(xSemaphoreDriver); | |
1143 | } | |
1144 | break; | |
1145 | ||
1146 | case 3: if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
1147 | if (driver_state->mlt_pv < equipment.PumpMaxTemp) { | |
1148 | if (driver_state->pump_run) | |
1149 | driver_state->pump_run = 0; | |
1150 | else | |
1151 | driver_state->pump_run = 1; | |
1152 | } else { | |
1153 | driver_state->pump_run = 0; | |
1154 | } | |
1155 | runtime.PumpCooling = driver_state->pump_run; | |
1156 | updateRuntime = true; | |
1157 | xSemaphoreGive(xSemaphoreDriver); | |
1158 | } | |
1159 | break; | |
1160 | ||
1161 | case 4: Main_Screen++; | |
1162 | break; | |
1163 | ||
1164 | case 5: Buttons[4].x = Buttons[5].x = -1; | |
1165 | TFT_fillRect(60, 150, 200, 40, TFT_BLACK); | |
1166 | break; | |
1167 | ||
1168 | default: | |
1169 | break; | |
1170 | } | |
1171 | ||
1172 | if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
1173 | if (! CoolBeep && (driver_state->mlt_pv < (driver_state->mlt_sp + 2.0))) { | |
1174 | SoundPlay(SOUND_Warn); | |
1175 | CoolBeep = true; | |
1176 | } | |
1177 | if (driver_state->mlt_pv <= driver_state->mlt_sp) { | |
1178 | SoundPlay(SOUND_TempReached); | |
1179 | Main_Screen++; | |
42 | 1180 | Sub_Screen = 0; |
0 | 1181 | } |
1182 | xSemaphoreGive(xSemaphoreDriver); | |
1183 | } | |
1184 | } | |
1185 | break; | |
1186 | ||
1187 | case MAIN_AUTO_WHIRLPOOL9: | |
1188 | case MAIN_AUTO_WHIRLPOOL7: | |
1189 | case MAIN_AUTO_WHIRLPOOL6: | |
1190 | case MAIN_AUTO_WHIRLPOOL2: | |
1191 | if (_Prompt) { | |
1192 | ||
1193 | switch (Buttons_Scan()) { | |
1194 | case 0: _Prompt = false; | |
1195 | break; | |
1196 | case 1: if (Main_Screen == MAIN_AUTO_WHIRLPOOL2) { | |
1197 | Main_Screen = MAIN_AUTO_DONE; | |
1198 | } else { | |
1199 | Main_Screen++; | |
1200 | } | |
1201 | Buttons_Clear(); | |
1202 | return true; //goto startover; | |
1203 | break; | |
1204 | default: | |
1205 | break; | |
1206 | } | |
1207 | ||
1208 | if (! _Prompt) { | |
1209 | /* | |
1210 | * Prepare the screen for the actual whirpool. | |
1211 | */ | |
1212 | Buttons_Clear(); | |
1213 | TFT_fillScreen(_bg); | |
42 | 1214 | Sub_Screen = 1; |
1215 | snprintf(msg, 63, "{\"main\":\"%d\",\"sub\":\"%d\",\"timer\":\"\"}", Main_Screen, Sub_Screen); | |
1216 | ws_server_send_text_clients("/ws", msg, strlen(msg)); | |
0 | 1217 | if (Main_Screen == MAIN_AUTO_WHIRLPOOL9) { |
1218 | TimeWhirlPool = recipe.Whirlpool9; | |
1219 | if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
1220 | driver_state->mlt_sp = 93.0; | |
1221 | driver_state->mlt_mode = MLT_MODE_PID; | |
1222 | xSemaphoreGive(xSemaphoreDriver); | |
1223 | } | |
1224 | TopMessage("Whirlpool 88..100"); | |
1225 | } else if (Main_Screen == MAIN_AUTO_WHIRLPOOL7) { | |
1226 | TimeWhirlPool = recipe.Whirlpool7; | |
1227 | if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
1228 | driver_state->mlt_sp = 74.0; | |
1229 | driver_state->mlt_mode = MLT_MODE_PID; | |
1230 | xSemaphoreGive(xSemaphoreDriver); | |
1231 | } | |
1232 | TopMessage("Whirlpool 71..77"); | |
1233 | } else if (Main_Screen == MAIN_AUTO_WHIRLPOOL6) { | |
1234 | TimeWhirlPool = recipe.Whirlpool6; | |
1235 | if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
1236 | driver_state->mlt_sp = 63.0; | |
1237 | driver_state->mlt_mode = MLT_MODE_PID; | |
1238 | xSemaphoreGive(xSemaphoreDriver); | |
1239 | } | |
1240 | TopMessage("Whirlpool 60..66"); | |
1241 | } else { | |
1242 | TimeWhirlPool = recipe.Whirlpool2; | |
1243 | TopMessage("Koude whirlpool"); | |
1244 | } | |
1245 | if (Resume) { | |
1246 | TimeWhirlPool = runtime.StageTimeLeft; | |
1247 | } | |
1248 | ||
1249 | /* | |
1250 | * If the pump is allowed at the current temperature, turn it on. | |
1251 | */ | |
1252 | if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
1253 | driver_state->pump_run = (driver_state->mlt_pv < equipment.PumpMaxTemp) ? 1 : 0; | |
1254 | xSemaphoreGive(xSemaphoreDriver); | |
1255 | } | |
1256 | log_annotation(ANNOTATION_STAGE, "Whirlpool"); | |
1257 | ||
1258 | TimerSet(TimeWhirlPool * 60); | |
1259 | runtime.StageTimeLeft = TimeWhirlPool; | |
1260 | updateRuntime = true; | |
1261 | MLT_info(71, 26, false); | |
1262 | ESP_LOGI(TAG, "Whirlpool %d minutes, sp %4.1f", TimeWhirlPool, driver_state->mlt_sp); | |
1263 | Buttons_Add(255, 120, 60, 40, "+1m", 0); | |
1264 | Buttons_Add( 5, 120, 60, 40, "-1m", 1); | |
42 | 1265 | Buttons_Add(255, 200, 60, 40, "Pomp", 2); |
0 | 1266 | Buttons_Show(); |
1267 | } | |
1268 | } else { | |
1269 | /* | |
1270 | * Not running in prompt mode, do the whirlpool. | |
1271 | */ | |
1272 | if (TimeLeft == 120) { | |
1273 | /* | |
1274 | * Drop the temperature when whirlpool is almost ready. | |
1275 | * If we are lucky the heater element will cool down so | |
1276 | * the next cooling stage will not wast too much energy. | |
1277 | */ | |
1278 | if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
1279 | if (Main_Screen == MAIN_AUTO_WHIRLPOOL9) | |
1280 | driver_state->mlt_sp = 88.0; | |
1281 | if (Main_Screen == MAIN_AUTO_WHIRLPOOL7) | |
1282 | driver_state->mlt_sp = 71.0; | |
1283 | if (Main_Screen == MAIN_AUTO_WHIRLPOOL6) | |
1284 | driver_state->mlt_sp = 60.0; | |
1285 | xSemaphoreGive(xSemaphoreDriver); | |
1286 | } | |
1287 | } | |
1288 | ||
1289 | MLT_info(71, 26, true); | |
1290 | TimerShow(TimeLeft, 65, 122); | |
1291 | switch (Buttons_Scan()) { | |
1292 | case 0: TimeLeft += 60; | |
1293 | break; | |
1294 | case 1: if (TimeLeft > 60) | |
1295 | TimeLeft -= 60; | |
1296 | else | |
1297 | TimeLeft = 0; | |
1298 | break; | |
1299 | case 2: if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
1300 | if (driver_state->mlt_pv < equipment.PumpMaxTemp) { | |
1301 | if (driver_state->pump_run) | |
1302 | driver_state->pump_run = 0; | |
1303 | else | |
1304 | driver_state->pump_run = 1; | |
1305 | } else { | |
1306 | driver_state->pump_run = 0; | |
1307 | } | |
1308 | xSemaphoreGive(xSemaphoreDriver); | |
1309 | } | |
1310 | } | |
1311 | ||
1312 | if (NewMinute) { | |
1313 | runtime.StageTimeLeft = TimeLeft / 60; | |
1314 | updateRuntime = true; | |
1315 | } | |
1316 | ||
1317 | if ((TimeLeft == 0)) { | |
1318 | if (Main_Screen == MAIN_AUTO_WHIRLPOOL9) { | |
1319 | Main_Screen = MAIN_AUTO_COOLING_H; | |
1320 | if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
1321 | driver_state->pump_run = runtime.PumpCooling; | |
1322 | xSemaphoreGive(xSemaphoreDriver); | |
1323 | } | |
1324 | } else if (Main_Screen == MAIN_AUTO_WHIRLPOOL7) { | |
1325 | Main_Screen = MAIN_AUTO_COOLING_M; | |
1326 | if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
1327 | driver_state->pump_run = runtime.PumpCooling; | |
1328 | xSemaphoreGive(xSemaphoreDriver); | |
1329 | } | |
1330 | } else if (Main_Screen == MAIN_AUTO_WHIRLPOOL6) { | |
1331 | Main_Screen = MAIN_AUTO_COOLING_C; | |
1332 | if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
1333 | driver_state->pump_run = runtime.PumpCooling; | |
1334 | xSemaphoreGive(xSemaphoreDriver); | |
1335 | } | |
1336 | } else if (Main_Screen == MAIN_AUTO_WHIRLPOOL2) { | |
1337 | Main_Screen = MAIN_AUTO_DONE; | |
1338 | } | |
1339 | } | |
1340 | } | |
1341 | break; | |
1342 | ||
1343 | case MAIN_AUTO_DONE: | |
1344 | case MAIN_AUTO_ABORT: | |
1345 | if (Buttons_Scan() == 0) | |
1346 | Main_Screen = MAIN_MODE_FREE; | |
1347 | break; | |
1348 | ||
1349 | default: | |
1350 | break; | |
1351 | } | |
1352 | ||
1353 | return false; | |
1354 | } | |
1355 | ||
1356 |