Audio Rain Sensor and Window Open Detector

by drmpf in Circuits > Arduino

496 Views, 3 Favorites, 0 Comments

Audio Rain Sensor and Window Open Detector

mainImage.jpg
rainDetectorESP32.jpg
bathroomWin.jpg
BLEtoTelnetBridge_outside.jpg
monitorComplete.jpg

This Audio Rain Sensor is very sensitive and can detect individual rain drops. It uses two (2) MEMS microphones, in stereo mode, one to listen for rain drops falling on a metal plate and one to listen to the ambient noise. An ESP32, which has a Floating Point Unit (FPU) and dual cores, is used. One core is dedicated to processing the microphone inputs, while the second core is dedicated to handling the WiFi connection. A novel floating point Fourier Transform (modified Goertzel) is used to calculate the magnitude of the signal in a small range of frequencies with better frequency resolution then a standard power of 2 discrete FFT.

The BLE Window Open sensors are very low power and will run for years on a coin cell. A BLE to WiFi bridge is used to collect the window sensor states and make them available via a web server.

The Rain Alert Monitor combines the Rain Sensor telnet data stream with the BLE Window Open sensors' state to trigger an alert, either buzzer or voice prompt, when it starts raining and a window has been left open. It includes a web page interface to show the current rain state and which windows are open

While this project includes BLE Window Open detectors, you can, optionally, to just use the Audio Rain Sensor and Rain Alert monitor to alert you when it starts and stops raining. The receiver announces a warning to “Close the Window” using Dfrobot's Voice Prompt Module. This also project covers how to change the warning to one of your own. Alternatively you can just use a buzzer alert.

This project is also on line at Rain Sensor and Window Open Detector and supersedes the Window Open and Rain Detector and Hydreon RG-9 projects. The three units, Audio Rain Sensor, BLE Window Open sensors and the Rain Alert Monitor are all connected by WiFi so they can placed around the house in convenient locations.

This project will cover:-

  1. Construction of a metal sounding board for the rain drops to strike.
  2. Setting up stereo MEMS microphones to listen to the rain drops and the surrounding ambient noise.
  3. Splitting the stereo into mono streams and streaming them to WAV files on an SD card.
  4. Using Audacity to view the recorded streams and isolate rain drop pulses.
  5. Using the modified Goertzel Fourier Transform to analyse the spectrum of the rain drop pulses and choose significant frequency range.
  6. Comparing the insides to outside (ambient noise) signals to determine cut-off ratio and magnitude of a rain drop pulse.
  7. Testing the Rain Sensor using previously recorded signals.
  8. Setting up a telnet server to serve the current state (Rain/Dry) at 1sec intervals.
  9. Setting up a web server to serve the Open/Close states of the BLE open window detectors
  10. Setting up the Rain Alert Monitor that combines the data from the Rain Sensor and Open Windows detector to raise an alarm when it starts to rain and window has been left open.
  11. Recording your own Alert announcement for Dfrobot's Voice Prompt Module.

Supplies

The Parts List. (Prices as at 30th August 2024 excluding shipping)

Audio Rain Sensor

Box :-

Scrap wood – 89mm x 22mm (3.5” x 7/8”) ~1200mm length

Scrap flashing – 300mm x 135mm x 0.35mm (zinc coated steel)

Assorted wood screws. Silastic / thin foam strips

Sensor:-

2 x Dfrobot Fermion: I2S MEMS Microphone (Breakout) SKU:SEN0526 ~ US$9.80 (total)

1 x Dfrobot FireBeetle 2 ESP32-E IoT Microcontroller SKU:DFR0654 ~ US$8.90

1 x Dfrobot USB 3.0 to Type-C Cable SKU:FIT0641 ~ US$1.95

1 x Dfrobot SD/MicroSD Memory Card (16GB Class10 SDHC with Adapter) SKU:FIT0394 ~ US$10.90 (Note: max SD card size should be <= 32GB)

1 x Dfrobot Plastic Project Box Enclosure Waterproof Clear Cover - 5.83 x 3.70 x 2.36 inch SKU:FIT0724 ~ US$9.50 OR Jaycar HB6249 ~US$14.00

1 x Dfrobot ProtoBoard Pro - Double Sided (100x75mm) SKU:FIT0193 ~ US$3.15 OR Jaycar HP9550 ~US$3.90

1 x Adafruit Micro SD SPI or SDIO Card Breakout Board - 3V ONLY ID: 4682 ~ US$3.90

Optionally add a second FireBeetle, USB Type-C cable, 16GB sd card and Adafruit SD breakout board so you can both record wav forms while processing the previous ones.

Rain Monitor

1 x Dfrobot FireBeetle 2 ESP32-E IoT Microcontroller SKU:DFR0654 ~ US$8.90

1 x Dfrobot USB 3.0 to Type-C Cable SKU:FIT0641 ~ US$1.95

1 x Dfrobot Plastic Project Box Enclosure Waterproof Clear Cover - 5.83 x 3.70 x 2.36 inch SKU:FIT0724 ~ US$9.50

1 x Dfrobot ProtoBoard Pro - Double Sided (100x75mm) SKU:FIT0193 ~ US$3.15

1 x Dfrobot Voice Prompt Module with Integrated MP3 Player and Speaker SKU:DFR1173 ~ US$7.90 OR Jaycar buzzer AB3462 ~US$3.90

BLE to WiFi Window Open Bridge

1 x Room Sensor Enclosure - Small Vented (Size 3) Core Electronics CE08507 ~US$3.10

1 x Seeed Studio XIAO ESP32-C3 ~ US$5.00

1 x Dfrobot USB 3.0 to Type-C Cable SKU:FIT0641 ~ US$1.95

Window/Door Open Detectors

As per BLE Window/Door Open Detector and Rain Detector

Construction of a Metal Sounding Board Rain Sensor

RainDetectorLidOff.jpg
rainDetectorInsideMic.jpg

The metal sounding board, that listens for rain drops, consists of a solid wooden box with and open top to which a thin sheet of scrap flashing (0.35mm thick, zinc coated) is secured. The 300mm x 89mm x 135mm (external dimensions) was constructed from scrap 3.5” x 7/8” timber, painted and the internal joins sealed with silastic. One of the microphones was mount at one end of the box and the 300mm x 135mm flashing secured to the top, loosely, with two screws. The top is secured so that is has some very slight movement and the screws have generous clearance holes in the flashing.

The dimensions of the box are not very strict. You could probably make it half the size. See below for how to determine the frequency response of the box and metal plate.

Setting Up Stereo MEMS Microphones to Listen to the Rain Drops and the Surrounding Ambient Noise.

bottomOfRainDetector.jpg
rainDetectorESP32.jpg
AudioRainSensor_sch.jpg

The ESP32 and the second microphone are mounted in the plastic enclosure which is screwed to the bottom of the box. The second microphone is mounted in a slot filed in the side of the enclosure so that the MEMS chip is external to the enclosure and facing towards the bottom of the box. In this position when the box is mounted outside the microphone is protected from direct rain by the box and from splashes, by facing up.

The circuit (pdf version) of the Rain Sensor is trivial. Two microphones wire in stereo, an ESP32 and an SD module. The SD module is only used for setting-up / tuning.

Programming Setup

Install the ESP32 board support V3.0.3 (other versions may or may not work)

See https://docs.espressif.com/projects/arduino-esp32/en/latest/installing.html for instruction. Choose V3.0.3 from the drop down version. This version is used for most but not all of the code here.

NOTE: A different version of the board support, V2.0.6, is used for the BLE to Web Window Open server. See that section below.

Select Board “Fire Beetle ESP32-E” and the Partition Scheme “Default 4MB with spiffs (1.2MB APP / 1.5 MB SPIFFS)”

Rename your existing libraries dir to some other name (e.g. libraries_mine) in the Arduino sketch directory and unzip this libraries.zip file to the Arduino sketch directory to install the necessary libraries. This same set of libraries is used for all the code here. The installation of the various sketches used in this project are covered below where they are used.

Note: The BLE Window Open Detectors use a special modified board support for very low power BLE see BLE Window/Door Open Detector and Rain Detector for installation and programming details.

Splitting the Stereo in to Mono Streams and Streaming Them to WAV Files on an SD Card.

The first sketch, ESP32_Mic_SD.ino, creates a task to read the stereo signal from the two microphones and pass the buffers to the loop() code to split into two mono streams and average every 4 samples to down sample to 4000 samples/sec. These mono streams are then written to two wave files, RecInside.wav and RecOutside.wav, on the SD card.

The two wave files are zero padded after the header, up to the first 512 bytes in the file. Subsequent writes are in multiples of 512 bytes. The 'length' of the WAV file data size, in the header, is set to a very large number, 1e9 bytes. Audacity, and this project, both ignore that number and uses the actually size of the file to determine the number of samples in the file. This means the header does not need to be rewritten as extra samples are added to the file.

The recording of the signal from the microphones is double buffered. As one rec_buffer is being filled the other is being processed and written to the SD card (max 32GB in size). Each rec_buffer read via I2S takes 250ms to read from the microphones, while the processing and SD write takes about 60ms. This means there is usually enough time for the SD card to write the previous buffer. However if a delay is detected in processing and writing the wav files then a message is logged to the log file, log.txt, with the time, in sec, when the delayed occurred.

To minimise the likelihood of delays in writing to the SD card, format the SD card before each run using SD Card Formatter

Each WAV file is flushed to the SD card every 10sec so you can power down or remove the SD card whenever you want to stop.

Using Audacity to View the Recorded Streams and Isolate Rain Drop Pulses.

RainStart.jpg
RainStart_amplified.jpg
Audacity_FFT_RainPulse.jpg

Having recorded wave forms from the two microphones, you can used Audacity to inspect them and isolate a rain drop pulse (or a hose drop pulse).

Install Audacity from https://www.audacityteam.org/download/ No extra libraries or add-ons are needed for this project.

Drag the RecInside.wav file into Audacity. Scroll to a rain section and highlight and expand a short part of the file, 60sec or so, to fill the width of the window.

If you cannot identify any rain section, highlight the whole file, (click on the bar above the wave form) and choose Effect → Volume and Compression → Amplify

Once you have found a small section, highlight it and note the time and length in the selection panel at the bottom. Close the file and re-import it without the Amplification and type in the time and length to re-select the range.

Choose File → Export Audio... and choose Current Selection and save this small section of the wav file to a new file.

Close the RecInside.wav and import the RecOutside.wav file and enter the exact same time and length for the selection and export that selection as well.

Rec_rainStart.zip contains the Inside and Outside records of an 7sec sample of rain just starting. Open it and drag the two files into Audacity.

In the first image above, the rain pulse as hard to see so highlight the Inside WAV and use Effect → Amplify to enlarge it. Then highlighted the Outside WAV and use Effect → Repeat Amplify to apply the same amplification to that waveform. (Second Image above)

As you can see the rain drop signal is many times louder than the outside noise.

Highlight one of the pulses in the RecInside WAV and choose Analyze → Plot Spectrum... (see third image above

Note the peak in the response around 200Hz and another around 700Hz and two more at multiples of 700Hz. These are the two main resonances for the metal plate. The 700Hz range was chosen to detect rain drop pulses because any ambient noise at the higher frequencies are better attenuated by the box.

Using the Modified Goertzel Fourier Transform to Analyse the Spectrum of the Rain Drop Pulses and Choose Significant Frequency Range.

FT_rainStart.jpg
FT_100ms_rainPulse.jpg
FT_100ms_660Hz_770Hz.jpg

Click on the above images to see them unclipped

OneRainPulse.zip, isolates just one rain drop pulse 0.1sec long. Copy OneRainPulse.wav (from OneRainPulse.zip) to the SD card and rename it sound.wav

Compile and run the ESP32_SD_FT.ino sketch. This sketch reads 0.1sec (400 samples at 4000Hz) from sound.wav at the time offset set by float startTimeOffset and calculates an 800 point Fourier Transform using the modified Goertzel method.

The modifed Goertzel method has a number of advantages over the usual (discrete) FFT (Fast Fourier Transform). The Goertzel method works with any number of sample points, not just powers of 2, calculates the results for one frequency at a time and can calculate the result for any frequency up to the Nyquist Frequency (one half the sampling frequency. i.e. 2000Khz in this case). The frequencies calculated are not limited to discrete frequencies of the usual discrete FFT.

In this case the magnitudes of 800 evenly spaced frequencies in the range 0 to 2000Khz are calculated. A discrete (power of 2) FFT of 400 points would zero pad to 512 points and then calculate 256 evenly spaced frequencies. Geortzel gives better frequency resolution which can be arbitrarily increased. The results are written to the ft.txt file in csv format. The magnitude values are scaled down by 1e-5 to avoid ovf outputs from Arduino's print(float) method.

Loading ft.txt into a spreadsheet and plotting the results gives the first image above. This is for a light rain pulse just as the rain is starting.

The second image above is the result for a hose (heavy rain) pulse.

To allow for variations in the resonant frequency as the metal lid accumulates water, the Audio Rain Sensor looks for the maximum magnitude over the range of 660Hz to 770Hz (third image above) and compares this to the maximum magnitude of the outside ambient noise in the same range. A ratio of Inside / Outside is used to compensate for varying rain strengths. Heavier rain means more outside noise.

Using Geortzel, only frequencies in the range of interest are calculated at about 4 times the frequency resolution obtainable by a power of 2 FFT. The floating point processor of the ESP32 makes this an efficient and practical process.

It is common to apply a windowing function which tails off the signal to zero at the start and end before calculating the Discrete Fourier Transform. As can be seen in the Audacity screen shot above, the rain drop pulses are typically less than 0.1sec in length and are already zero at the start and the end, so no windowing is applied (i.e. a rectangular window is used).

Comparing the Insides to Outside (ambient Noise) Signals to Determine Cut-off Ratio and Magnitude of a Rain Drop Pulse.

ratios_startRain_wav.jpg

For moderate to heavy rain, inside magnitude and ratio of inside/outside magnitudes in the 660Hz to 770Hz frequency range are large. However when the rain is just starting it is often very light with just a few drops. So we need to determine the minimum inside magnitude and the minimum inside/outside ratio that indicates a rain drop pulse.

Rain drop pulses are about 0.1sec long so that is the size of the wave sample that is processed by the Fourier Transform, but to improve the detection, each 0.1sec interval is overlapped by 0.05sec with the previous one. That is the input wave forms are updated in 0.05sec intervals and Fourier Transform is performed on the last 0.1sec of the input. Because of this overlap, the code can generate multiple pulse outputs for a single rain drop.

As shown above Rec_rainStart.zip contains 7secs of a 5 light rain drop pulses as the rain is starting.

To calculate the ratio and the inside and outside magnitudes (and maximum frequencies) of this wave form, copy the files from Rec_rainStart.zip to the SD card and rename them RecInside.wav and RecOutside.wav.

Unzip the ESP32_SD_Mic_RS.zip to create the ESP32_SD_Mic_RS sketch directory. As supplied ESP32_SD_Mic_RS.ino is setup for normal running as a rain sensor with a Telnet server to server the current state (Dry/Rain). To use this sketch to test pre-recorded WAV files there are two defines near the top of the ESP32_SD_Mic_RS.ino file.

//#define TESTING BACK_TESTING
//#define TESTING DUMP_ALL_RATIOS_AND_MAGNITUDES

Un-commenting either of these disables the microphones and WiFi and just processes the RecInside.wav and RecOutside.wav files from the SD card.

To write out each ratio and magnitude, un-comment

#define TESTING DUMP_ALL_RATIOS_AND_MAGNITUDES

The resulting mag.txt contains the ratios and magnitudes (and frequencies) for each 0.1s interval moving 0.05s at a time. The magnitude numbers are scaled down by 1e-5 to prevent Arduino printing ovf

Loading that mag.txt file into a spreadsheet allows you to plot the ratios (RED) and magnitudes (YELLOW). Lining those up with the WAV gives the image above.

Using this information, a minimum ratio of 20 and a minimum inside magnitude of 5000 were chosen. That is the maximum inside magnitude in the range 660Hz to 770Hz must be >= 5000 (x 1e5) in order to be considered as a rain pulse. In addition the ratio of the maximum inside to outside magnitude must be >= 20. Only then will the signal be tagged as a rain pulse.

These values are set at the top of the ProcessingBuffers.cpp file in the ESP32_SD_Mic_RS sketch directory. The only other thing to do is to ignore single pulses that could be from a branch or a bird landing on the metal plate. ProcessingBuffers.cpp does this in two ways. It does not set the bool isRaining variable true until :-

Either

1) there have been 1.5sec of pulses with no more then 0.5sec gap between them

Or

2) there have been 8 pulses within 10secs (using a moving average over the last 40 x 0.25sec intervals).

Once isRaining is set true, it remains true until there has been 10secs with no pulse detected.

These settings can be adjusted by editing the values at the top of the ProcessingBuffers.cpp file.

Testing the Sensor Using Previously Recorded Signals.

Now that a plausible set of values have been determined for sensing rain start/stop, you can go back and test using the previously recorded wave forms obtained from ESP32_Mic_SD.ino. Copy the inside and outside wav files to the SD card and rename them RecInside.wav and RecOutside.wav. Edit the top of the at the top of ESP32_SD_Mic_RD.ino to un-comment

#define TESTING BACK_TESTING

to process the test files and log the detected pulses and the start and stop of the rain. The log.txt file contains the output from processing the Rec_rainStart.zip files (renamed to RecInside.wav and RecOutside.wav)

================= Opening Log File ================
Pulse Detection Settings:-
deltaT:0.05
minRatio:20.00
minMag inside:5000.00
noRainStartDeltaTCount:10
startRainDeltaTCount:30
rainStoppedDeltaTCount:200
pulseDeltaTCountUpdate:5
noOfPulseUpdatePoints:40
MIN_CUMULATIVE_PULSES:8

time,ratio,Inside_Max,Inside_Hz,Outside_Max,Outside_Hz,isRaining
0.150,77.8345,12995.82,700.00,166.97,732.50,0
0.200,108.9323,14194.51,700.00,130.31,720.00,0
0.750,,,,,,0, >> start rain timed out - no pulse
2.550,156.5123,21158.82,697.50,135.19,725.00,0
2.600,161.1716,27243.72,697.50,169.04,720.00,0
2.650,40.8051,6767.98,697.50,165.86,730.00,0
3.150,40.7449,7881.14,695.00,193.43,725.00,0
3.200,48.2422,8694.43,697.50,180.22,705.00,0
3.750,,,,,,0, >> start rain timed out - no pulse
4.700,21.1219,7949.80,697.50,376.38,660.00,0
4.750,30.4593,6000.30,700.00,196.99,700.00,0
4.750,,,,,,0
4.750,,,,,,1, >> Rain Started - cumulative pulses
6.550,34.7398,10667.54,697.50,307.07,700.00,1
6.600,35.0148,10665.38,697.50,304.60,707.50,1

In this case the Rain Sensor reported Rain after the first 4 drops, i.e. in less then 5sec.

Setting Up a Telnet Server to Serve the Current State (Rain/Dry) at 1sec Intervals.

Having tuned the Rain Sensor for frequency range and signal level and single pulse rejection, the telnet server can be programmed into the ESP32. As supplied ESP32_SD_Mic_RS.zip is setup for normal running as a rain sensor with a Telnet server to server the current state (Dry/Rain). Install the supporting libraries. Rename your existing libraries dir to some other name (e.g. libraries_mine) in the Arduino sketch directory and unzip this libraries.zip file to the Arduino sketch directory to install the necessary libraries. This same set of libraries is used for all the code here.

Make sure, after testing, that these two defines near the top of the ESP32_SD_Mic_RS.ino file are commented out.

//#define TESTING BACK_TESTING
//#define TESTING DUMP_ALL_RATIOS_AND_MAGNITUDES

Then program the Dfrobot Firebeetle ESP32-E with ESP32_SD_Mic_RS.ino (using the ESP32 board support V3.0.3). This is the operational Rain Sensor. This sketch uses ESPAutoWiFiConfig to connect to your WiFi network. If there is no network configured OR the ESP32 cannot connect, the Green led on the Firebeetle will flash rapidly and the ESP32 it will create an AccessPoint, SSID: WiFiConfig, password: 12345678 that you can connect to, to configure your network and the IP address for the Rain Sensor. See ESPAutoWiFiConfig for more detailed instructions.

Rain Sensor Code

The rain sensor splits its functions between the two (2) ESP32 cores.

The 'Arduino' core (core 1) runs the microphone recording and processing. A task gets the stereo signals, in blocks of 0.05sec at 16000Hz, double buffers them and passes the buffers to the main loop() code which processes the recordings in 0.1sec blocks, overlapped by 0.05sec on each update. The i2s recording process uses direct memory access (DMA) with bypasses the CPU. This leaves the loop() code running on core 1 it free to process the preceding block. This ensures no data is missed.

The second core (core 0) of the ESP32 is dedicated to handling the WiFi / Telnet connection. This code is base in the High Speed ESP32 Control project which uses a modified version of AsyncTCP, HS_AsyncTCP.zip. The HS_AsyncTCP code ensures that all the WiFi / Telnet processing occurs on core 0 so that it does not interfere with the microphone signal processing. Communication between these two cores is via volatile variables, defined in VolatileVars.h. The ESP32 is 32bit processor that loads 4bytes (32bits) in a single instruction so 4 byte data reads / writes do not need to be locked to complete successfully. So there are no locks in this code which simplifies the programming.

The telnet server provides data on the current state of the Rain Sensor at one (1) second intervals, see WiFiDataHandling.cpp, using the volatile variables updated by the ProcessBuffers.cpp code. The data transmitted in is csv format:-

last change count, State, current count(*0.05s), pulses/sec, maxRatio, maxRatioMag

The state is the important data and is either Dry or Rain. The other data provides some insight into the sensor's operation. The current count is the number of 0.05s samples since the last reboot. The last change count is the count at which the Dry / Rain state last changed. The calculation, current count – last change count * 0.05 , will give the number of seconds that the sensor has been in its current state. Note the current count will not overflow for about 136 years.

The pulses/sec is the number of detected rain pulses in the previous second. The maxRatio is the highest inside/outside ratio measured in the previous second. The maxRatioMag is the magnitude of the inside signal for that maxRatio.

Using TeraTerm to connect, via port 23, the rain sensor gives this output:-

1073043,Dry, 1194342 , 0 , 2.4 , 346
1073043,Dry, 1194362 , 0 , 3.3 , 329
1073043,Dry, 1194382 , 4 , 436.2 , 77090
1073043,Dry, 1194402 , 1 , 257.8 , 29318
1194405,Rain, 1194422 , 3 , 325.9 , 52396
1194405,Rain, 1194442 , 0 , 3.2 , 378
1194405,Rain, 1194462 , 0 , 4.6 , 723
1194405,Rain, 1194482 , 0 , 3.4 , 504
1194405,Rain, 1194502 , 0 , 3.2 , 524
1194405,Rain, 1194522 , 0 , 2.6 , 321
1194405,Rain, 1194542 , 0 , 1.6 , 187
1194405,Rain, 1194562 , 0 , 3.2 , 422
1194405,Rain, 1194582 , 0 , 3.3 , 405
1194405,Rain, 1194602 , 0 , 4.1 , 397
1194606,Dry, 1194622 , 0 , 2.9 , 348
1194606,Dry, 1194642 , 0 , 2.7 , 275
1194606,Dry, 1194662 , 0 , 3.9 , 305
1194606,Dry, 1194682 , 6 , 335.1 , 76916
1194685,Rain, 1194702 , 4 , 568.5 , 52719
1194685,Rain, 1194722 , 0 , 3.8 , 330
1194685,Rain, 1194742 , 4 , 506.3 , 55888

Indicating that it had been Dry for 101 mins, then detects Rain drops and then after 10 secs of no further rain drops switches to Dry for 3.95 secs and then detects Rain drops again.

Setting Up a Web Server to Serve the Open/Close States of the BLE Open Window Detectors

bathroomWin.jpg
BLEtoTelnetBridge_inside.jpg
BLEtoTelnetBridge_outside.jpg
WindowsOpenWebpage.png

The BLE window open detectors construction and programming are described in detail in BLE Window/Door Open Detector. (first image above)

The BLE to Web Server Bridge

The BLE to Web Server bridge scans for the current state of the open/close BLE detectors and provides the data to a web page. The circuit consists of just an single XIAO ESP32C3 board.

The BLE to Web Server bridge also runs ESPAutoWiFiConfig to let you connect to your network and set the device's static IP. See ESPAutoWiFiConfig for the details. Here the config/connected indicator led has been omitted (pinNo is 0) but you can add another connection led to a spare XIAO output if you wish.

Programming the BLE to Web Server Bridge

The BLE to Web Server Bridge requires a specific version of the ESP32 Arduino board support, V2.0.6.

Close Arduino and rename the Arduino15 directory to Arduino15_esp32_3_0_3. The location of the Arduino15 directory is shown in File → Preferences at the bottom of the dialog box.

Then restart Arduino and install the ESP32 board support V2.0.6 (other versions may not work) See https://docs.espressif.com/projects/arduino-esp32/en/latest/installing.html for instruction. Choose V2.0.6 from the drop down version selection.

Unzip WindowOpen_ESP32C3_BLEtoWebServer.zip to your Arduino sketch directory. Rename your existing libraries dir to some other name (e.g. libraries_mine) in the Arduino sketch directory and unzip this libraries.zip file to the Arduino sketch directory to install the necessary libraries. This same set of libraries is used for all the code here.

Select Board “XIAO_ESP32C3” and the Partition Scheme “Huge APP (3MB No OTA/1MB SPIFFS)

You need to edit the expectedDevices names to match the names of your Window Open BLE devices and then program the XIAO ESP32C3 board. Use ESPAutoWiFiConfig to setup your WiFi network connection and this server's IP. You can uncomment the #define DEBUG near the top of the file to get info of the BLE devices found

Connecting to the web server, e.g. http://10.1.1.202 gives this page which updates every 5 sec.

Opening the URL http://10.1.1.202/status gives the following text output. This is the output used by the Rain Alert Monitor.

Back_Bedroom_Win_Rhs,C
Back_Bedroom_Win_Lhs,C
Front_Bathroom_Win,C
Front_Bedroom_Win_Lhs,O
Front_Bedroom_Win_Rhs,O

The state of each window is either C for closed or O for open or B for bad, i.e. no status update from the BLE module in the last 220sec.

Setting Up the Rain Alert Monitor

monitorComplete.jpg
monitorBoardBottom.jpg
RainMonitor_buzzer.jpg
RainMonitor_voice.jpg
UsbCableConnection.jpg
monitorWebpage.png

The Rain Alert Monitor combines the data from the Rain Sensor and Open Windows server to raise an alarm when it starts to rain and a window has been left open.

There are two versions of the circuit. Each of them is trivial. Just the Firebeetle ESP32-E board and either a buzzer AB3462 or Dfrobot's Voice Prompt Module

The first two images abover are for the Voice Prompt version.

The circuits are (again) trivial. Busser version pdf and Voice Prompt version pdf

Construction

Trim the corners of the Dfrobot ProtoBoard Pro to fit in the Dfrobot Plastic Project Box. Drill two holes for small self tapping screws to hold the board in place. File a notch in the lip for the USB power cable and drill a series of holes on each side to allow the sound of the buzzer / voice prompt to exit.

Before wiring up the Voice Monitor, load it with the prompt .mp3 file you want played when it starts raining and there is a window open. As delivered the Voice Prompt Module has two files. Plug in the USB cable as shown here. NOTE Carefully: the red lead goes to the 5V pin and the silver side of the plug faces the 5V... GND labels. (See the image above)

The Voice Prompt Module will appear as a disk drive on your computer. Delete the two .mp3 files and copy your prompt as 001.mp3. An example prompt file is here(See the next section for how to make your own.)

To test the message touch the P1 pin to the GND lead.

Once you have loaded your message and tested it, you can wire it into the board. Be very careful when wiring up the Voice Prompt module to correctly connect the 5V and GND pins.

Programming

The same RS_ESP32_Monitor.ino sketch supports both of these circuits.

Install the ESP32 board support V3.0.3 (other versions may or may not work) See https://docs.espressif.com/projects/arduino-esp32/en/latest/installing.html for instruction. Choose V3.0.3 from the drop down version. This version is used for most but not all of the code here.

Select Board “Fire Beetle ESP32-E” and the Partition Scheme “Default 4MB with spiffs (1.2MB APP / 1.5 MB SPIFFS)”

Rename your existing libraries dir to some other name (e.g. libraries_mine) in the Arduino sketch directory and unzip this libraries.zip file to the Arduino sketch directory to install the necessary libraries. This same set of libraries is used for all the code here. The installation of the various sketches used in this project are in their respective sections.

Unzip RS_ESP32_Monitor.zip to create the RS_ESP32_Monitor sketch directory. Set the length of the prompt and the delay between repeats

const unsigned long MSG_LENGTH_ms = 18000; // length of msg
// use the MSG_DELAY to adjust time between repeats of msg when raining and window open
unsigned long MSG_DELAY_ms = MSG_LENGTH_ms + 30000; // delay between repeats of msg 30sec

Program the Firebeetle ESP32-E with that sketch. Use ESPAutoWiFiConfig to setup your WiFi network connection and this monitor's. Connecting to the monitor's webserver, e.g. http://10.1.1.203 shows the web page above.

If the Rain Sensor detects rain and there is a window open, then for the buzzer version, the buzzer will buzz for 3sec. For the Voice Prompt version, the prompt .mp3 will be played and restarted after a delay if it is still raining and a window is still open.

Code Description

The RS_ESP32_Monitor.ino sketch contains a web server to display the status web page, above, as telnet client to connect to the Rain Sensor, an Http client to connect to the Window Open Monitor and buzzer and voice prompt handling,

The voice prompt handling is simple. While the Dfrobot Voice Prompt provides an extensive range of commands that can be sent via the TX/RX pins, in this project there is only one mp3 file which has already had it volume adjusted to the desired level. So all the sketch needs to do is pulse the P1 pin to GND to “play the next track” and then start a timer to inhibit retrigging the P1 pin until the track has finished. Since there is only one file, it is always the “next track” to be played.

The Http client, that connects to the Window Open Monitor, runs as a separate task. Each 3secs it request http://10.1.1.202/status to get the current window states as a text stream. Each line is then passed to processWindowOpenLine() to process and store the latest state in the listOfWindows. Access to the linked list listOfWindows is guarded by a recursive mutex. The main loop() and the web server both access the listOfWindows.

The telnet client opens a connection to the Rain Sensor. The Rain Sensor sends its current state and other data, as described above, once a second. handleRainDetectorClient() is called each loop() to handle the connection and to receive and process the Rain Sensor data. If the Monitor cannot connect to the Rain Sensor after 10 retries, the monitor restarts. Each 5secs, the telnet client send a CR LF to the Rain Sensor to indicate the Monitor is still active. The Rain Sensor will close the connection on its end after 10 secs if nothing received.

The web server provides the web page that show the Open/Closed state of each window and the Rain/Dry state as well as the up time for this monitor. The web page is built in a SafeString, cSF(msg,1024); , that has a capacity of 1024. If the page exceeds that size it will be truncated. You can check on that by uncommenting

#define DEBUG

near the top of RS_ESP32_Monitor.ino. That will print a SafeString error message if msg is too small to hold the entire web page. In that case increase the size of the msg until the errors dissappear.

>>> WebServer handleRoot
Error: msg.concat() needs capacity of 826(i.e. char[827]) for the first 28 chars of the input.
Input arg was '<font size="+2" color="red">'

The Rain Alert Monitor automatically reboots every 24hrs to clean up the ESP32 memory. Originally a String msg; was used to build the web page in, but using a String caused the web server locked up in less then 24hrs, when updating every 5sec. Changing to a SafeString fixed that problem.

Adding a Your Own Voice Prompt

Before wiring Dfrobot's Voice Prompt Module into the board, you need to load it with the prompt you want played. An example prompt is 001.mp3 which has an alarm and a repeated message to “Close the Window”.

To make your own, choose an alarm tone from one of the many freely available on the internet. Search for “free alarm tones”. Avoid those with low frequency components as the Voice Prompt Module does not render low frequencies.

Load the alarm into Audacity and then export it as a MONO file. Reload it and cut it to the desired length and save it again.

To add your voice message, start your mobile's camera in movie mode and say your message. Export the movie to your computer (Share via Email) and load it into the free ShortCut video editor and save the audio (search “how to extract audio with shortcut”) There are other ways of exporting the audio, but this was the method used for this project.

Load the audio msg into Audacity and cut and paste it to the end of the alarm and join the two clips. Export the audio and load it into the Voice Prompt Module,, via the USB cable, naming the file 001.mp3. Touch P1 to GND to play the file. Use Amplify in Audacity to adjust the volume of the track to the sound level you want. If the audio is distorted, reduce the amplitude in Audacity by setting a -ve db amplification and retest.

Conclusion

This Audio Rain Sensor uses stereo MEMS microphones and a novel Fourier Transforms to detect individual rain drops. The Rain Sensor's state is made available via a telnet server which the Rain Alarm Monitor connects to and combines with the data from the BLE Window Open detectors' BLE to Web Server bridge, to raise and alarm if it starts to rain and a window has been left open.