From 6953c97efd4d0f7d0f43032d90039f042edbf033 Mon Sep 17 00:00:00 2001 From: Mario Mariete <11509521+melkati@users.noreply.github.com> Date: Tue, 30 Jan 2024 08:40:47 +0100 Subject: [PATCH 1/4] Fix WiFi initialization issue (disable WiFi if SSID not set) --- CO2_Gadget_WIFI.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CO2_Gadget_WIFI.h b/CO2_Gadget_WIFI.h index 85ea0ff3..86fbe8b8 100644 --- a/CO2_Gadget_WIFI.h +++ b/CO2_Gadget_WIFI.h @@ -634,6 +634,9 @@ boolean TimePeriodIsOver(unsigned long &startOfPeriod, unsigned long TimePeriod) unsigned long MyTestTimer = 0; // Timer-variables MUST be of type unsigned long void initWifi() { + if (wifiSSID == "") { + activeWIFI = false; + } if (activeWIFI) { wifiChanged = true; troubledWIFI = false; From 64e13a2cb17ef2c6520595ca0a1a796658db76d1 Mon Sep 17 00:00:00 2001 From: Mario Mariete <11509521+melkati@users.noreply.github.com> Date: Tue, 30 Jan 2024 10:31:56 +0100 Subject: [PATCH 2/4] Modify partition table and Disable OTA for ESP32 to free up a lot of memory. Add activeOTA flag for ESP32 S3 and include in menu. False by default for security. Add a 5 secs delay until menu is active for better Improv-WiFi response Looks like freeing memory fixes #145 --- CO2_Gadget.ino | 5 +++-- CO2_Gadget_Menu.h | 20 +++++++++++++++++--- CO2_Gadget_Partitions-no_ota.csv | 5 +++++ CO2_Gadget_Preferences.h | 8 +++++++- CO2_Gadget_WIFI.h | 4 +++- platformio.ini | 15 +++++++-------- 6 files changed, 42 insertions(+), 15 deletions(-) create mode 100644 CO2_Gadget_Partitions-no_ota.csv diff --git a/CO2_Gadget.ino b/CO2_Gadget.ino index bc1b5f0b..9afb978c 100644 --- a/CO2_Gadget.ino +++ b/CO2_Gadget.ino @@ -34,6 +34,7 @@ bool activeBLE = true; bool activeWIFI = true; bool activeMQTT = true; bool activeESPNOW = false; +bool activeOTA = false; bool troubledWIFI = false; // There are problems connecting to WIFI. Temporary suspend WIFI bool troubledMQTT = false; // There are problems connecting to MQTT. Temporary suspend MQTT uint64_t timeTroubledWIFI = 0; // Time since WIFI is troubled @@ -54,7 +55,6 @@ bool displayShowHumidity = true; bool displayShowBattery = true; bool displayShowCO2 = true; bool displayShowPM25 = true; - bool debugSensors = false; bool inMenu = false; uint16_t measurementInterval = 10; @@ -63,6 +63,7 @@ int8_t selectedCO2Sensor = -1; bool outputsModeRelay = false; uint8_t channelESPNow = 1; uint16_t boardIdESPNow = 0; +uint64_t timeInitializationCompleted = 0; // Variables for Battery reading float battery_voltage = 0; @@ -494,7 +495,7 @@ void setup() { } WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, brown_reg_temp); // enable brownout detector Serial.println("-->[STUP] Ready."); - delay(100); + timeInitializationCompleted = millis(); } void loop() { diff --git a/CO2_Gadget_Menu.h b/CO2_Gadget_Menu.h index c56455fd..3940c52e 100644 --- a/CO2_Gadget_Menu.h +++ b/CO2_Gadget_Menu.h @@ -331,11 +331,8 @@ result doSetWiFiSSID(eventMask e, navNode &nav, prompt &item) { Serial.println(e); Serial.flush(); #endif - // Serial.printf("tempWiFiSSID: #%s#\n", tempWiFiSSID); wifiSSID = String(tempWiFiSSID); - // Serial.printf("wifiSSID: #%s#\n", wifiSSID.c_str()); wifiSSID.trim(); - // Serial.printf("wifiSSID: #%s#\n", wifiSSID.c_str()); return proceed; } @@ -367,11 +364,24 @@ TOGGLE(activeWIFI, activeWIFIMenu, "WIFI Enable: ", doNothing,noEvent, wrapStyle ,VALUE("ON", true, doSetActiveWIFI, exitEvent) ,VALUE("OFF", false, doSetActiveWIFI, exitEvent)); +#ifdef SUPPORT_OTA +result doSetActiveOTA(eventMask e, navNode &nav, prompt &item) { + return proceed; +} + +TOGGLE(activeOTA, activeOTAMenu, "OTA Enable: ", doNothing,noEvent, wrapStyle + ,VALUE("ON", true, doSetActiveOTA, exitEvent) + ,VALUE("OFF", false, doSetActiveOTA, exitEvent)); +#endif + MENU(wifiConfigMenu, "WIFI Config", doNothing, noEvent, wrapStyle ,SUBMENU(activeWIFIMenu) ,EDIT("SSID", tempWiFiSSID, ssidChars, doSetWiFiSSID, exitEvent, wrapStyle) ,EDIT("Pass:", tempWiFiPasswrd, allChars, doSetWiFiPasswrd, exitEvent, wrapStyle) ,EDIT("Host:", tempHostName, allChars, doSetHostName, exitEvent, wrapStyle) +#ifdef SUPPORT_OTA + ,SUBMENU(activeOTAMenu) +#endif ,EXIT("[PREF] activeBLE is:\t#%s# (%d)\n", ((activeBLE) ? "Enabled" : "Disabled"), activeBLE); Serial.printf("-->[PREF] activeWIFI is:\t#%s# (%d)\n", ((activeWIFI) ? "Enabled" : "Disabled"), activeWIFI); Serial.printf("-->[PREF] activeMQTT is:\t#%s# (%d)\n", ((activeMQTT) ? "Enabled" : "Disabled"), activeMQTT); - Serial.printf("-->[PREF] activeESPNOW is:\t#%s# (%d)\n", ((activeMQTT) ? "Enabled" : "Disabled"), activeESPNOW); + Serial.printf("-->[PREF] activeESPNOW is:\t#%s# (%d)\n", ((activeESPNOW) ? "Enabled" : "Disabled"), activeESPNOW); + Serial.printf("-->[PREF] activeOTA is:\t#%s# (%d)\n", ((activeOTA) ? "Enabled" : "Disabled"), activeOTA); Serial.printf("-->[PREF] rootTopic:\t#%s#\n", rootTopic.c_str()); Serial.printf("-->[PREF] batDischgd:\t #%d#\n", batteryDischargedMillivolts); Serial.printf("-->[PREF] batChargd:\t #%d#\n", batteryFullyChargedMillivolts); @@ -85,6 +86,7 @@ void initPreferences() { activeWIFI = preferences.getBool("activeWIFI", true); activeMQTT = preferences.getBool("activeMQTT", false); activeESPNOW = preferences.getBool("activeESPNOW", false); + activeOTA = preferences.getBool("activeOTA", false); rootTopic = preferences.getString("rootTopic", rootTopic); mqttClientId = preferences.getString("mqttClientId", mqttClientId); mqttBroker = preferences.getString("mqttBroker", mqttBroker).c_str(); @@ -183,6 +185,7 @@ void putPreferences() { preferences.putBool("activeWIFI", activeWIFI); preferences.putBool("activeMQTT", activeMQTT); preferences.putBool("activeESPNOW", activeESPNOW); + preferences.putBool("activeOTA", activeOTA); preferences.putString("rootTopic", rootTopic); preferences.putUInt("batDischgd", batteryDischargedMillivolts); preferences.putUInt("batChargd", batteryFullyChargedMillivolts); @@ -237,6 +240,7 @@ String getPreferencesAsJson() { doc["activeWIFI"] = preferences.getBool("activeWIFI", false); doc["activeMQTT"] = preferences.getBool("activeMQTT", false); doc["activeESPNOW"] = preferences.getBool("activeESPNOW", false); + doc["activeOTA"] = preferences.getBool("activeOTA", false); doc["rootTopic"] = preferences.getString("rootTopic", rootTopic); doc["batDischgd"] = preferences.getInt("batDischgd", 3500); doc["batChargd"] = preferences.getInt("batChargd", 4200); @@ -293,6 +297,7 @@ String getActualSettingsAsJson() { doc["activeWIFI"] = activeWIFI; doc["activeMQTT"] = activeMQTT; doc["activeESPNOW"] = activeESPNOW; + doc["activeOTA"] = activeOTA; doc["rootTopic"] = rootTopic; doc["batDischgd"] = batteryDischargedMillivolts; doc["batChargd"] = batteryFullyChargedMillivolts; @@ -379,6 +384,7 @@ bool handleSavePreferencesfromJSON(String jsonPreferences) { activeWIFI = JsonDocument["activeWIFI"]; activeMQTT = JsonDocument["activeMQTT"]; activeESPNOW = JsonDocument["activeESPNOW"]; + activeOTA = JsonDocument["activeOTA"]; rootTopic = JsonDocument["rootTopic"].as().c_str(); batteryDischargedMillivolts = JsonDocument["batDischgd"]; batteryFullyChargedMillivolts = JsonDocument["batChargd"]; diff --git a/CO2_Gadget_WIFI.h b/CO2_Gadget_WIFI.h index 86fbe8b8..1b8ae63a 100644 --- a/CO2_Gadget_WIFI.h +++ b/CO2_Gadget_WIFI.h @@ -739,7 +739,9 @@ void wifiClientLoop() { void OTALoop() { #ifdef SUPPORT_OTA - AsyncElegantOTA.loop(); + if ((activeWIFI) && (activeOTA) && (!troubledWIFI) && (WiFi.status() == WL_CONNECTED)) { + AsyncElegantOTA.loop(); + } #endif } diff --git a/platformio.ini b/platformio.ini index b2ff9711..45c22d42 100644 --- a/platformio.ini +++ b/platformio.ini @@ -25,7 +25,7 @@ monitor_speed = 115200 monitor_port = COM12 upload_port = COM12 monitor_filters = time, esp32_exception_decoder -board_build.partitions = CO2_Gadget_Partitions.csv ; Others at Windows at C:\Users\%USER%\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.5\tools\partitions +board_build.partitions = CO2_Gadget_Partitions-no_ota.csv ; Others at Windows at C:\Users\%USER%\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.5\tools\partitions extra_scripts = lib_ldf_mode = chain+ lib_deps = @@ -57,8 +57,7 @@ build_flags = -D MQTT_BROKER_SERVER="\"192.168.1.145"\" -D CO2_GADGET_VERSION="\"0.8."\" - - -D CO2_GADGET_REV="\"090-development"\" + -D CO2_GADGET_REV="\"092-development"\" -D CORE_DEBUG_LEVEL=0 -DNEOPIXEL_PIN=26 ; Pinnumber for button for down/next and back / exit actions -DNEOPIXEL_COUNT=16 ; How many neopixels to control @@ -77,10 +76,10 @@ build_flags = -DPIN_HYSTERESIS=100 ; Hysteresis PPM to avoid pins going ON and OFF continuously. TODO : Minimum time to switch -DWIFI_PRIVACY ; Comment to show WiFi password in serial and the menu (intended for debugging) -DSUPPORT_BLE ; Comment to dissable Bluetooth (makes more memory available) - -USUPPORT_ESPNOW - -DSUPPORT_OTA ; Needs SUPPORT_WIFI - -DSUPPORT_MDNS ; Needs SUPPORT_WIFI - -DSUPPORT_MQTT ; Needs SUPPORT_WIFI + -DSUPPORT_ESPNOW + -USUPPORT_OTA ; + -DSUPPORT_MDNS ; + -DSUPPORT_MQTT ; -DSUPPORT_MQTT_DISCOVERY -DMQTT_DISCOVERY_PREFIX="\"homeassistant/\"" -DESPNOW_PEER_MAC_ADDRESS="{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}" ; MAC Address of the ESP-NOW receiver (STA MAC). For unicast use peer address, as: {0xE8, 0x68, 0xE7, 0x0F, 0x08, 0x90} @@ -237,7 +236,6 @@ platform = espressif32 board = lilygo-t-display-s3 framework = ${common_env_data.framework} monitor_filters = ${common_env_data.monitor_filters} -; board_build.partitions = ${common_env_data.board_build.partitions} extra_scripts = ${common_env_data.extra_scripts} board_build.flash_mode = dio board_upload.flash_size = 16MB @@ -250,6 +248,7 @@ lib_deps = ${common_env_data.lib_deps} build_flags = ${common_env_data.build_flags} + -DSUPPORT_OTA -DARDUINO_ESP32_DEV=1 -DTDISPLAY_S3 -DBTN_UP=14 ; Pinnumber for button for up/previous and select / enter actions From d6ab6a340ed5272ada6745d84bf657c3e8a7c95b Mon Sep 17 00:00:00 2001 From: Mario Mariete <11509521+melkati@users.noreply.github.com> Date: Tue, 30 Jan 2024 10:32:19 +0100 Subject: [PATCH 3/4] Update README.md --- README.md | 61 ++++++++++++++++--------------------------------------- 1 file changed, 17 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index c4744528..4ec826b4 100644 --- a/README.md +++ b/README.md @@ -25,11 +25,14 @@ This repository is mainly addressed at developers. If you are an end user willin - Sending of data via MQTT - Receiving remote commands via MQTT - MQTT Discovery protocol for Home Assistant (and others supporting it as HomeSeer with mcsMQTT) +- Easy installing via web browser +- Easy WiFi setup via web browser on install and anytime (supports Improv-WiFi) +- Easy WiFi setup via bluetooth with the MyAmbiance App in iOS and Android - ESP-NOW communications protocol from Espressif for long range and low power consuption ([more info here](https://emariete.com/en/gateway-esp-now-mqtt/)) - Over the air updates OTA - Support for Neopixel (WS2812B) addressable LEDs (RGB, GBR and RGBW) - Support for RGB LEDs -- GPIO outputs to, for example, activation of air circulation on CO2 concentration threshold with hysteresis. Check GPIO to use at [my blog CO2 Gadget firmware page](https://emariete.com/medidor-co2-gadget/) +- GPIO outputs for alarms and activation of air circulation on CO2 concentration threshold with hysteresis. Check GPIO to use at [my blog CO2 Gadget firmware page](https://emariete.com/medidor-co2-gadget/) - ~~-LoRa/LoRaWAN in study. If you are interested, please [join this conversation](https://github.com/melkati/CO2-Gadget/issues/35).~~ # Supported hardware and build @@ -88,6 +91,7 @@ CanAirIO sensorlib right now supports: | Panasonic SN-GCJA5L | Yes | Yes | Auto | STABLE | | Plantower models | Yes | --- | Auto | STABLE | | Nova SDS011 | Yes | --- | Auto | STABLE | +| IKEA Vindriktning | Yes | --- | Select | STABLE | Sensirion SPS30 | Yes | Yes | Select / Auto | STABLE | NOTE: Panasonic via UART in ESP8266 maybe needs select in detection @@ -110,7 +114,13 @@ NOTE: Panasonic via UART in ESP8266 maybe needs select in detection | SHT31 | i2c | Auto | STABLE | | AHT10 | i2c | Auto | STABLE | | BME280 | i2c | Auto | STABLE | +| BMP280 | i2c | Auto | STABLE | | BME680 | i2c | Auto | STABLE | + +| DfRobot SEN0469 NH3 | i2c | Auto | TESTING | +| DFRobot SEN0466 CO | i2c | Auto | TESTING | +| Geiger CAJOE | i2c | Select | TESTING | + | DHTxx | TwoWire | Auto | DEPRECATED | NOTE: DHT22 is supported but is not recommended @@ -122,7 +132,7 @@ Full details on CanAirIO sensorlib [here](https://github.com/kike-canaries/canai ## With PlatformIO (recommended) -**Note:** If all you want is to flash CO2 Gadget into your board go [here:](https://emariete.com/en/meter-co2-gadget/). You don't need to compile the firmware. +**Note:** If all you want is to install CO2 Gadget into your board go [here:](https://emariete.com/en/meter-co2-gadget/). You can install it from your web browser and don't need to compile the firmware. ### Install PlatformIO @@ -156,47 +166,10 @@ If using PlatformIO **GUI**, to compile and upload CO2-Gadget into your board, p ## With Arduino **NOTE:** -Currently neither the code is ready to compile with the Arduino IDE nor these instructions are up to date. If you want to compile with the Arduino IDE, you will have to solve includes, dependencies and defines yourself. - -When the code is more stable and changes less often, I will update the code the instructions to compile with the Arduino IDE. Right now it is modified very often with bugfixes and new functionalities and it takes me a lot of time to be aware of maintaining compatibility with the Arduino IDE. +Currently Arduino IDE is not supported. If you want to compile with the Arduino IDE, you will have to solve includes, dependencies and defines yourself. I recommend that you use VS Code with PlatformIO. You have many tutorials on the internet, and it is not as difficult at all as it seems. -#### Prerequisites - -To **compile this project with Arduino IDE** (the integrated development enviroment), you have to **install Arduino IDE**, and **add the libraries** referenced in **lib_deps** in the file [platformio.ini](https://github.com/melkati/CO2-Gadget/blob/master/platformio.ini), as **Arduino won't install it automatically** like PlatformIO does. - -Also, you need to add support for ESP32 boards: - -For Arduino IDE: Adding the line **https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json** in: File > Preferences > Additional Boards Manager URLs. - -In Arduino IDE select your board, COM port, etc. in the Tools menu and to upload to your board select Program -> Upload or click on the "upload" icon. - -To **compile this project with Arduino CLI** (the command line version of Arduino), you first need to install **arduino-cli** or the **Arduino IDE** with the libraries referenced in **lib_deps** in the file [platformio.ini](https://github.com/melkati/CO2-Gadget/blob/master/platformio.ini), because **Arduino won't install it automatically** like PlatformIO does. - -You must first add support for ESP32 boards in Arduino CLI: Follow the next steps: - -```bash -arduino-cli config init -``` - -in the `.arduino15/arduino-cli.yaml` file add: - -```yml -board_manager: - additional_urls: - - https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json -``` - -From `arduino-cli` you can load CO2 Gadget in an ESP32 board following these steps: - -```javascript -arduino-cli core update-index -arduino-cli core install esp32:esp32:esp32 -arduino-cli compile --fqbn esp32:esp32:esp32 CO2_Gadget.ino -arduino-cli upload --fqbn esp32:esp32:esp32:UploadSpeed=115200 -p /dev/ttyUSB0 basic -``` - # Supporting the project If you want to contribute to the code or documentation, consider posting a bug report, feature request or a pull request. @@ -209,13 +182,12 @@ When creating a pull request, we recommend that you do the following: - Clone the repository - Create a new branch for your fix or feature. For example, git checkout -b fix/my-fix or git checkout -b feat/my-feature. - Run to any clang formatter if it is a code, for example using the `vscode` formatter. We are using Google style. More info [here](https://clang.llvm.org/docs/ClangFormatStyleOptions.html) -- Document the PR description or code will be great -- Target your pull request to be merged with `development` branch +- Document the PR description and code is a must +- Target your pull request to be merged with the `development` branch # TODO - [ ] Implement full support for PM 2.5 -- [ ] Full configuration vía web page # Useful information @@ -224,10 +196,11 @@ When creating a pull request, we recommend that you do the following: - [Everything about the Winsen MH-Z19 NDIR CO2 sensors](https://emariete.com/en/sensor-co2-mh-z19b/) - [Everything about the Winsen Low Consumption CO2 Sensor MH-Z1311A](https://emariete.com/en/sensor-co2-low-consumption-mh-z1311a-winsen/) - [MH-Z19B vs Senseair S8 NDIR sensors](https://emariete.com/en/comparison-co2-sensors-mh-z19b-vs-senseair-s8/) +- [Tutorial to build a CO2 Monitor with a TTGO T-Display board](https://emariete.com/en/co2-meter-co2-display-tft-colour-ttgo-t-display-sensirion-scd30/) # Credits -Thanks to all collaborators, contributors and [eMariete](https://emariete.com) community for testing and reports. +Thanks to all collaborators, contributors and to the [eMariete](https://emariete.com) community for testing and reports. --- ## License From 152baf708ef9c9bbdf1a62a7207886fad256efd8 Mon Sep 17 00:00:00 2001 From: Mario Mariete <11509521+melkati@users.noreply.github.com> Date: Tue, 30 Jan 2024 11:47:36 +0100 Subject: [PATCH 4/4] Enable/disable MQTT menu based on activeWIFI status and prevent unnecessary screen fill when wifiChanged and not inMenu Fix WiFi initialitation issues with display and menu when WiFi activated from menu --- CO2_Gadget_Menu.h | 8 +++++++- CO2_Gadget_WIFI.h | 4 ++-- platformio.ini | 6 +++--- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/CO2_Gadget_Menu.h b/CO2_Gadget_Menu.h index 3940c52e..73316e3c 100644 --- a/CO2_Gadget_Menu.h +++ b/CO2_Gadget_Menu.h @@ -1013,8 +1013,14 @@ void menuLoop() { return; } + if (activeWIFI) { + activeMQTTMenu[0].enable(); + } else { + activeMQTTMenu[0].disable(); + } + #if defined(SUPPORT_TFT) - if (wifiChanged) { + if ((wifiChanged) && (!inMenu)) { wifiChanged = false; tft.fillScreen(TFT_BLACK); } diff --git a/CO2_Gadget_WIFI.h b/CO2_Gadget_WIFI.h index 1b8ae63a..39a90e01 100644 --- a/CO2_Gadget_WIFI.h +++ b/CO2_Gadget_WIFI.h @@ -723,7 +723,7 @@ void wifiClientLoop() { // This is a workaround until I can directly determine whether the Wi-Fi data has been changed via BLE // Only checks for SSID changed (not password) - if (WiFi.SSID() != wifiSSID) { + if ((WiFi.SSID() != wifiSSID) && (!inMenu)) { Serial.println("-->[WiFi] Wi-Fi SSID changed. Old SSID: " + wifiSSID + ", new SSID: " + WiFi.SSID()); wifiSSID = WiFi.SSID(); putPreferences(); @@ -731,7 +731,7 @@ void wifiClientLoop() { wifiChanged = true; } - if (wifiChanged) { + if ((wifiChanged) && (!inMenu)) { wifiChanged = false; initWifi(); } diff --git a/platformio.ini b/platformio.ini index 45c22d42..47bb0d17 100644 --- a/platformio.ini +++ b/platformio.ini @@ -56,8 +56,8 @@ build_flags = '-DWIFI_PW_CREDENTIALS=""' -D MQTT_BROKER_SERVER="\"192.168.1.145"\" - -D CO2_GADGET_VERSION="\"0.8."\" - -D CO2_GADGET_REV="\"092-development"\" + -D CO2_GADGET_VERSION="\"0.9."\" + -D CO2_GADGET_REV="\"001-development"\" -D CORE_DEBUG_LEVEL=0 -DNEOPIXEL_PIN=26 ; Pinnumber for button for down/next and back / exit actions -DNEOPIXEL_COUNT=16 ; How many neopixels to control @@ -84,7 +84,7 @@ build_flags = -DMQTT_DISCOVERY_PREFIX="\"homeassistant/\"" -DESPNOW_PEER_MAC_ADDRESS="{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}" ; MAC Address of the ESP-NOW receiver (STA MAC). For unicast use peer address, as: {0xE8, 0x68, 0xE7, 0x0F, 0x08, 0x90} -DESPNOW_WIFI_CH=1 ; ESP-NOW WiFi Channel. Must be same as gateway - ; -DDEBUG_ARDUINOMENU + -DUEBUG_ARDUINOMENU ; -DMENU_DEBUG ; Needs streamFlow library -Os ; Optimize compilation for use memory -w ; Supress compilation warnings