diff --git a/README.md b/README.md index ed82ac7..3825f52 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,22 @@ Air quality sensor on ESP32-S3 using ESP-IDF framework ## Hardware Components * WT32-SC01 Plus - ESP32S3 with 3.5 Touch screen -* SHT31 - Temperature Sensor +* SHT31 - Temperature Sensor (Optional) * BH1750 - Light Sensor * SPS30 Sensirion - Particle sensor +* SCD30 Sensirion - CO2 Sensor (Optional) + +## Features +* LVGL based display UI + * Touch screen UI + * Graph showing last 6 hours of values + * Wifi enroll using ESP Smart Config + * Display brightness changes based on ambient light +* Web server + * Responsive UI based on Bootstrap framework + * Real time sensor values using event streem + * Graph showing last 6 hours of values + * Firmware upgrade + * SD card file manager + * Debug page for remote debugging +* Homekit enabled diff --git a/gulpfile.js b/gulpfile.js index d7b0055..a0f6a6b 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -188,15 +188,15 @@ function font_create(bpp, size, font, output, symbols_and_range) { gulp.task('display-fonts-big-font', function() { return font_create( - 8, 165, - './node_modules/@fontsource/montserrat/files/montserrat-all-300-normal.woff', + 8, 155, + './node_modules/@fontsource/montserrat/files/montserrat-all-400-normal.woff', 'big_panel_font.c', '--symbols="0,1,2,3,4,5,6,7,8,9,-"'); }); gulp.task('display-fonts-big-font-dual', function() { return font_create( - 8, 130, - './node_modules/@fontsource/montserrat/files/montserrat-all-300-normal.woff', + 8, 118, + './node_modules/@fontsource/montserrat/files/montserrat-all-400-normal.woff', 'big_panel_font_dual.c', '--symbols="0,1,2,3,4,5,6,7,8,9,-"'); }); diff --git a/main/Kconfig b/main/Kconfig index 18e6827..c2a66a8 100644 --- a/main/Kconfig +++ b/main/Kconfig @@ -8,4 +8,9 @@ config SCD30_SENSOR_ENABLE bool "Enable Sensor SCD30 for CO2, temperature & humidity" default n +config SCD30_SENSOR_TEMPERATURE_OFFSET + int "Temperature offset for SCD30 in increment of 0.01C" + default 0 + depends on SCD30_SENSOR_ENABLE + endmenu \ No newline at end of file diff --git a/main/hardware/sensors/scd30_sensor_device.cpp b/main/hardware/sensors/scd30_sensor_device.cpp index 7e0b059..ccff269 100644 --- a/main/hardware/sensors/scd30_sensor_device.cpp +++ b/main/hardware/sensors/scd30_sensor_device.cpp @@ -31,6 +31,9 @@ std::array, 4> scd30_sensor_device::read() auto err = scd30_read_measurement(&scd30_sensor_, &co2, &temperatureC, &humidity); if (err == ESP_OK) { +#ifdef CONFIG_SCD30_SENSOR_TEMPERATURE_OFFSET + temperatureC -= CONFIG_SCD30_SENSOR_TEMPERATURE_OFFSET / 100; // offset for the heat generated by sensor itself. +#endif temperatureF = (temperatureC * 1.8) + 32; ESP_LOGI(SENSOR_SCD30_TAG, "Read SCD30 sensor values:%g ppm %g F, %g C %g %%", co2, temperatureF, temperatureC, humidity); } diff --git a/main/hardware/sensors/sensor.h b/main/hardware/sensors/sensor.h index 9448014..5a36ea0 100644 --- a/main/hardware/sensors/sensor.h +++ b/main/hardware/sensors/sensor.h @@ -258,7 +258,7 @@ constexpr std::array pm_2_5_definition_display{ constexpr std::array pm_10_definition_display{ sensor_definition_display{0, 54, sensor_level::level_1}, - sensor_definition_display{55, 154, sensor_level::level_2}, + sensor_definition_display{54, 154, sensor_level::level_2}, sensor_definition_display{154, 254, sensor_level::level_3}, sensor_definition_display{254, 354, sensor_level::level_4}, sensor_definition_display{354, 424, sensor_level::level_5}, @@ -268,9 +268,9 @@ constexpr std::array pm_10_definition_display{ #ifdef CONFIG_SCD30_SENSOR_ENABLE constexpr std::array co2_definition_display{ sensor_definition_display{0, 600, sensor_level::level_1}, - sensor_definition_display{601, 800, sensor_level::level_2}, - sensor_definition_display{801, 1000, sensor_level::level_3}, - sensor_definition_display{1001, 1500, sensor_level::level_4}, + sensor_definition_display{600, 800, sensor_level::level_2}, + sensor_definition_display{800, 1000, sensor_level::level_3}, + sensor_definition_display{1000, 1500, sensor_level::level_4}, sensor_definition_display{1500, 2000, sensor_level::level_5}, sensor_definition_display{2000, std::numeric_limits::max(), sensor_level::level_6}, }; diff --git a/main/lv_conf.h b/main/lv_conf.h index e602b11..f334f90 100644 --- a/main/lv_conf.h +++ b/main/lv_conf.h @@ -154,7 +154,7 @@ /*Allow dithering the gradients (to achieve visual smooth color gradients on limited color depth display) *LV_DITHER_GRADIENT implies allocating one or two more lines of the object's rendering surface *The increase in memory consumption is (32 bits * object width) plus 24 bits * object width if using error diffusion */ -#define LV_DITHER_GRADIENT 1 +#define LV_DITHER_GRADIENT 0 #if LV_DITHER_GRADIENT /*Add support for error diffusion dithering. *Error diffusion dithering gets a much better visual result, but implies more CPU consumption and memory when drawing. @@ -360,7 +360,7 @@ #define LV_FONT_MONTSERRAT_26 0 #define LV_FONT_MONTSERRAT_28 0 #define LV_FONT_MONTSERRAT_30 0 -#define LV_FONT_MONTSERRAT_32 0 +#define LV_FONT_MONTSERRAT_32 1 #define LV_FONT_MONTSERRAT_34 0 #define LV_FONT_MONTSERRAT_36 0 #define LV_FONT_MONTSERRAT_38 0 diff --git a/main/main.cpp b/main/main.cpp index aa0f4e3..0133428 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -23,7 +23,7 @@ ESP_EVENT_DEFINE_BASE(APP_COMMON_EVENT); extern "C" void app_main(void) { ESP_LOGI(OPERATIONS_TAG, "Starting ...."); - esp_log_level_set("*", ESP_LOG_INFO); + esp_log_level_set("*", ESP_LOG_NONE); try { diff --git a/main/ui/ui_interface.cpp b/main/ui/ui_interface.cpp index 95bb10f..be2f719 100644 --- a/main/ui/ui_interface.cpp +++ b/main/ui/ui_interface.cpp @@ -70,11 +70,18 @@ void ui_interface::reenable_homekit_pairing() std::string ui_interface::get_up_time() { const auto now = esp_timer_get_time() / (1000 * 1000); - const uint8_t hour = now / 3600; + const auto hour = now / 3600; const uint8_t mins = (now % 3600) / 60; const uint8_t sec = (now % 3600) % 60; - return esp32::string::sprintf("%02d hours %02d mins %02d secs", hour, mins, sec); + if (hour >= 24) + { + return esp32::string::sprintf("%lld days %02lld hours %02d mins %02d secs", hour / 24, hour % 24, mins, sec); + } + else + { + return esp32::string::sprintf("%02lld hours %02d mins %02d secs", hour, mins, sec); + } } std::string ui_interface::get_heap_info_str(uint32_t caps) @@ -232,7 +239,6 @@ ui_interface::information_table_type ui_interface::get_information_table(informa {"Reset Reason", get_reset_reason_string()}, {"Mac Address", get_default_mac_address()}, {"SD Card", sd_card_->get_info()}, - // {"Screen Brightness", esp32::string::sprintf("%d %%", (display_.get_brightness() * 100) / 256)}, {"SPS30 sensor status", hardware_->get_sps30_error_register_status()}, }; diff --git a/main/ui/ui_main_screen.cpp b/main/ui/ui_main_screen.cpp index 14ba066..bccc259 100644 --- a/main/ui/ui_main_screen.cpp +++ b/main/ui/ui_main_screen.cpp @@ -10,23 +10,24 @@ void ui_main_screen::init() #ifdef CONFIG_SCD30_SENSOR_ENABLE constexpr int x_pad = 10; - constexpr int y_pad = 15; - constexpr int big_panels_w = (screen_width - 2 * x_pad) / 2; + constexpr int y_pad = 25; + constexpr int big_panels_w = (screen_width - 3 * x_pad) / 2; constexpr int big_panel_h = ((screen_height * 2) / 3) - 30; - pm_2_5_panel_and_labels_ = create_big_panel(sensor_id_index::pm_2_5, x_pad, y_pad, big_panels_w, big_panel_h, &big_panel_font_dual); + pm_2_5_panel_and_labels_ = create_big_panel(sensor_id_index::pm_2_5, x_pad, y_pad, big_panels_w, big_panel_h, &big_panel_font_dual, -15); lv_obj_add_event_cb(pm_2_5_panel_and_labels_.panel, event_callback>, LV_EVENT_SHORT_CLICKED, this); - co2_panel_and_labels_ = create_big_panel(sensor_id_index::CO2, x_pad * 2 + big_panels_w, y_pad, big_panels_w, big_panel_h, &big_panel_font_dual); + co2_panel_and_labels_ = + create_big_panel(sensor_id_index::CO2, x_pad * 2 + big_panels_w, y_pad, big_panels_w, big_panel_h, &big_panel_font_dual, -15); lv_obj_add_event_cb(co2_panel_and_labels_.panel, event_callback>, LV_EVENT_SHORT_CLICKED, this); #else constexpr int y_pad = 10; constexpr int big_panel_w = (screen_width * 3) / 4; - constexpr int big_panel_h = ((screen_height * 2) / 3) - 15; + constexpr int big_panel_h = ((screen_height * 2) / 3) - 10; pm_2_5_panel_and_labels_ = - create_big_panel(sensor_id_index::pm_2_5, (screen_width - big_panel_w) / 2, y_pad, big_panel_w, big_panel_h, &big_panel_font); + create_big_panel(sensor_id_index::pm_2_5, (screen_width - big_panel_w) / 2, y_pad, big_panel_w, big_panel_h, &big_panel_font, -5); lv_obj_add_event_cb(pm_2_5_panel_and_labels_.panel, event_callback>, LV_EVENT_SHORT_CLICKED, this); #endif @@ -74,9 +75,9 @@ void ui_main_screen::show_screen() } ui_screen_with_sensor_panel::panel_and_label ui_main_screen::create_big_panel(sensor_id_index index, lv_coord_t x_ofs, lv_coord_t y_ofs, lv_coord_t w, - lv_coord_t h, const lv_font_t *font) + lv_coord_t h, const lv_font_t *font, lv_coord_t value_label_bottom_pad) { - auto panel = create_panel(x_ofs, y_ofs, w, h, 40); + auto panel = create_panel(x_ofs, y_ofs, w, h, 60); auto label = lv_label_create(panel); lv_obj_set_size(label, LV_SIZE_CONTENT, LV_SIZE_CONTENT); @@ -84,7 +85,7 @@ ui_screen_with_sensor_panel::panel_and_label ui_main_screen::create_big_panel(se lv_label_set_text_static(label, get_sensor_name(index).data()); lv_obj_set_style_text_color(label, off_black_color, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_opa(label, 255, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_text_font(label, &lv_font_montserrat_24, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(label, &lv_font_montserrat_32, LV_PART_MAIN | LV_STATE_DEFAULT); auto value_label = lv_label_create(panel); lv_obj_set_size(value_label, LV_SIZE_CONTENT, LV_SIZE_CONTENT); @@ -95,7 +96,7 @@ ui_screen_with_sensor_panel::panel_and_label ui_main_screen::create_big_panel(se lv_obj_set_style_text_color(value_label, text_color, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_align(label, LV_ALIGN_TOP_MID, 0, 9); - lv_obj_align(value_label, LV_ALIGN_BOTTOM_MID, 0, -1); + lv_obj_align(value_label, LV_ALIGN_BOTTOM_MID, 0, value_label_bottom_pad); panel_and_label pair{panel, value_label}; set_default_value_in_panel(pair); diff --git a/main/ui/ui_main_screen.h b/main/ui/ui_main_screen.h index 8f0c0bd..36c0c22 100644 --- a/main/ui/ui_main_screen.h +++ b/main/ui/ui_main_screen.h @@ -20,7 +20,8 @@ class ui_main_screen final : public ui_screen_with_sensor_panel panel_and_label temperature_panel_and_labels_; panel_and_label humidity_panel_and_labels_; - panel_and_label create_big_panel(sensor_id_index index, lv_coord_t x_ofs, lv_coord_t y_ofs, lv_coord_t w, lv_coord_t h, const lv_font_t *font); + panel_and_label create_big_panel(sensor_id_index index, lv_coord_t x_ofs, lv_coord_t y_ofs, lv_coord_t w, lv_coord_t h, const lv_font_t *font, + lv_coord_t value_label_bottom_pad); lv_obj_t *create_panel(lv_coord_t x_ofs, lv_coord_t y_ofs, lv_coord_t w, lv_coord_t h, lv_coord_t radius); panel_and_label create_temperature_panel(lv_coord_t x_ofs, lv_coord_t y_ofs); panel_and_label create_humidity_panel(lv_coord_t x_ofs, lv_coord_t y_ofs); diff --git a/main/wifi/wifi_manager.cpp b/main/wifi/wifi_manager.cpp index c806bec..0c5c2f6 100644 --- a/main/wifi/wifi_manager.cpp +++ b/main/wifi/wifi_manager.cpp @@ -119,7 +119,7 @@ void wifi_manager::wifi_task_ftn() { ESP_LOGI(WIFI_TAG, "Wifi enrollment done"); - auto ssid = wifi_enroll_instance->get_ssid(); + const auto ssid = wifi_enroll_instance->get_ssid(); if (!ssid.empty()) { ESP_LOGI(WIFI_TAG, "Updating wifi ssid/password"); diff --git a/sdkconfig b/sdkconfig index 432790a..0d1cf14 100644 --- a/sdkconfig +++ b/sdkconfig @@ -1614,6 +1614,7 @@ CONFIG_WPA_MBEDTLS_TLS_CLIENT=y # # CONFIG_SHT3X_SENSOR_ENABLE is not set CONFIG_SCD30_SENSOR_ENABLE=y +CONFIG_SCD30_SENSOR_TEMPERATURE_OFFSET=200 # end of Project #