main/co2meter.c

changeset 16
e38ffa806e84
parent 14
deaca7606e23
child 17
f9eca4a55911
equal deleted inserted replaced
15:83314e7b1b4a 16:e38ffa806e84
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;
122 } 245 }
123 246
124 const int wakeup_time_sec = 55; 247 const int wakeup_time_sec = 55;
125 ESP_LOGI(TAG, "Enabling timer wakeup, %ds", wakeup_time_sec); 248 ESP_LOGI(TAG, "Enabling timer wakeup, %ds", wakeup_time_sec);
126 esp_sleep_enable_timer_wakeup(wakeup_time_sec * 1000000); 249 esp_sleep_enable_timer_wakeup(wakeup_time_sec * 1000000);
127 250 const uint64_t ext_wakeup_pin_1_mask = 1ULL << ROT_ENC_SW_GPIO;
128 // const int ext_wakeup_pin_1 = ROT_ENC_SW_GPIO; // 25 in example, redefine to rotary name. 251
129 // const uint64_t ext_wakeup_pin_1_mask = 1ULL << ext_wakeup_pin_1; 252 ESP_LOGI(TAG, "Enabling EXT1 wakeup on pin GPIO%d", ROT_ENC_SW_GPIO);
130 253 esp_sleep_enable_ext1_wakeup(ext_wakeup_pin_1_mask, ESP_EXT1_WAKEUP_ALL_LOW);
131 // printf("Enabling EXT1 wakeup on pins GPIO%d\n", ext_wakeup_pin_1);
132 // esp_sleep_enable_ext1_wakeup(ext_wakeup_pin_1_mask, ESP_EXT1_WAKEUP_ANY_HIGH); // TODO: what is the logic of the rotary button.
133 254
134 // Isolate GPIO12 pin from external circuits. This is needed for modules 255 // Isolate GPIO12 pin from external circuits. This is needed for modules
135 // which have an external pull-up resistor on GPIO12 (such as ESP32-WROVER) 256 // which have an external pull-up resistor on GPIO12 (such as ESP32-WROVER)
136 // to minimize current consumption. 257 // to minimize current consumption.
137 // rtc_gpio_isolate(GPIO_NUM_12); 258 // rtc_gpio_isolate(GPIO_NUM_12);
157 u8g2_esp32_hal.scl = PIN_SCL; 278 u8g2_esp32_hal.scl = PIN_SCL;
158 u8g2_esp32_hal_init(u8g2_esp32_hal); 279 u8g2_esp32_hal_init(u8g2_esp32_hal);
159 280
160 u8g2_Setup_sh1106_i2c_128x64_noname_f(&u8g2, U8G2_R0, u8g2_esp32_i2c_byte_cb, u8g2_esp32_gpio_and_delay_cb); // init u8g2 structure 281 u8g2_Setup_sh1106_i2c_128x64_noname_f(&u8g2, U8G2_R0, u8g2_esp32_i2c_byte_cb, u8g2_esp32_gpio_and_delay_cb); // init u8g2 structure
161 u8x8_SetI2CAddress(&u8g2.u8x8, 0x78); 282 u8x8_SetI2CAddress(&u8g2.u8x8, 0x78);
162 ESP_LOGI(TAG, "u8g2_InitDisplay");
163 u8g2_InitDisplay(&u8g2); // send init sequence to the display, display is in sleep mode after this, 283 u8g2_InitDisplay(&u8g2); // send init sequence to the display, display is in sleep mode after this,
164 284
165 /* 285 /*
166 * Setup SPIFFS filesystem 286 * Setup SPIFFS filesystem
167 */ 287 */
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
463 708
464 printf("Entering deep sleep\n"); 709 printf("Entering deep sleep\n");
465 gettimeofday(&sleep_enter_time, NULL); 710 gettimeofday(&sleep_enter_time, NULL);
466 esp_deep_sleep_start(); 711 esp_deep_sleep_start();
467 712
468 Main_Loop1 = MAIN_LOOP1_INIT; 713 Main_Loop1 = ML1_INIT;
469 New_Loop2 = MAIN_LOOP2_INIT; 714 New_Loop2 = ML2_INIT;
470 } 715 }
471 716
472 } 717 }
473 718

mercurial