Software Explanation and Overview

 

Boot and WAKE timing

Using my desired setting for waking up every 15 min as an example.

  • Initial BOOT has no frame of reference on timing yet, so system will WAKE in 3 seconds

  • 1st WAKE will the calibrate itself to happen on an orderly time boundary. In my example( 15 after, 30 after, 15 til hour, top of the hour). Note: WAKE time is pulled forward 60 seconds to ensure data is refreshed slightly ahead of my e-ink display (MQTT subscriber)

  • Subsequent WAKEs will be at time interval on the boundaries described above.

General Software Organization

This project can grow quickly. I determined early that placing the project in one .cpp file might turn out to be a bad idea for me and I wanted to break up the project to avoid a single, massive file that I’d regret maintaining. I like to steer clear of technical debt.

ESP32 and Deep Sleep

Deep sleep on the ESP32 basically results in a reboot of the microcontroller. We do have basic visibility as to the reason we woke up (timer event or pin interrupt, for instance). We have access to a special SRAM location in the RTC module that we can use to store critical values we need to persist. Normal variables will be lost.

When creating a project or application that uses deep sleep, you must determine what data needs to persist when the device reboots. Rainfall amount is a must. All other sensor values are read, but not stored, just transmitted to a data storage location for further evaluation. One might think that temperature high/low data should be kept, but I chose to move that data analysis off the sensor station responsibilities.

Data Structures

The sensorData structure is a wrapper to keep all the sensor data values. This structure is not persistent in RTC SRAM.

The historicalData structure is used to hold hourly and 24h rainfall data. Any variables with the RTC_DATA_ATTR store the variable in RTC SRAM and can be accessed on after a WAKE event. RTC memory is cleared on RESET.

bootCount was used extensively in my debug efforts on the unintentional RESET issues.

 

//=========================================== // Custom structures //=========================================== struct sensorData { float temperatureC; float temperatureF; float windSpeed; float windDirection; float barometricPressure; float BMEtemperature; float humidity; float UVIndex; float lux; float batteryVoltage; int batteryADC; }; //rainfall is stored here for historical data uses RTC struct historicalData { unsigned int hourlyRainfall[24]; unsigned int current60MinRainfall[12]; }; //=========================================== // RTC Memory storage //=========================================== RTC_DATA_ATTR volatile int rainTicks = 0; RTC_DATA_ATTR int lastHour = 0; RTC_DATA_ATTR time_t nextUpdate; RTC_DATA_ATTR struct historicalData rainfall; RTC_DATA_ATTR int bootCount = 0;

Notes about deep sleep

As I researched regarding people not finding the deep_sleep header file, I found it may not be needed.

  1. Comment out the header file #include statement (or remove it)

 

//=========================================== // Includes //=========================================== //#include "esp_deep_sleep.h"

 

2. change the sleep timer call from

esp_deep_sleep_enable_timer_wakeup

to

esp_sleep_enable_timer_wakeup

void sleepyTime(long UpdateIntervalModified) { Serial.println("\n\n\nGoing to sleep now..."); Serial.printf("Waking in %i seconds\n\n\n\n\n\n\n\n\n\n", UpdateIntervalModified); //updateWake(); esp_sleep_enable_timer_wakeup(UpdateIntervalModified * SEC); esp_sleep_enable_ext0_wakeup(GPIO_NUM_25, 0); esp_deep_sleep_start(); }

This change will be part of my next master version (v1.3)

Low Battery Mode

When measured battery is > 15% remaining a flag is set to multiply the wake time interval by 4. In my case, 15 min will turn into 60 min for data reporting.

Rainfall Measurement

Hourly subtotals are stored hour by hour and added to report last 24 hour totals. The system also reports the current hour rainfall.

One tip in the rainfall gauge is 0.011" (0.2794 mm) of rain.

Look for a software update: rainfall is reporting current hour, not the last 60 minutes. Also, technically, the last 23 hours are summed, not last 24 hours.

Wind Speed Measurement

This routine is still in testing, but currently uses multiple switch closures to measure wind speed on the anemometer. Not fully certain that this is bug free.

Rough math

Vendor of anemometer states “A wind speed of 2.4km/h causes the switch to close once per second.“, so this is our calibration target. They never state the measurement in terms of revolutions per second.

If they expect x1 per revolution then…

cup path circumference = .666m = 2(3.14)(.106m), so radius of arm is .106m, or 4.17 inches

If they expect x2 per revolution then…

cup path circumference = 1.333m = 2(3.14)(.211m), so radius of arm is .211m, or 8.31 inches

The math supports an arm radius of .106m. The datasheet is giving us the impression that x1 closure of relay per second is the basis for their calibration information. This is why I make the assertion that my calculations are off/high by 2x and subsequently divide by 2.

Speed Mi/h)

Speed (km/h)

Speed (m/s)

Angular Velocity (rev/sec) @1x

Angular Period (ms/rev) @1x

Angular Period (ms/rev) @2x

Speed Mi/h)

Speed (km/h)

Speed (m/s)

Angular Velocity (rev/sec) @1x

Angular Period (ms/rev) @1x

Angular Period (ms/rev) @2x

1.5

2.4

.667

1

1000

500

14.9

24

6.667

10

100

50

31.1

50

13.889

20.9

47

24

62.1

100

27.778

41.7

23

12

149.1

240

66.667

100

10

5

Theory of Operation

I make us of the time to negotiate the WiFi connection to measure wind speed in the background with an ISR. I collect ∆t information in an array and allow for up to 6 samples to average. I reject ∆t measurements below 10ms as a software debounce.

 

Wind Direction Measurement

It interests me that the lowest ADC value is 263, but we are looking for values below 150. While I refactored the original code, I did not adjust that target. I’m guessing the ADC has non-linearities that are the cause of this.

Measure all R values in wind vane
It appears the original code does not reflect NORTH as outlined by the vendor data sheet. It’s subjective and can be calibrated to any frame of reference. I’ll need to be very bored to fix this.

Wind Vane Calibration

I’m showing North as the wind vane bullet points to the anemometer. Adjust mast accordingly.

EEPROM Module (v 1.2 or greater supports this hardware)

 

This is an optional module I threw together for those that want to be 100% certain they do not lose rainfall data due to RESET events. I have access to many serial NVMs at work and used a 512Kb or 64KB NVM. I only currently am using 144B for storage. A 24C512 from Atmel/Microchip was used in my case.

  • Hardware RESET events are covered by LDO upgrade

  • Still see very intermittent RESET events (MQTT broker goes off line, no internet connectivity, stuff out of my control, etc)

    • If this scenario concerns you, then you may wish to build this module

  • I could have certainly used ESP32 onboard EEPROM, but in the unlikely event of write endurance failure, I just replace the module, not the entire ESP32.

The EEPROM routine stores rainfall history structure to NVM in parallel with the RTC memory values. The routine is written to only execute writes to memory if something has changed. This conserves write endurance, although the memory I use has 1M cycle endurance.

There is a compiler directive to enable or disable this functionality.

Initial Evaluation Results

I was able to force RESET events and 24hour rainfall totals remain. Rainfall (hourly) totals RESET at the top of the hour as they should.

MQTT Topics

Topic Name

Purpose

Topic Name

Purpose

batteryADC

ADC reading of VBAT divider

batteryVoltage

Calculated VBAT

boot

boot counter

caseTemperature

temperature at PCB

ESPCoreC

ESP internal core temperature in deg C

ESPCoreF

ESP internal core temperature in deg F

lowBattery

bool indicator of <15% battery remaining

lux

light level

photoresistor

ADC value for photoresistor

pressure

barometric pressure

rainfall

current hour rainfall

rainfall24

current 24 hour rainfall

relHum

relative humidity

temperatureC

temperatureC value at DS1820B probe

temperatureF

temperatureF value at DS1820B probe

UVIndex

UVIndex

windDirection

wind heading

windCardinalDirection

cardinal direction

windSpeed

wind speed indicator

 

Sensor Datasheets

  File Modified

PDF File windandrainsensors.pdf

Aug 24, 2021 by James Hughes

PDF File bh1750fvi-e.pdf

Aug 24, 2021 by James Hughes

PDF File BST-BME280_DS001-10.pdf

Aug 24, 2021 by James Hughes

PDF File DS18S20.pdf

Aug 24, 2021 by James Hughes

PDF File Si1145-46-47.pdf

Aug 24, 2021 by James Hughes