9 #define PIN_SDA (CONFIG_I2C_MASTER_SDA) |
9 #define PIN_SDA (CONFIG_I2C_MASTER_SDA) |
10 #define PIN_SCL (CONFIG_I2C_MASTER_SCL) |
10 #define PIN_SCL (CONFIG_I2C_MASTER_SCL) |
11 #define ROT_ENC_A_GPIO (CONFIG_ROT_ENC_A_GPIO) |
11 #define ROT_ENC_A_GPIO (CONFIG_ROT_ENC_A_GPIO) |
12 #define ROT_ENC_B_GPIO (CONFIG_ROT_ENC_B_GPIO) |
12 #define ROT_ENC_B_GPIO (CONFIG_ROT_ENC_B_GPIO) |
13 #define ROT_ENC_SW_GPIO (CONFIG_ROT_ENC_SW_GPIO) |
13 #define ROT_ENC_SW_GPIO (CONFIG_ROT_ENC_SW_GPIO) |
14 |
14 #define INACTIVITY 480 ///< Time in 250 mSec units. |
15 |
15 |
16 #define ENABLE_HALF_STEPS false ///< Set to true to enable tracking of rotary encoder at half step resolution |
|
17 #define RESET_AT 0 ///< Set to a positive non-zero number to reset the position if this value is exceeded |
16 #define RESET_AT 0 ///< Set to a positive non-zero number to reset the position if this value is exceeded |
18 #define FLIP_DIRECTION false ///< Set to true to reverse the clockwise/counterclockwise sense |
17 |
19 |
18 |
20 |
19 int Main_Loop1 = ML1_INIT; ///< Loop 1 init |
21 int Main_Loop1 = MAIN_LOOP1_INIT; ///< Loop 1 init |
|
22 int Main_Loop2 = -1; ///< Loop 2 invalid |
20 int Main_Loop2 = -1; ///< Loop 2 invalid |
|
21 int New_Loop2 = ML2_DONE; ///< Loop 2 new state |
23 bool System_TimeOk = false; ///< System time status |
22 bool System_TimeOk = false; ///< System time status |
24 time_t now; ///< Current time |
23 time_t now; ///< Current time |
25 struct tm timeinfo; ///< Current time structure |
24 struct tm timeinfo; ///< Current time structure |
26 char strftime_buf[64]; ///< Time buffer |
25 char strftime_buf[64]; ///< Time buffer |
27 static RTC_DATA_ATTR struct timeval sleep_enter_time; |
26 static RTC_DATA_ATTR struct timeval sleep_enter_time; |
28 static TaskHandle_t xTaskDS18B20 = NULL; |
27 static TaskHandle_t xTaskDS18B20 = NULL; |
29 static TaskHandle_t xTaskADC = NULL; |
28 static TaskHandle_t xTaskADC = NULL; |
30 static TaskHandle_t xTaskWifi = NULL; |
29 static TaskHandle_t xTaskWifi = NULL; |
31 static TaskHandle_t xTaskMQTT = NULL; |
30 static TaskHandle_t xTaskMQTT = NULL; |
32 const esp_app_desc_t *app_desc = NULL; |
31 const esp_app_desc_t *app_desc = NULL; ///< Application description |
33 u8g2_t u8g2; ///< A structure which will contain all the data for one display |
32 u8g2_t u8g2; ///< A structure which will contain all the data for one display |
34 |
33 rotary_encoder_info_t rinfo = { 0 }; ///< Rotary encoder record |
|
34 static int PushDuration = 0; ///< Duration of the pushed button |
35 |
35 |
36 extern unit_t units[3]; ///< Pressure test units |
36 extern unit_t units[3]; ///< Pressure test units |
37 extern SemaphoreHandle_t xSemaphoreUnits; ///< Units lock semaphore |
37 extern SemaphoreHandle_t xSemaphoreUnits; ///< Units lock semaphore |
38 extern DS18B20_State *ds18b20_state; ///< DS18B20 state |
38 extern DS18B20_State *ds18b20_state; ///< DS18B20 state |
39 extern SemaphoreHandle_t xSemaphoreDS18B20; ///< DS18B20 lock semaphore |
39 extern SemaphoreHandle_t xSemaphoreDS18B20; ///< DS18B20 lock semaphore |
40 extern ADC_State *adc_state; ///< ADC state |
40 extern ADC_State *adc_state; ///< ADC state |
41 extern SemaphoreHandle_t xSemaphoreADC; ///< ADC lock semaphore |
41 extern SemaphoreHandle_t xSemaphoreADC; ///< ADC lock semaphore |
42 extern int count_pub; |
42 extern int count_pub; ///< Published MQTT messages in transit |
43 |
43 static xQueueHandle gpio_evt_queue = NULL; ///< Rotary pushbutton queue |
44 |
44 static int usertimer = 0; ///< User inactive timeout |
45 void screen_main(float t, float p1, float p2, float p3) |
45 |
|
46 |
|
47 |
|
48 void screen_main() |
46 { |
49 { |
47 char buf[65]; |
50 char buf[65]; |
|
51 int i; |
48 |
52 |
49 u8g2_ClearBuffer(&u8g2); |
53 u8g2_ClearBuffer(&u8g2); |
50 u8g2_DrawHLine(&u8g2, 0, 14, 128); |
54 u8g2_DrawHLine(&u8g2, 0, 14, 128); |
51 u8g2_SetFont(&u8g2, u8g2_font_t0_15_tr); |
55 u8g2_SetFont(&u8g2, u8g2_font_t0_15_tr); |
52 sprintf(buf, "CO2 meter %s", app_desc->version); |
56 sprintf(buf, "CO2 meter %s", app_desc->version); |
53 u8g2_uint_t w = u8g2_GetStrWidth(&u8g2, buf); |
57 u8g2_uint_t w = u8g2_GetStrWidth(&u8g2, buf); |
54 u8g2_DrawStr(&u8g2, (128 - w) / 2,12, buf); |
58 u8g2_DrawStr(&u8g2, (128 - w) / 2,12, buf); |
55 |
59 |
56 u8g2_SetFont(&u8g2, u8g2_font_t0_22b_tf); |
60 if (xSemaphoreTake(xSemaphoreUnits, 25) == pdTRUE) { |
57 sprintf(buf, "%.1f °C", t); |
61 |
58 w = u8g2_GetUTF8Width(&u8g2, buf); |
62 u8g2_SetFont(&u8g2, u8g2_font_t0_22b_tf); |
59 u8g2_DrawUTF8(&u8g2, (128 - w) / 2,40, buf); |
63 sprintf(buf, "%.1f °C", units[0].temperature / 1000.0); |
60 u8g2_SetFont(&u8g2, u8g2_font_t0_18b_tf); |
64 w = u8g2_GetUTF8Width(&u8g2, buf); |
61 |
65 u8g2_DrawUTF8(&u8g2, (128 - w) / 2,40, buf); |
62 sprintf(buf, "%.1f", p1); |
66 u8g2_SetFont(&u8g2, u8g2_font_t0_18b_tf); |
63 w = u8g2_GetUTF8Width(&u8g2, buf); |
67 |
64 u8g2_DrawUTF8(&u8g2, ((42 - w) / 2),63, buf); |
68 for (i = 0; i < 3; i++) { |
65 |
69 sprintf(buf, "%.1f", units[i].pressure / 1000.0); |
66 sprintf(buf, "%.1f", p2); |
70 w = u8g2_GetUTF8Width(&u8g2, buf); |
67 w = u8g2_GetUTF8Width(&u8g2, buf); |
71 u8g2_DrawUTF8(&u8g2, ((42 - w) / 2) + i * 43,63, buf); |
68 u8g2_DrawUTF8(&u8g2, ((42 - w) / 2) + 43,63, buf); |
72 } |
69 |
73 xSemaphoreGive(xSemaphoreUnits); |
70 sprintf(buf, "%.1f", p3); |
74 } |
71 w = u8g2_GetUTF8Width(&u8g2, buf); |
|
72 u8g2_DrawUTF8(&u8g2, ((42 - w) / 2) + 86,63, buf); |
|
73 |
|
74 u8g2_SendBuffer(&u8g2); |
75 u8g2_SendBuffer(&u8g2); |
75 u8g2_SetPowerSave(&u8g2, 0); // wake up display |
76 u8g2_SetPowerSave(&u8g2, 0); // wake up display |
|
77 } |
|
78 |
|
79 |
|
80 |
|
81 void screen_unit(int no) |
|
82 { |
|
83 char buf[65]; |
|
84 |
|
85 u8g2_ClearBuffer(&u8g2); |
|
86 u8g2_DrawHLine(&u8g2, 0, 14, 128); |
|
87 u8g2_SetFont(&u8g2, u8g2_font_t0_15_tr); |
|
88 sprintf(buf, "Unit %d", no + 1); |
|
89 u8g2_uint_t w = u8g2_GetStrWidth(&u8g2, buf); |
|
90 u8g2_DrawStr(&u8g2, (128 - w) / 2,12, buf); |
|
91 |
|
92 if (xSemaphoreTake(xSemaphoreUnits, 25) == pdTRUE) { |
|
93 |
|
94 u8g2_SetFont(&u8g2, u8g2_font_t0_22b_tf); |
|
95 sprintf(buf, "%.1f °C", units[no].temperature / 1000.0); |
|
96 w = u8g2_GetUTF8Width(&u8g2, buf); |
|
97 u8g2_DrawUTF8(&u8g2, (128 - w) / 2,40, buf); |
|
98 // u8g2_SetFont(&u8g2, u8g2_font_t0_18b_tf); |
|
99 |
|
100 sprintf(buf, "%.2f bar", units[no].pressure / 1000.0); |
|
101 w = u8g2_GetUTF8Width(&u8g2, buf); |
|
102 u8g2_DrawUTF8(&u8g2, (128 - w) / 2,63, buf); |
|
103 |
|
104 xSemaphoreGive(xSemaphoreUnits); |
|
105 } |
|
106 u8g2_SendBuffer(&u8g2); |
|
107 u8g2_SetPowerSave(&u8g2, 0); // wake up display |
|
108 } |
|
109 |
|
110 |
|
111 |
|
112 void screen_unit_setup(int no, int sub) |
|
113 { |
|
114 char buf[65]; |
|
115 |
|
116 u8g2_ClearBuffer(&u8g2); |
|
117 u8g2_DrawHLine(&u8g2, 0, 14, 128); |
|
118 u8g2_SetFont(&u8g2, u8g2_font_t0_15_tr); |
|
119 sprintf(buf, "Unit %d setup", no + 1); |
|
120 u8g2_uint_t w = u8g2_GetStrWidth(&u8g2, buf); |
|
121 u8g2_DrawStr(&u8g2, (128 - w) / 2,12, buf); |
|
122 |
|
123 if (sub == 0) |
|
124 u8g2_SetFont(&u8g2, u8g2_font_t0_15b_tr); |
|
125 else |
|
126 u8g2_SetFont(&u8g2, u8g2_font_t0_15_tr); |
|
127 sprintf(buf, "Mode %s", units[no].mode ? "ON":"OFF"); |
|
128 u8g2_DrawStr(&u8g2,2,28, buf); |
|
129 |
|
130 if (sub == 1) |
|
131 u8g2_SetFont(&u8g2, u8g2_font_t0_15b_tr); |
|
132 else |
|
133 u8g2_SetFont(&u8g2, u8g2_font_t0_15_tr); |
|
134 sprintf(buf, "Calibrate"); |
|
135 u8g2_DrawStr(&u8g2,2,40, buf); |
|
136 |
|
137 if (sub == 2) |
|
138 u8g2_SetFont(&u8g2, u8g2_font_t0_15b_tr); |
|
139 else |
|
140 u8g2_SetFont(&u8g2, u8g2_font_t0_15_tr); |
|
141 sprintf(buf, "T.sensor "); |
|
142 u8g2_DrawStr(&u8g2,2,52, buf); |
|
143 |
|
144 if (sub == 3) |
|
145 u8g2_SetFont(&u8g2, u8g2_font_t0_15b_tr); |
|
146 else |
|
147 u8g2_SetFont(&u8g2, u8g2_font_t0_15_tr); |
|
148 sprintf(buf, "Return"); |
|
149 u8g2_DrawStr(&u8g2,2,64, buf); |
|
150 |
|
151 u8g2_SendBuffer(&u8g2); |
|
152 u8g2_SetPowerSave(&u8g2, 0); |
76 } |
153 } |
77 |
154 |
78 |
155 |
79 |
156 |
80 void screen_fatal(char *e1, char *e2) |
157 void screen_fatal(char *e1, char *e2) |
82 u8g2_SetFont(&u8g2, u8g2_font_t0_15_tr); |
159 u8g2_SetFont(&u8g2, u8g2_font_t0_15_tr); |
83 u8g2_DrawStr(&u8g2,2,12,e1); |
160 u8g2_DrawStr(&u8g2,2,12,e1); |
84 u8g2_DrawStr(&u8g2,2,24,e2); |
161 u8g2_DrawStr(&u8g2,2,24,e2); |
85 u8g2_SendBuffer(&u8g2); |
162 u8g2_SendBuffer(&u8g2); |
86 u8g2_SetPowerSave(&u8g2, 0); |
163 u8g2_SetPowerSave(&u8g2, 0); |
87 |
|
88 } |
164 } |
89 |
165 |
|
166 |
|
167 |
|
168 /* |
|
169 * Interrupt service routine for the rotary pushbutton. |
|
170 */ |
|
171 static void IRAM_ATTR gpio_isr_handler(void* arg) |
|
172 { |
|
173 uint32_t gpio_num = (uint32_t) arg; |
|
174 xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL); |
|
175 } |
|
176 |
|
177 |
|
178 |
|
179 /* |
|
180 * GPIO queue task. See if there is a rotary pushbutton event in the queue. |
|
181 */ |
|
182 static void gpio_task(void* arg) |
|
183 { |
|
184 uint32_t io_num; |
|
185 static int64_t pushed = 0; |
|
186 |
|
187 for(;;) { |
|
188 if (xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) { |
|
189 if (io_num == ROT_ENC_SW_GPIO) { |
|
190 if (gpio_get_level(io_num) == 0) { |
|
191 pushed = esp_timer_get_time(); |
|
192 PushDuration = 0; |
|
193 } else if (gpio_get_level(io_num) == 1) { |
|
194 PushDuration = (esp_timer_get_time() - pushed) / 1000; |
|
195 ESP_LOGI(TAG, "GPIO rotary button intr, val: %d time: %d", gpio_get_level(io_num), PushDuration); |
|
196 } |
|
197 } else { |
|
198 ESP_LOGE(TAG, "GPIO[%d] unknown intr, val: %d", io_num, gpio_get_level(io_num)); |
|
199 } |
|
200 usertimer = INACTIVITY; |
|
201 } |
|
202 } |
|
203 } |
|
204 |
|
205 |
|
206 |
|
207 /* |
|
208 * Select new menu number on a postitive or negative rotary position. |
|
209 * Then reset the rotary position. |
|
210 */ |
|
211 static void rotate_to_menu(rotary_encoder_position_t pos, int next_menu, int prev_menu) |
|
212 { |
|
213 if (pos > 0) |
|
214 New_Loop2 = next_menu; |
|
215 else if (pos < 0) |
|
216 New_Loop2 = prev_menu; |
|
217 ESP_ERROR_CHECK(rotary_encoder_reset(&rinfo)); |
|
218 } |
90 |
219 |
91 |
220 |
92 |
221 |
93 void app_main() |
222 void app_main() |
94 { |
223 { |
95 struct timeval now; |
224 struct timeval now; |
96 gettimeofday(&now, NULL); |
225 gettimeofday(&now, NULL); |
97 int sleep_time_ms = (now.tv_sec - sleep_enter_time.tv_sec) * 1000 + (now.tv_usec - sleep_enter_time.tv_usec) / 1000; |
226 int sleep_time_ms = (now.tv_sec - sleep_enter_time.tv_sec) * 1000 + (now.tv_usec - sleep_enter_time.tv_usec) / 1000; |
98 int New_Loop2 = MAIN_LOOP2_INIT; |
|
99 esp_err_t ret; |
227 esp_err_t ret; |
100 |
228 |
101 Main_Loop1 = MAIN_LOOP1_INIT; |
229 Main_Loop1 = ML1_INIT; |
102 Main_Loop2 = -1; |
230 Main_Loop2 = -1; |
103 |
231 |
104 switch (esp_sleep_get_wakeup_cause()) { |
232 switch (esp_sleep_get_wakeup_cause()) { |
105 case ESP_SLEEP_WAKEUP_EXT1: { |
233 case ESP_SLEEP_WAKEUP_EXT1: { |
106 uint64_t wakeup_pin_mask = esp_sleep_get_ext1_wakeup_status(); |
234 ESP_LOGI(TAG, "Starting from deep sleep, Rotary switch pressed"); |
107 if (wakeup_pin_mask != 0) { |
235 New_Loop2 = ML2_INIT; |
108 int pin = __builtin_ffsll(wakeup_pin_mask) - 1; |
|
109 printf("Wake up from GPIO %d\n", pin); |
|
110 } else { |
|
111 printf("Wake up from GPIO\n"); |
|
112 } |
|
113 break; |
236 break; |
114 } |
237 } |
115 case ESP_SLEEP_WAKEUP_TIMER: { |
238 case ESP_SLEEP_WAKEUP_TIMER: { |
116 ESP_LOGI(TAG, "Starting from deep sleep, timer wakeup after %dms", sleep_time_ms); |
239 ESP_LOGI(TAG, "Starting from deep sleep, timer wakeup after %dms", sleep_time_ms); |
117 break; |
240 break; |
246 * Setup the Rotary Encoder. |
366 * Setup the Rotary Encoder. |
247 * esp32-rotary-encoder requires that the GPIO ISR service is |
367 * esp32-rotary-encoder requires that the GPIO ISR service is |
248 * installed before calling rotary_encoder_register() |
368 * installed before calling rotary_encoder_register() |
249 */ |
369 */ |
250 ESP_ERROR_CHECK(gpio_install_isr_service(0)); |
370 ESP_ERROR_CHECK(gpio_install_isr_service(0)); |
251 rotary_encoder_info_t rinfo = { 0 }; |
|
252 ESP_ERROR_CHECK(rotary_encoder_init(&rinfo, ROT_ENC_A_GPIO, ROT_ENC_B_GPIO)); |
371 ESP_ERROR_CHECK(rotary_encoder_init(&rinfo, ROT_ENC_A_GPIO, ROT_ENC_B_GPIO)); |
253 // ESP_ERROR_CHECK(rotary_encoder_enable_half_steps(&rinfo, ENABLE_HALF_STEPS)); |
372 ESP_ERROR_CHECK(rotary_encoder_enable_half_steps(&rinfo, false)); |
254 #ifdef FLIP_DIRECTION |
373 |
255 // ESP_ERROR_CHECK(rotary_encoder_flip_direction(&rinfo)); |
374 gpio_config_t io_conf; |
256 #endif |
375 io_conf.intr_type = GPIO_PIN_INTR_ANYEDGE; |
|
376 io_conf.pin_bit_mask = (1ULL << ROT_ENC_SW_GPIO); |
|
377 io_conf.mode = GPIO_MODE_INPUT; |
|
378 gpio_config(&io_conf); |
|
379 |
|
380 gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t)); |
|
381 xTaskCreate(gpio_task, "gpio_task", 2048, NULL, 10, NULL); |
|
382 |
|
383 gpio_isr_handler_add(ROT_ENC_SW_GPIO, gpio_isr_handler, (void*) ROT_ENC_SW_GPIO); |
257 |
384 |
258 // Create a queue for events from the rotary encoder driver. |
385 // Create a queue for events from the rotary encoder driver. |
259 // Tasks can read from this queue to receive up to date position information. |
386 // Tasks can read from this queue to receive up to date position information. |
260 // QueueHandle_t event_queue = rotary_encoder_create_queue(); |
387 QueueHandle_t event_queue = rotary_encoder_create_queue(); |
261 // ESP_ERROR_CHECK(rotary_encoder_set_queue(&rinfo, event_queue)); |
388 ESP_ERROR_CHECK(rotary_encoder_set_queue(&rinfo, event_queue)); |
262 |
|
263 |
389 |
264 /* |
390 /* |
265 * Main application loop. |
391 * Main application loop. |
266 */ |
392 */ |
267 while (1) { |
393 while (1) { |
268 |
394 |
269 ESP_LOGI(TAG, "Entered app loop"); |
395 ESP_LOGI(TAG, "Entered app loop"); |
|
396 rotary_encoder_event_t event = { 0 }; |
|
397 int sub = 0; |
270 |
398 |
271 /* Measure process or user input via rotary switch */ |
399 /* Measure process or user input via rotary switch */ |
272 while (1) { |
400 while (1) { |
273 switch (Main_Loop1) { |
401 switch (Main_Loop1) { |
274 case MAIN_LOOP1_INIT: |
402 case ML1_INIT: |
275 ESP_LOGI(TAG, "Loop timer: Init"); |
403 ESP_LOGI(TAG, "Loop timer: Init"); |
276 // If configured do MAIN_LOOP1_CONNECT |
404 // If configured do ML1_CONNECT |
277 Main_Loop1 = MAIN_LOOP1_CONNECT; |
405 Main_Loop1 = ML1_CONNECT; |
278 requestWiFi_system(true); |
406 requestWiFi_system(true); |
279 request_ds18b20(); |
407 request_ds18b20(); |
280 request_adc(); |
408 request_adc(); |
281 break; |
409 break; |
282 |
410 |
283 case MAIN_LOOP1_CONNECT: |
411 case ML1_CONNECT: |
284 if (ready_WiFi()) |
412 if (ready_WiFi()) |
285 Main_Loop1 = MAIN_LOOP1_MQTT_CONNECT; |
413 Main_Loop1 = ML1_MQTT_CONNECT; |
286 break; |
414 break; |
287 |
415 |
288 case MAIN_LOOP1_MQTT_CONNECT: |
416 case ML1_MQTT_CONNECT: |
289 if (ready_ds18b20() && ready_adc()) { |
417 if (ready_ds18b20() && ready_adc()) { |
290 connect_mqtt(true); |
418 connect_mqtt(true); |
291 Main_Loop1 = MAIN_LOOP1_WAITCON; |
419 Main_Loop1 = ML1_WAITCON; |
292 ESP_LOGI(TAG, "Loop timer: Wait MQTT"); |
420 ESP_LOGI(TAG, "Loop timer: Wait MQTT"); |
293 |
421 |
294 /* Get global temperature, use for all units. */ |
422 /* Get global temperature, use for all units. */ |
295 uint32_t temp = 0; |
423 uint32_t temp = 0; |
296 int state = 0; |
424 int state = 0; |
297 char rom_code[17]; |
425 char rom_code[17]; |
298 float t = 0, p1, p2, p3; |
|
299 if (xSemaphoreTake(xSemaphoreDS18B20, 10) == pdTRUE) { |
426 if (xSemaphoreTake(xSemaphoreDS18B20, 10) == pdTRUE) { |
300 temp = (ds18b20_state->sensor[0].temperature * 1000); |
427 temp = (ds18b20_state->sensor[0].temperature * 1000); |
301 state = (ds18b20_state->sensor[0].error == 0) ? 0:1; |
428 state = (ds18b20_state->sensor[0].error == 0) ? 0:1; |
302 strncpy(rom_code, ds18b20_state->sensor[0].rom_code, 17); |
429 strncpy(rom_code, ds18b20_state->sensor[0].rom_code, 17); |
303 rom_code[16] = '\0'; |
430 rom_code[16] = '\0'; |
304 xSemaphoreGive(xSemaphoreDS18B20); |
431 xSemaphoreGive(xSemaphoreDS18B20); |
305 } |
432 } |
306 t = temp / 1000.0; |
|
307 |
433 |
308 /* Copy measured data and calculate results */ |
434 /* Copy measured data and calculate results */ |
309 if (xSemaphoreTake(xSemaphoreUnits, 25) == pdTRUE) { |
435 if (xSemaphoreTake(xSemaphoreUnits, 25) == pdTRUE) { |
310 for (int i = 0; i < 3; i++) { |
436 for (int i = 0; i < 3; i++) { |
311 if (i == 0) |
|
312 units[i].mode = 1; |
|
313 units[i].temperature = temp; |
437 units[i].temperature = temp; |
314 units[i].temperature_state = state; |
438 units[i].temperature_state = state; |
315 units[i].alarm = 0; |
439 units[i].alarm = 0; |
316 if (state) |
440 if (state) |
317 units[i].alarm |= ALARM_SYS_TEMPERATURE & ALARM_UNIT_TEMPERATURE; |
441 units[i].alarm |= ALARM_SYS_TEMPERATURE & ALARM_UNIT_TEMPERATURE; |
325 units[i].alarm |= ALARM_UNIT_PRESSURE; |
449 units[i].alarm |= ALARM_UNIT_PRESSURE; |
326 int P = (units[i].pressure_voltage / (adc_state->Batt_voltage / 1000) - units[i].pressure_zero) * 14; // in bar |
450 int P = (units[i].pressure_voltage / (adc_state->Batt_voltage / 1000) - units[i].pressure_zero) * 14; // in bar |
327 if (P < 0) |
451 if (P < 0) |
328 P = 0; |
452 P = 0; |
329 units[i].pressure = P; |
453 units[i].pressure = P; |
330 if (i == 0) |
|
331 p1 = P / 1000.0; |
|
332 else if (i == 1) |
|
333 p2 = P / 1000.0; |
|
334 else if (i == 2) |
|
335 p3 = P / 1000.0; |
|
336 printf("%d volt: %d batt: %d scale: %d bar: %d\n", i, units[i].pressure_voltage, adc_state->Batt_voltage, |
454 printf("%d volt: %d batt: %d scale: %d bar: %d\n", i, units[i].pressure_voltage, adc_state->Batt_voltage, |
337 units[i].pressure_voltage / (adc_state->Batt_voltage / 1000) - units[i].pressure_zero, P); |
455 units[i].pressure_voltage / (adc_state->Batt_voltage / 1000) - units[i].pressure_zero, P); |
338 // Moet die echt op 5 volt? |
456 // Moet die echt op 5 volt? |
339 // Verbruik 10 mA |
457 // Verbruik 10 mA |
340 // Setup tijd max 2 mS |
458 // Setup tijd max 2 mS |
341 xSemaphoreGive(xSemaphoreADC); |
459 xSemaphoreGive(xSemaphoreADC); |
342 } |
460 } |
343 } |
461 } |
344 write_units(); |
462 write_units(); |
345 xSemaphoreGive(xSemaphoreUnits); |
463 xSemaphoreGive(xSemaphoreUnits); |
346 screen_main(t, p1, p2, p3); |
464 switch (Main_Loop2) { |
|
465 case ML2_USER: screen_main(); break; |
|
466 case ML2_UNIT1: screen_unit(0); break; |
|
467 case ML2_UNIT2: screen_unit(1); break; |
|
468 case ML2_UNIT3: screen_unit(2); break; |
|
469 } |
347 } |
470 } |
348 } |
471 } |
349 break; |
472 break; |
350 |
473 |
351 case MAIN_LOOP1_WAITCON: |
474 case ML1_WAITCON: |
352 if (ready_mqtt()) |
475 if (ready_mqtt()) |
353 Main_Loop1 = MAIN_LOOP1_SEND; |
476 Main_Loop1 = ML1_SEND; |
354 break; |
477 break; |
355 |
478 |
356 case MAIN_LOOP1_SEND: |
479 case ML1_SEND: |
357 ESP_LOGI(TAG, "Loop timer: Send MQTT"); |
480 ESP_LOGI(TAG, "Loop timer: Send MQTT"); |
358 publishNode(); |
481 publishNode(); |
359 publishUnits(); |
482 publishUnits(); |
360 publishLogs(); |
483 publishLogs(); |
361 Main_Loop1 = MAIN_LOOP1_WAITACK; |
484 Main_Loop1 = ML1_WAITACK; |
362 break; |
485 break; |
363 |
486 |
364 case MAIN_LOOP1_WAITACK: |
487 case ML1_WAITACK: |
365 if (count_pub == 0) // Wait until all published messages are sent. |
488 if (count_pub == 0) // Wait until all published messages are sent. |
366 Main_Loop1 = MAIN_LOOP1_MQTT_DISCONNECT; |
489 Main_Loop1 = ML1_MQTT_DISCONNECT; |
367 break; |
490 break; |
368 |
491 |
369 case MAIN_LOOP1_MQTT_DISCONNECT: |
492 case ML1_MQTT_DISCONNECT: |
370 ESP_LOGI(TAG, "Loop timer: Disconnect MQTT"); |
493 ESP_LOGI(TAG, "Loop timer: Disconnect MQTT"); |
371 connect_mqtt(false); // Doesn't really disconnect. |
494 connect_mqtt(false); // Doesn't really disconnect. |
372 Main_Loop1 = MAIN_LOOP1_DISCONNECT; |
495 Main_Loop1 = ML1_DISCONNECT; |
373 break; |
496 break; |
374 |
497 |
375 case MAIN_LOOP1_DISCONNECT: |
498 case ML1_DISCONNECT: |
376 if (! ready_mqtt()) { |
499 if (! ready_mqtt()) { |
377 ESP_LOGI(TAG, "Loop timer: WiFi off"); |
500 ESP_LOGI(TAG, "Loop timer: WiFi off"); |
378 requestWiFi_system(false); |
501 requestWiFi_system(false); |
379 Main_Loop1 = MAIN_LOOP1_WIFI_OFF; |
502 Main_Loop1 = ML1_WIFI_OFF; |
380 } |
503 } |
381 break; |
504 break; |
382 |
505 |
383 case MAIN_LOOP1_WIFI_OFF: |
506 case ML1_WIFI_OFF: |
384 if (! ready_WiFi()) { |
507 if (! ready_WiFi()) { |
385 ESP_LOGI(TAG, "Loop timer: Done"); |
508 ESP_LOGI(TAG, "Loop timer: Done"); |
386 Main_Loop1 = MAIN_LOOP1_DONE; |
509 Main_Loop1 = ML1_DONE; |
387 } |
510 } |
388 break; |
511 break; |
389 |
512 |
390 case MAIN_LOOP1_DONE: |
513 case ML1_DONE: |
391 break; |
514 break; |
392 } |
515 } |
393 |
516 |
394 /* |
517 /* |
395 * One time actions |
518 * One time actions |
397 if (New_Loop2 != Main_Loop2) { |
520 if (New_Loop2 != Main_Loop2) { |
398 |
521 |
399 Main_Loop2 = New_Loop2; |
522 Main_Loop2 = New_Loop2; |
400 |
523 |
401 switch (Main_Loop2) { |
524 switch (Main_Loop2) { |
402 case MAIN_LOOP2_INIT: |
525 case ML2_INIT: |
403 ESP_LOGI(TAG, "Loop user: Init"); |
526 ESP_LOGI(TAG, "Loop user: Init"); |
404 // u8g2_SetPowerSave(&u8g2, 0); // wake up display |
527 // u8g2_SetPowerSave(&u8g2, 0); // wake up display |
405 // u8g2_ClearBuffer(&u8g2); |
528 // u8g2_ClearBuffer(&u8g2); |
406 // New_Loop2 = MAIN_LOOP2_INACTIVE; |
529 New_Loop2 = ML2_USER; |
407 New_Loop2 = MAIN_LOOP2_DONE; |
530 usertimer = INACTIVITY; |
408 break; |
531 break; |
409 |
532 |
410 case MAIN_LOOP2_INACTIVE: |
533 case ML2_USER: |
411 // u8g2_SetPowerSave(&u8g2, 1); // powersave display |
534 ESP_LOGI(TAG, "Loop user: User mainmenu"); |
412 New_Loop2 = MAIN_LOOP2_DONE; |
535 screen_main(); |
|
536 break; |
|
537 |
|
538 case ML2_UNIT1: |
|
539 case ML2_UNIT2: |
|
540 case ML2_UNIT3: |
|
541 ESP_LOGI(TAG, "Loop user: Unit %d", Main_Loop2 - ML2_UNIT1); |
|
542 screen_unit(Main_Loop2 - ML2_UNIT1); |
|
543 break; |
|
544 |
|
545 case ML2_SET_WIFI: |
|
546 ESP_LOGI(TAG, "Loop user: Setup WiFi"); |
|
547 break; |
|
548 |
|
549 case ML2_SET_NETWORK: |
|
550 ESP_LOGI(TAG, "Loop user: Setup Network"); |
|
551 break; |
|
552 |
|
553 case ML2_SET_MQTT: |
|
554 ESP_LOGI(TAG, "Loop user: Setup MQTT"); |
|
555 break; |
|
556 |
|
557 case ML2_UPDATE: |
|
558 ESP_LOGI(TAG, "Loop user: Update"); |
|
559 break; |
|
560 |
|
561 case ML2_SETUP_UNIT1: |
|
562 case ML2_SETUP_UNIT2: |
|
563 case ML2_SETUP_UNIT3: |
|
564 ESP_LOGI(TAG, "Loop user: Setup Unit %d", Main_Loop2 - ML2_SETUP_UNIT1); |
|
565 sub = 0; |
|
566 screen_unit_setup(Main_Loop2 - ML2_SETUP_UNIT1, sub); |
|
567 break; |
|
568 |
|
569 case ML2_INACTIVE: |
|
570 ESP_LOGI(TAG, "Loop user: Inactive"); |
|
571 u8g2_SetPowerSave(&u8g2, 1); // powersave display |
|
572 New_Loop2 = ML2_DONE; |
413 break; |
573 break; |
414 |
574 |
415 default: |
575 default: |
416 break; |
576 break; |
417 } |
577 } |
418 } |
578 } |
419 |
579 |
420 /* |
580 /* |
421 * Action process. |
581 * Main user processing. Handle the rotary encoder and pushbutton. |
422 */ |
582 */ |
423 switch (Main_Loop2) { |
583 if (Main_Loop2 < ML2_INACTIVE) { |
424 // If wakeup from GPIO -- state machine 2 |
584 // If wakeup from GPIO -- state machine 2 |
425 // Init OLED |
585 // Init OLED |
426 // If not configured, start configure |
586 // If not configured, start configure |
427 // If configured select first unit |
587 // If configured select first unit |
428 // New rotate position, set screen, reset waittimer |
588 // New rotate position, set screen, reset waittimer |
429 // Handle screen (first is show measured values) |
589 // Handle screen (first is show measured values) |
441 |
601 |
442 // Sensors menu: Assignments, turn to choose one. |
602 // Sensors menu: Assignments, turn to choose one. |
443 // Sensors setup menu: DS18B20 addr Press is assign |
603 // Sensors setup menu: DS18B20 addr Press is assign |
444 // DS18B20 addr |
604 // DS18B20 addr |
445 |
605 |
|
606 if (xQueueReceive(event_queue, &event, 250 / portTICK_PERIOD_MS) == pdTRUE) { |
|
607 usertimer = INACTIVITY; |
|
608 switch (Main_Loop2) { |
|
609 case ML2_USER: rotate_to_menu(event.state.position, ML2_UNIT1, ML2_USER); break; |
|
610 case ML2_UNIT1: rotate_to_menu(event.state.position, ML2_UNIT2, ML2_USER); break; |
|
611 case ML2_UNIT2: rotate_to_menu(event.state.position, ML2_UNIT3, ML2_UNIT1); break; |
|
612 case ML2_UNIT3: rotate_to_menu(event.state.position, ML2_SET_WIFI, ML2_UNIT2); break; |
|
613 case ML2_SET_WIFI: rotate_to_menu(event.state.position, ML2_SET_NETWORK, ML2_UNIT3); break; |
|
614 case ML2_SET_NETWORK: rotate_to_menu(event.state.position, ML2_SET_MQTT, ML2_SET_WIFI); break; |
|
615 case ML2_SET_MQTT: rotate_to_menu(event.state.position, ML2_UPDATE, ML2_SET_NETWORK); break; |
|
616 case ML2_UPDATE: rotate_to_menu(event.state.position, ML2_UPDATE, ML2_SET_MQTT); break; |
|
617 case ML2_SETUP_UNIT1: |
|
618 case ML2_SETUP_UNIT2: |
|
619 case ML2_SETUP_UNIT3: if (event.state.position > 0) { |
|
620 if (sub < 3) { |
|
621 sub++; |
|
622 screen_unit_setup(Main_Loop2 - ML2_SETUP_UNIT1, sub); |
|
623 } |
|
624 ESP_ERROR_CHECK(rotary_encoder_reset(&rinfo)); |
|
625 } else if (event.state.position < 0) { |
|
626 if (sub > 0) { |
|
627 sub--; |
|
628 screen_unit_setup(Main_Loop2 - ML2_SETUP_UNIT1, sub); |
|
629 } |
|
630 ESP_ERROR_CHECK(rotary_encoder_reset(&rinfo)); |
|
631 } |
|
632 break; |
|
633 default: |
|
634 ESP_LOGI(TAG, "Event: position %d, direction %s", event.state.position, |
|
635 event.state.direction ? (event.state.direction == ROTARY_ENCODER_DIRECTION_CLOCKWISE ? "CW":"CCW"):"NOT_SET"); |
|
636 } |
|
637 } else { |
|
638 // Poll current position and direction |
|
639 rotary_encoder_state_t state = { 0 }; |
|
640 ESP_ERROR_CHECK(rotary_encoder_get_state(&rinfo, &state)); |
|
641 |
|
642 // ESP_LOGI(TAG, "Poll: position %d, direction %s timer %d", state.position, |
|
643 // state.direction ? (state.direction == ROTARY_ENCODER_DIRECTION_CLOCKWISE ? "CW" : "CCW") : "NOT_SET", usertimer); |
|
644 if (usertimer) |
|
645 usertimer--; |
|
646 else |
|
647 New_Loop2 = ML2_INACTIVE; |
|
648 |
|
649 // Reset the device |
|
650 // if (RESET_AT && (state.position >= RESET_AT || state.position <= -RESET_AT)) { |
|
651 // ESP_LOGI(TAG, "Reset"); |
|
652 // ESP_ERROR_CHECK(rotary_encoder_reset(&rinfo)); |
|
653 // } |
|
654 } |
|
655 } |
|
656 |
|
657 switch (Main_Loop2) { |
446 // Break if all done and inactive. |
658 // Break if all done and inactive. |
|
659 case ML2_UNIT1: |
|
660 case ML2_UNIT2: |
|
661 case ML2_UNIT3: |
|
662 if (PushDuration) { |
|
663 New_Loop2 = ML2_SETUP_UNIT1 + (Main_Loop2 - ML2_UNIT1); |
|
664 PushDuration = 0; |
|
665 } |
|
666 break; |
|
667 |
|
668 case ML2_SETUP_UNIT1: |
|
669 case ML2_SETUP_UNIT2: |
|
670 case ML2_SETUP_UNIT3: |
|
671 if (PushDuration) { |
|
672 if (sub == 0) { |
|
673 if (xSemaphoreTake(xSemaphoreUnits, 25) == pdTRUE) { |
|
674 if (units[Main_Loop2 - ML2_SETUP_UNIT1].mode) |
|
675 units[Main_Loop2 - ML2_SETUP_UNIT1].mode = 0; |
|
676 else |
|
677 units[Main_Loop2 - ML2_SETUP_UNIT1].mode = 1; |
|
678 write_units(); |
|
679 xSemaphoreGive(xSemaphoreUnits); |
|
680 } |
|
681 screen_unit_setup(Main_Loop2 - ML2_SETUP_UNIT1, sub); |
|
682 if (Main_Loop1 == ML1_DONE) |
|
683 Main_Loop1 = ML1_INIT; |
|
684 } |
|
685 if (sub == 3) |
|
686 New_Loop2 = ML2_UNIT1 + (Main_Loop2 - ML2_SETUP_UNIT1); |
|
687 printf("sub %d new %d\n", sub, New_Loop2); |
|
688 PushDuration = 0; |
|
689 } |
|
690 break; |
|
691 |
447 default: |
692 default: |
448 break; |
693 break; |
449 } |
694 } |
450 |
695 |
451 if (Main_Loop1 == MAIN_LOOP1_DONE && Main_Loop2 == MAIN_LOOP2_DONE) |
696 if (Main_Loop1 == ML1_DONE && Main_Loop2 == ML2_DONE) |
452 break; |
697 break; |
453 |
698 |
454 vTaskDelay(10 / portTICK_PERIOD_MS); |
699 vTaskDelay(10 / portTICK_PERIOD_MS); |
455 } |
700 } |
456 |
701 |