Author: Costea Ciprian Marian
Master: AAC2
The purpose of this project is to develop a low power, portable weather station module, powered by solar energy. This module will be registered in the WeatherUnderground IBM Cloud platform where the queried sensor data can be observed. The module is based on a ESP32 platform, interfaced with a BME280 sensor capable of monitoring the environmental temperature, humidity and atmospheric pressure. Additionally, if needed, this data will also be able to be sent through the Firebase service for better visibility or debugging purposes.
The hardware schematics and wiring can be observed in the following image developed in Kicad
The ESP32 board is being powered through its 3.3V pin and the communication with the BME280 sensor is realized through the I2C protocol (SCL and SDA pins). With respect to the power input part of the hardware, the two solar panels connected in parallel are charging up the Lithium Li-Ion battery, through the TP4056 Lithium Battery Charger.
The real physical implementation can be observed in the image below:
The blue LED light of the ESP32 board indicates that the platform is in the processing state (Active Mode), has a valid WiFi connection and is querying/sending sensor data. Otherwise, the board is in the Hibernate State (Low Power consumption mode). Additionally, the red light from the TP4056 Lithium Battery Charger indicates that the Li-Ion battery is currently charging.
The following flowchart of the software architecture shows the states and transitions which the application will execute.
Note that primarily the software will send queried data to “wunderground” server and optionally to Firebase, based on the value set for a specific flag.
With respect to WiFi setup, if the ESP32 board cannot establish the connection in under 20 seconds the software logic will reset the platform in order to avoid any unconditional hangs, resuming its bloc logic execution from the very beginning.
One key aspect in the software architecture is that the 'loop' method, common to an Arduino project, will never be called because we enter a Hibernation state after each processing and transmission of the sensor queried data (performed in the 'setup' routine).
Regarding the transition to a low power consumption mode, the ESP32 platform supports 5 operational power modes:
For this project we chose the Hibernation Mode, which only keeps alive the RTC timer and some RTC GPIOs used for waking the platform up. In this mode the advertised power consumption is around ~2.5uA. The ESP32 core, WiFi, Bluetooth and other Peripherals will be inactive. In order to transition to Hibernation Mode, the following code snippet is used, in the setup routine. Note that in addition to setting up Deep Sleep for ESP32, we force RTC peripherals and RTC memories to powerdown in order to achieve Hibernation mode status.
#define TIME_TO_SLEEP 7 /* Time ESP32 will be in sleep state -- hibernation (in seconds) */ #define uS_TO_S_FACTOR 1000000 /* Conversion factor for micro seconds to seconds */ // configure wakeup source as the RTC Timer esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR); // force specific powerdown modes for RTC peripherals and RTC memories esp_sleep_pd_config(ESP_PD_DOMAIN_MAX, ESP_PD_OPTION_OFF); esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_OFF); esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_SLOW_MEM, ESP_PD_OPTION_OFF); esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_FAST_MEM, ESP_PD_OPTION_OFF); // Enter Hibernation mode esp_deep_sleep_start();
Sending the queried sensor data to the “wunderground” server is achieved by using HTTP requests as it can be observed in the following code snippet, along with the construction of the HTTP GET request.
String constructHttpGET(float temp, float humidity, float pressure) { String url = "https://weatherstation.wunderground.com/weatherstation/updateweatherstation.php?ID=<your_device_id>&PASSWORD=<your_device_passwd>&dateutc=now"; float tempf; // Convert temperature to Fahrenheit from Celsius tempf = (temp * 1.8) + 32; url += "&tempf=" + String(tempf); url += "&humidity=" + String(humidity); pressure *= 0.0296; // metric to US url += "&baromin=" + String(pressure); url += "&action=updateraw"; return url; } void wundergroundSendData(float temp, float humidity, float pressure) { HTTPClient httpClient; String urlSend; // Send Data to WunderGround Server urlSend = constructHttpGET(temp, humidity, pressure); Serial.println("URL to send: " + urlSend); httpClient.begin(urlSend.c_str()); Serial.println("Connected to wunderground server"); int httpResponseCode = httpClient.GET(); if (httpResponseCode > 0) { Serial.print("HTTP Response code: "); Serial.println(httpResponseCode); } else { Serial.print("Error code: "); Serial.println(httpResponseCode); } httpClient.end(); }
As it can be seen in the following images from the WeatherUnderground, under the page related to the registered device (in this case – IBUCHA284), the periodically queried BME280 sensor data is being received and displayed.
Among the challenges I've encountered while developing this project, sometimes, when powering the board, the voltage supplied would drop causing the brownout detection system from the ESP32 board to trigger, which leads to a platform reset. In order to bypass this issue, I've applied the following code in the setup routine, which successfully disables the brownout detection system from the ESP32.
#include "soc/soc.h" #include "soc/rtc_cntl_reg.h" ..... // disable brownout detector WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
More analysis with respect to usage of RTC memory in Deep Sleep as opposed to directly using Hibernation mode would be of interest. While Hibernation mode uses less power by not keeping the RTC recovery memory on, in Deep Sleep we could use this RTC memory to store any relevant data and maybe bypass some of the initialization mechanism. Some effort was invested in this regard, but the RTC_DATA_ATTR data type is not complex enough to support storing information regarding Wifi or Firebase status. Nevertheless, the tradeoff between Hibernation and Deep Sleep could be further explored.
Li-Ion battery level could be monitored by using the ADC module available on the ESP32 platform, taking into consideration that the battery outputs a voltage between 3.7V and 4.2V (when fully charged).
Since this project is finally intended to be installed outdoors, a platform connection through a low throughput, low data rate, low power and long distance communication protocol such as LoRaWAN would be more practical compared to WiFi.
A more suitable case/packaging could be built/developed for the hardware solution of this project.
https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf
https://esphome.io/devices/nodemcu_esp32.html
https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/sleep_modes.html
https://lastminuteengineers.com/esp32-sleep-modes-power-consumption/
https://randomnerdtutorials.com/esp32-deep-sleep-arduino-ide-wake-up-sources/
https://ksummersill.medium.com/hibernate-the-esp32-with-dht22-while-pushing-payload-data-to-aws-895b60c5774b
https://randomnerdtutorials.com/power-esp32-esp8266-solar-panels-battery-level-monitoring/
https://ocw.cs.pub.ro/courses/iothings/laboratoare/2022/lab4
https://randomnerdtutorials.com/esp32-bme280-arduino-ide-pressure-temperature-humidity/