main/co2meter.c

changeset 18
d969e0fe05dc
parent 17
f9eca4a55911
child 19
4fb9ed228a23
equal deleted inserted replaced
17:f9eca4a55911 18:d969e0fe05dc
91 u8g2_DrawStr(&u8g2, (128 - w) / 2,12, buf); 91 u8g2_DrawStr(&u8g2, (128 - w) / 2,12, buf);
92 } 92 }
93 93
94 94
95 95
96 void screen_splash()
97 {
98 screen_top("CO2 meter %s", app_desc->version);
99
100 u8g2_SetFont(&u8g2, u8g2_font_t0_22b_tf);
101 u8g2_uint_t w = u8g2_GetUTF8Width(&u8g2, "START");
102 u8g2_DrawUTF8(&u8g2, (128 - w) / 2,50, "START");
103
104 u8g2_SendBuffer(&u8g2);
105 u8g2_SetPowerSave(&u8g2, 0); // wake up display
106 }
107
108
109
96 void screen_main() 110 void screen_main()
97 { 111 {
98 char buf[65]; 112 char buf[65];
99 int i; 113 int i;
100 114
140 154
141 xSemaphoreGive(xSemaphoreUnits); 155 xSemaphoreGive(xSemaphoreUnits);
142 } 156 }
143 u8g2_SendBuffer(&u8g2); 157 u8g2_SendBuffer(&u8g2);
144 u8g2_SetPowerSave(&u8g2, 0); // wake up display 158 u8g2_SetPowerSave(&u8g2, 0); // wake up display
159 }
160
161
162
163 void screen_unit_zero(int no, int sub)
164 {
165 screen_top("Unit %d zero mV", no + 1);
166 menu_line( 0, 2, 25, "Current %d", units[no].pressure_zero);
167 menu_line(sub == 0, 2, 37, "New value %d", units[no].pressure_voltage / (adc_state->Batt_voltage / 1000));
168 menu_line(sub == 1, 2, 49, "Return");
169
170 u8g2_SendBuffer(&u8g2);
171 u8g2_SetPowerSave(&u8g2, 0);
145 } 172 }
146 173
147 174
148 175
149 void screen_unit_setup(int no, int sub) 176 void screen_unit_setup(int no, int sub)
223 ESP_ERROR_CHECK(rotary_encoder_reset(&rinfo)); 250 ESP_ERROR_CHECK(rotary_encoder_reset(&rinfo));
224 } 251 }
225 252
226 253
227 254
255 int rotate_to_sub(rotary_encoder_position_t pos, int min, int max, int cursub)
256 {
257 int sub = cursub;
258
259 if (pos > 0) {
260 if (sub < max)
261 sub++;
262 else
263 sub = min;
264 ESP_ERROR_CHECK(rotary_encoder_reset(&rinfo));
265 } else if (pos < 0) {
266 if (sub > min)
267 sub--;
268 else
269 sub = max;
270 ESP_ERROR_CHECK(rotary_encoder_reset(&rinfo));
271 }
272 return sub;
273 }
274
275
228 void app_main() 276 void app_main()
229 { 277 {
230 struct timeval now; 278 struct timeval now;
231 gettimeofday(&now, NULL); 279 gettimeofday(&now, NULL);
232 int sleep_time_ms = (now.tv_sec - sleep_enter_time.tv_sec) * 1000 + (now.tv_usec - sleep_enter_time.tv_usec) / 1000; 280 int sleep_time_ms = (now.tv_sec - sleep_enter_time.tv_sec) * 1000 + (now.tv_usec - sleep_enter_time.tv_usec) / 1000;
233 esp_err_t ret; 281 esp_err_t ret;
234 282
235 Main_Loop1 = ML1_INIT; 283 Main_Loop1 = ML1_INIT;
236 Main_Loop2 = -1; 284 Main_Loop2 = -1;
237 285
286 /*
287 * Setup the OLED display.
288 * See: https://github.com/nkolban/esp32-snippets/blob/master/hardware/displays/U8G2/
289 */
290 u8g2_esp32_hal_t u8g2_esp32_hal = U8G2_ESP32_HAL_DEFAULT;
291 u8g2_esp32_hal.sda = PIN_SDA;
292 u8g2_esp32_hal.scl = PIN_SCL;
293 u8g2_esp32_hal_init(u8g2_esp32_hal);
294
295 u8g2_Setup_sh1106_i2c_128x64_noname_f(&u8g2, U8G2_R0, u8g2_esp32_i2c_byte_cb, u8g2_esp32_gpio_and_delay_cb); // init u8g2 structure
296 u8x8_SetI2CAddress(&u8g2.u8x8, 0x78);
297 u8g2_InitDisplay(&u8g2); // send init sequence to the display, display is in sleep mode after this,
298
299 app_desc = esp_ota_get_app_description();
300
238 switch (esp_sleep_get_wakeup_cause()) { 301 switch (esp_sleep_get_wakeup_cause()) {
239 case ESP_SLEEP_WAKEUP_EXT1: { 302 case ESP_SLEEP_WAKEUP_EXT1: {
240 ESP_LOGI(TAG, "Starting from deep sleep, Rotary switch pressed"); 303 ESP_LOGI(TAG, "Starting from deep sleep, Rotary switch pressed");
241 New_Loop2 = ML2_INIT; 304 New_Loop2 = ML2_INIT;
305 screen_splash();
242 break; 306 break;
243 } 307 }
244 case ESP_SLEEP_WAKEUP_TIMER: { 308 case ESP_SLEEP_WAKEUP_TIMER: {
245 ESP_LOGI(TAG, "Starting from deep sleep, timer wakeup after %dms", sleep_time_ms); 309 ESP_LOGI(TAG, "Starting from deep sleep, timer wakeup after %dms", sleep_time_ms);
246 break; 310 break;
247 } 311 }
248 case ESP_SLEEP_WAKEUP_UNDEFINED: 312 case ESP_SLEEP_WAKEUP_UNDEFINED:
249 default: 313 default:
250 ESP_LOGI(TAG, "Starting from hard reset"); 314 ESP_LOGI(TAG, "Starting from hard reset");
315 screen_splash();
251 } 316 }
252 317
253 const int wakeup_time_sec = 55; 318 const int wakeup_time_sec = 55;
254 ESP_LOGI(TAG, "Enabling timer wakeup, %ds", wakeup_time_sec); 319 ESP_LOGI(TAG, "Enabling timer wakeup, %ds", wakeup_time_sec);
255 esp_sleep_enable_timer_wakeup(wakeup_time_sec * 1000000); 320 esp_sleep_enable_timer_wakeup(wakeup_time_sec * 1000000);
260 325
261 // Isolate GPIO12 pin from external circuits. This is needed for modules 326 // Isolate GPIO12 pin from external circuits. This is needed for modules
262 // which have an external pull-up resistor on GPIO12 (such as ESP32-WROVER) 327 // which have an external pull-up resistor on GPIO12 (such as ESP32-WROVER)
263 // to minimize current consumption. 328 // to minimize current consumption.
264 // rtc_gpio_isolate(GPIO_NUM_12); 329 // rtc_gpio_isolate(GPIO_NUM_12);
265
266 app_desc = esp_ota_get_app_description();
267 330
268 /* 331 /*
269 * Initialize NVS 332 * Initialize NVS
270 */ 333 */
271 ret = nvs_flash_init(); 334 ret = nvs_flash_init();
272 if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { 335 if (ret == ESP_ERR_NVS_NO_FREE_PAGES) {
273 ESP_ERROR_CHECK(nvs_flash_erase()); 336 ESP_ERROR_CHECK(nvs_flash_erase());
274 ret = nvs_flash_init(); 337 ret = nvs_flash_init();
275 } 338 }
276 ESP_ERROR_CHECK(ret); 339 ESP_ERROR_CHECK(ret);
277
278 /*
279 * Setup the OLED display.
280 * See: https://github.com/nkolban/esp32-snippets/blob/master/hardware/displays/U8G2/
281 */
282 u8g2_esp32_hal_t u8g2_esp32_hal = U8G2_ESP32_HAL_DEFAULT;
283 u8g2_esp32_hal.sda = PIN_SDA;
284 u8g2_esp32_hal.scl = PIN_SCL;
285 u8g2_esp32_hal_init(u8g2_esp32_hal);
286
287 u8g2_Setup_sh1106_i2c_128x64_noname_f(&u8g2, U8G2_R0, u8g2_esp32_i2c_byte_cb, u8g2_esp32_gpio_and_delay_cb); // init u8g2 structure
288 u8x8_SetI2CAddress(&u8g2.u8x8, 0x78);
289 u8g2_InitDisplay(&u8g2); // send init sequence to the display, display is in sleep mode after this,
290 340
291 /* 341 /*
292 * Setup SPIFFS filesystem 342 * Setup SPIFFS filesystem
293 */ 343 */
294 ESP_LOGI(TAG, "Initializing SPIFFS"); 344 ESP_LOGI(TAG, "Initializing SPIFFS");
399 while (1) { 449 while (1) {
400 450
401 ESP_LOGI(TAG, "Entered app loop"); 451 ESP_LOGI(TAG, "Entered app loop");
402 rotary_encoder_event_t event = { 0 }; 452 rotary_encoder_event_t event = { 0 };
403 int sub = 0; 453 int sub = 0;
454 u8g2_SetPowerSave(&u8g2, 1);
404 455
405 /* Measure process or user input via rotary switch */ 456 /* Measure process or user input via rotary switch */
406 while (1) { 457 while (1) {
407 switch (Main_Loop1) { 458 switch (Main_Loop1) {
408 case ML1_INIT: 459 case ML1_INIT:
448 strncpy(units[i].temperature_rom_code, rom_code, 17); 499 strncpy(units[i].temperature_rom_code, rom_code, 17);
449 if (xSemaphoreTake(xSemaphoreADC, 10) == pdTRUE) { 500 if (xSemaphoreTake(xSemaphoreADC, 10) == pdTRUE) {
450 units[i].pressure_state = adc_state->Pressure[i].error; 501 units[i].pressure_state = adc_state->Pressure[i].error;
451 units[i].pressure_channel = adc_state->Pressure[i].channel; 502 units[i].pressure_channel = adc_state->Pressure[i].channel;
452 units[i].pressure_voltage = adc_state->Pressure[i].voltage; 503 units[i].pressure_voltage = adc_state->Pressure[i].voltage;
453 units[i].pressure_zero = 110;
454 if (units[i].pressure_state || units[i].pressure_voltage < 80) 504 if (units[i].pressure_state || units[i].pressure_voltage < 80)
455 units[i].alarm |= ALARM_UNIT_PRESSURE; 505 units[i].alarm |= ALARM_UNIT_PRESSURE;
456 int P = (units[i].pressure_voltage / (adc_state->Batt_voltage / 1000) - units[i].pressure_zero) * 14; // in bar 506 int P = (units[i].pressure_voltage / (adc_state->Batt_voltage / 1000) - units[i].pressure_zero) * 14; // in bar
457 if (P < 0) 507 if (P < 0)
458 P = 0; 508 P = 0;
459 units[i].pressure = P; 509 units[i].pressure = P;
460 printf("%d volt: %d batt: %d scale: %d bar: %d\n", i, units[i].pressure_voltage, adc_state->Batt_voltage, 510 printf("%d volt: %d batt: %d scale: %d mbar: %d\n", i, units[i].pressure_voltage, adc_state->Batt_voltage,
461 units[i].pressure_voltage / (adc_state->Batt_voltage / 1000) - units[i].pressure_zero, P); 511 units[i].pressure_voltage / (adc_state->Batt_voltage / 1000) - units[i].pressure_zero, P);
462 // Moet die echt op 5 volt? 512 // Moet die echt op 5 volt?
463 // Verbruik 10 mA 513 // Verbruik 10 mA
464 // Setup tijd max 2 mS 514 // Setup tijd max 2 mS
465 xSemaphoreGive(xSemaphoreADC); 515 xSemaphoreGive(xSemaphoreADC);
568 ESP_LOGI(TAG, "Loop user: Setup Unit %d", Main_Loop2 - ML2_SETUP_UNIT1); 618 ESP_LOGI(TAG, "Loop user: Setup Unit %d", Main_Loop2 - ML2_SETUP_UNIT1);
569 sub = 0; 619 sub = 0;
570 screen_unit_setup(Main_Loop2 - ML2_SETUP_UNIT1, sub); 620 screen_unit_setup(Main_Loop2 - ML2_SETUP_UNIT1, sub);
571 break; 621 break;
572 622
623 case ML2_ZERO_UNIT1:
624 case ML2_ZERO_UNIT2:
625 case ML2_ZERO_UNIT3:
626 ESP_LOGI(TAG, "Loop user: Zero Unit %d", Main_Loop2 - ML2_ZERO_UNIT1);
627 sub = 0;
628 screen_unit_zero(Main_Loop2 - ML2_ZERO_UNIT1, sub);
629 break;
630
573 case ML2_INACTIVE: 631 case ML2_INACTIVE:
574 ESP_LOGI(TAG, "Loop user: Inactive"); 632 ESP_LOGI(TAG, "Loop user: Inactive");
575 u8g2_SetPowerSave(&u8g2, 1); // powersave display 633 u8g2_SetPowerSave(&u8g2, 1); // powersave display
576 New_Loop2 = ML2_DONE; 634 New_Loop2 = ML2_DONE;
577 break; 635 break;
612 case ML2_SET_NETWORK: rotate_to_menu(event.state.position, ML2_SET_MQTT, ML2_SET_WIFI); break; 670 case ML2_SET_NETWORK: rotate_to_menu(event.state.position, ML2_SET_MQTT, ML2_SET_WIFI); break;
613 case ML2_SET_MQTT: rotate_to_menu(event.state.position, ML2_UPDATE, ML2_SET_NETWORK); break; 671 case ML2_SET_MQTT: rotate_to_menu(event.state.position, ML2_UPDATE, ML2_SET_NETWORK); break;
614 case ML2_UPDATE: rotate_to_menu(event.state.position, ML2_UPDATE, ML2_SET_MQTT); break; 672 case ML2_UPDATE: rotate_to_menu(event.state.position, ML2_UPDATE, ML2_SET_MQTT); break;
615 case ML2_SETUP_UNIT1: 673 case ML2_SETUP_UNIT1:
616 case ML2_SETUP_UNIT2: 674 case ML2_SETUP_UNIT2:
617 case ML2_SETUP_UNIT3: if (event.state.position > 0) { 675 case ML2_SETUP_UNIT3: sub = rotate_to_sub(event.state.position, 0, 3, sub);
618 if (sub < 3) { 676 screen_unit_setup(Main_Loop2 - ML2_SETUP_UNIT1, sub);
619 sub++; 677 break;
620 } else { 678 case ML2_ZERO_UNIT1:
621 sub = 0; 679 case ML2_ZERO_UNIT2:
622 } 680 case ML2_ZERO_UNIT3: sub = rotate_to_sub(event.state.position, 0, 1, sub);
623 screen_unit_setup(Main_Loop2 - ML2_SETUP_UNIT1, sub); 681 screen_unit_zero(Main_Loop2 - ML2_ZERO_UNIT1, sub);
624 ESP_ERROR_CHECK(rotary_encoder_reset(&rinfo));
625 } else if (event.state.position < 0) {
626 if (sub > 0) {
627 sub--;
628 } else {
629 sub = 3;
630 }
631 screen_unit_setup(Main_Loop2 - ML2_SETUP_UNIT1, sub);
632 ESP_ERROR_CHECK(rotary_encoder_reset(&rinfo));
633 }
634 break; 682 break;
635 default: 683 default:
636 ESP_LOGI(TAG, "Event: position %d, direction %s", event.state.position, 684 ESP_LOGI(TAG, "Event: position %d, direction %s", event.state.position,
637 event.state.direction ? (event.state.direction == ROTARY_ENCODER_DIRECTION_CLOCKWISE ? "CW":"CCW"):"NOT_SET"); 685 event.state.direction ? (event.state.direction == ROTARY_ENCODER_DIRECTION_CLOCKWISE ? "CW":"CCW"):"NOT_SET");
638 } 686 }
653 } else 701 } else
654 New_Loop2 = ML2_INACTIVE; 702 New_Loop2 = ML2_INACTIVE;
655 } 703 }
656 } 704 }
657 705
658 switch (Main_Loop2) { 706 /*
659 // Break if all done and inactive. 707 * Handle pressed rotary button.
660 case ML2_UNIT1: 708 */
661 case ML2_UNIT2: 709 if (PushDuration) {
662 case ML2_UNIT3: 710 int idx = 0;
663 if (PushDuration) { 711 switch (Main_Loop2) {
664 New_Loop2 = ML2_SETUP_UNIT1 + (Main_Loop2 - ML2_UNIT1); 712 case ML2_UNIT1:
665 PushDuration = 0; 713 case ML2_UNIT2:
714 case ML2_UNIT3:
715 New_Loop2 = ML2_SETUP_UNIT1 + (Main_Loop2 - ML2_UNIT1);
716 break;
717
718 case ML2_SETUP_UNIT1:
719 case ML2_SETUP_UNIT2:
720 case ML2_SETUP_UNIT3:
721 idx = Main_Loop2 - ML2_SETUP_UNIT1;
722 if (sub == 0) {
723 if (xSemaphoreTake(xSemaphoreUnits, 25) == pdTRUE) {
724 if (units[idx].mode)
725 units[idx].mode = 0;
726 else
727 units[idx].mode = 1;
728 write_units();
729 xSemaphoreGive(xSemaphoreUnits);
730 }
731 screen_unit_setup(idx, sub);
732 if (Main_Loop1 == ML1_DONE)
733 Main_Loop1 = ML1_INIT;
666 } 734 }
667 break; 735 if (sub == 1)
668 736 New_Loop2 = ML2_ZERO_UNIT1 + idx;
669 case ML2_SETUP_UNIT1: 737 if (sub == 3)
670 case ML2_SETUP_UNIT2: 738 New_Loop2 = ML2_UNIT1 + idx;
671 case ML2_SETUP_UNIT3: 739 printf("unit setup sub %d new %d idx %d\n", sub, New_Loop2, idx);
672 if (PushDuration) { 740 break;
673 if (sub == 0) { 741
674 if (xSemaphoreTake(xSemaphoreUnits, 25) == pdTRUE) { 742 case ML2_ZERO_UNIT1:
675 if (units[Main_Loop2 - ML2_SETUP_UNIT1].mode) 743 case ML2_ZERO_UNIT2:
676 units[Main_Loop2 - ML2_SETUP_UNIT1].mode = 0; 744 case ML2_ZERO_UNIT3:
677 else 745 idx = Main_Loop2 - ML2_ZERO_UNIT1;
678 units[Main_Loop2 - ML2_SETUP_UNIT1].mode = 1; 746 if (sub == 0) {
679 write_units(); 747 if (xSemaphoreTake(xSemaphoreUnits, 25) == pdTRUE &&
680 xSemaphoreGive(xSemaphoreUnits); 748 xSemaphoreTake(xSemaphoreADC, 10) == pdTRUE &&
681 } 749 adc_state->Pressure[idx].voltage > 165 &&
682 screen_unit_setup(Main_Loop2 - ML2_SETUP_UNIT1, sub); 750 adc_state->Pressure[idx].voltage < 660) {
751 units[idx].pressure_zero = adc_state->Pressure[idx].voltage / (adc_state->Batt_voltage / 1000);
752 write_units();
753 xSemaphoreGive(xSemaphoreADC);
754 xSemaphoreGive(xSemaphoreUnits);
755 screen_unit_zero(idx, sub);
683 if (Main_Loop1 == ML1_DONE) 756 if (Main_Loop1 == ML1_DONE)
684 Main_Loop1 = ML1_INIT; 757 Main_Loop1 = ML1_INIT;
685 } 758 }
686 if (sub == 3)
687 New_Loop2 = ML2_UNIT1 + (Main_Loop2 - ML2_SETUP_UNIT1);
688 printf("sub %d new %d\n", sub, New_Loop2);
689 PushDuration = 0;
690 } 759 }
691 break; 760 if (sub == 1) {
692 761 New_Loop2 = ML2_SETUP_UNIT1 + idx;
693 default: 762 sub = 1;
694 break; 763 }
764 printf("unit zero sub %d new %d idx %d\n", sub, New_Loop2, idx);
765 break;
766
767 default:
768 break;
769 }
770 PushDuration = 0;
695 } 771 }
696 772
697 if (Main_Loop1 == ML1_DONE && Main_Loop2 == ML2_DONE) 773 if (Main_Loop1 == ML1_DONE && Main_Loop2 == ML2_DONE)
698 break; 774 break;
699 775

mercurial