Skip to content

Commit

Permalink
[HM-RD] Added leak/water detection sensor with ESP32 deep sleep / sen…
Browse files Browse the repository at this point in the history
…sor wake (#1615)

Added leak/water detection sensor with ESP32 deep sleep / sensor wake
  • Loading branch information
diepeterpan committed Apr 25, 2023
1 parent e3e7004 commit abeef87
Show file tree
Hide file tree
Showing 9 changed files with 252 additions and 21 deletions.
2 changes: 2 additions & 0 deletions docs/setitup/sensors.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
|BH1750|Digital light|[parts list](https://compatible.openmqttgateway.com/index.php/parts)|
|BME280|Temperature, Humidity, Pressure|[parts list](https://compatible.openmqttgateway.com/index.php/parts)|
|BMP280|Temperature, Pressure|[parts list](https://compatible.openmqttgateway.com/index.php/parts)|
|C-37, YL-83, HM-RD|Leak, Water|[parts list](https://compatible.openmqttgateway.com/index.php/parts)|
|HTU21|Temperature, Humidity|[parts list](https://compatible.openmqttgateway.com/index.php/parts)|
|GPIO Input|Inputs|-|
|GPIO KeyCode|Keycode|[parts list](https://compatible.openmqttgateway.com/index.php/parts)|
Expand All @@ -24,6 +25,7 @@
|BH1750 SCL|A5|D1|22|
|BME280/BMP280 SDA|A4|D2|21|
|BME280/BMP280 SCL|A5|D1|22|
|C-37, YL-83, HM-RD|A0 + D14|A0 + D14|A7 + D14|
|DHT11/22|<a href="img/OpenMQTTgateway_Arduino_Addon_DHT.png" target="_blank">D8</a>|<a href="img/OpenMQTTgateway_ESP8266_Addon_DHT.png" target="_blank">D1</a>|16|
|HC-SR501/HC-SR505|7|D5|5|
|HTU21 SDA|A4|D2|21|
Expand Down
15 changes: 9 additions & 6 deletions docs/use/boards.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,19 +92,22 @@ OpenMQTTGateway support a low power mode for ESP32, this mode can be set by MQTT
The low power mode can be changed also with a push to button B when the board is processing (top button on M5stickC, M5stickC Plus and middle button of M5stack).
If you are already in low power mode 1 or 2 with M5Stack you can wake up the board by pressing the red button.

### Low power mode (deepSleep) for ESP8266 boards
In certain use cases where power is severly limited you can use the ESP8266 deep sleep capability.
### Low power mode (deepSleep) for ESP8266 & ESP32 boards
In certain use cases where power is severly limited you can use the ESP8266 or ESP32 deep sleep capability.

* e.g. measuring a pool temperature every 5 minutes using an ESP8266 and DS18B20 probe where the ESP8266 is powered by very limited battery backed solar power.
* e.g. as a water/leak detector which wake-up based on sensor state an ESP32 and C-37 YL-83 HM-RD sensor where the ESP32 is powered by very limited battery power.

During deep sleep everything is off and (almost) all execution state is lost.

Consumption is about 20 µA.
Consumption is about 20 µA on an ESP8266.

Use this when you want the device to sleep for minutes or hours.
Use this when you want the device to sleep for minutes, hours woken by external sensor state.

You only have to define the macro `ESP8266_DEEP_SLEEP_IN_US` with the number of microseconds.
You only have to define the macro `DEEP_SLEEP_IN_US` with the number of microseconds, this works for both ESP8266 and ESP32.

A hardware jumper is required connecting RST to a GPIO (not to CH_PD) defined by the macro `ESP8266_DEEP_SLEEP_WAKE_PIN` and defaulted to D0.
For an ESP8266 a hardware jumper is required connecting RST to a GPIO (not to CH_PD) defined by the macro `ESP8266_DEEP_SLEEP_WAKE_PIN` and defaulted to D0.

On an ESP32 we can also use an external sensor state to wake-up the ESP and this is defined by macro `ESP32_EXT0_WAKE_PIN` and which state it must toggle to by macro `ESP32_EXT0_WAKE_PIN_STATE` defaulted to 1 (high).

And the sensor code must set variable `ready_to_sleep` to true after publishing the measurement to MQTT and the main loop will then enter deep sleep.
7 changes: 5 additions & 2 deletions environments.ini
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,10 @@ build_flags =
'-DsimplePublishing=true'
'-DWM_PWD_FROM_MAC=true'
'-DUSE_MAC_AS_GATEWAY_NAME=true'

'-DZsensorC37_YL83_HMRD="HMRD"'
'-DDEEP_SLEEP_IN_US=120000000' ; Deep sleep for a period of time to conserve battery
'-DESP32_EXT0_WAKE_PIN=GPIO_NUM_14' ;Should a water leak be detected immediatly wake the ESP32 and report the problem
'-DESP32_EXT0_WAKE_PIN_STATE=0' ;Should a water leak be detected immediatly wake the ESP32 and report the problem, sensor state to look for wakeup
[env:esp32dev-rf]
platform = ${com.esp32_platform}
board = esp32dev
Expand Down Expand Up @@ -1070,7 +1073,7 @@ build_flags =
;'-DZgatewayWeatherStation="WeatherStation"'
'-DsimplePublishing=true'
'-DGateway_Name="OMG_ESP8266_ALL"'
'-DESP8266_DEEP_SLEEP_IN_US=120000000'
'-DDEEP_SLEEP_IN_US=120000000'
board_build.flash_mode = dout

[env:nodemcuv2-fastled-test]
Expand Down
12 changes: 11 additions & 1 deletion main/User_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -298,12 +298,22 @@ static_assert(MQTT_SECURE_SELF_SIGNED_INDEX_DEFAULT < (sizeof(certs_array) / siz
* Deep-sleep for the ESP8266.
* Set the wake pin.
*/
#ifdef ESP8266_DEEP_SLEEP_IN_US
#if defined(DEEP_SLEEP_IN_US) && defined(ESP8266)
# ifndef ESP8266_DEEP_SLEEP_WAKE_PIN
# define ESP8266_DEEP_SLEEP_WAKE_PIN D0
# endif
#endif

/**
* Ext wake for Deep-sleep for the ESP32.
* Set the wake pin state.
*/
#ifdef ESP32_EXT0_WAKE_PIN
# ifndef ESP32_EXT0_WAKE_PIN_STATE
# define ESP32_EXT0_WAKE_PIN_STATE 1
# endif
#endif

/*------------------DEEP SLEEP parameters ------------------*/
//DEFAULT_LOW_POWER_MODE -1 to normal mode, low power mode can't be used on this build
//DEFAULT_LOW_POWER_MODE 0 to normal mode (no power consumption optimisations)
Expand Down
80 changes: 80 additions & 0 deletions main/ZsensorC37_YL83_HMRD.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
OpenMQTTGateway Addon - ESP8266 or Arduino program for home automation
Act as a wifi or ethernet gateway between your 433mhz/infrared IR/BLE signal and a MQTT broker
Send and receiving command by MQTT
This file sets parameters for the integration of C-37 YL-83 HM-RD water detection sensors
This file is part of OpenMQTTGateway.
OpenMQTTGateway is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenMQTTGateway is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "User_config.h"

#ifdef ZsensorC37_YL83_HMRD

//Time used to wait for an interval before resending temp and hum
unsigned long timeC37YL83HMRD = 0;
unsigned int persistedanalog = 0;
unsigned int persisteddigital = 0;

void setupZsensorC37_YL83_HMRD() {
pinMode(C37_YL83_HMRD_Digital_GPIO, INPUT);
Log.trace(F("C37_YL83_HMRD: digital configured pin: %d" CR), C37_YL83_HMRD_Digital_GPIO);

pinMode(C37_YL83_HMRD_Analog_GPIO, INPUT);
Log.trace(F("C37_YL83_HMRD: Analog configured pin: %d" CR), C37_YL83_HMRD_Analog_GPIO);

# ifdef C37_YL83_HMRD_Analog_RESOLUTION
analogReadResolution(C37_YL83_HMRD_Analog_RESOLUTION);
Log.trace(F("C37_YL83_HMRD: resolution: %d" CR), C37_YL83_HMRD_Analog_RESOLUTION);
# endif
}

void MeasureC37_YL83_HMRDWater() {
if (millis() > (timeC37YL83HMRD + C37_YL83_HMRD_INTERVAL_SEC)) { //retrieving value of water sensor every xUL
timeC37YL83HMRD = millis();
static int persistedanalog;
static int persisteddigital;

int sensorDigitalValue = digitalRead(C37_YL83_HMRD_Digital_GPIO); // Read the analog value from sensor
int sensorAnalogValue = analogRead(C37_YL83_HMRD_Analog_GPIO);

Log.trace(F("Creating C37_YL83_HMRD buffer" CR));
StaticJsonDocument<JSON_MSG_BUFFER> jsonBuffer;
JsonObject C37_YL83_HMRDdata = jsonBuffer.to<JsonObject>();
if (sensorDigitalValue != persisteddigital || C37_YL83_HMRD_ALWAYS) {
C37_YL83_HMRDdata["detected"] = (sensorDigitalValue == 1 ? "false" : "true");
} else {
Log.trace(F("Same digital don't send it" CR));
}
if (sensorAnalogValue != persistedanalog || C37_YL83_HMRD_ALWAYS) {
C37_YL83_HMRDdata["reading"] = sensorAnalogValue;
} else {
Log.trace(F("Same analog don't send it" CR));
}
if (C37_YL83_HMRDdata.size() > 0) {
pub(C37_YL83_HMRD_TOPIC, C37_YL83_HMRDdata);
delay(10);
# if defined(DEEP_SLEEP_IN_US) || defined(ESP32_EXT0_WAKE_PIN)
if (sensorDigitalValue == 1) //No water detected, all good we can sleep
ready_to_sleep = true;
# endif
}
persistedanalog = sensorAnalogValue;
persisteddigital = sensorDigitalValue;
}
}
#endif
6 changes: 3 additions & 3 deletions main/ZsensorDS1820.ino
Original file line number Diff line number Diff line change
Expand Up @@ -158,13 +158,13 @@ void MeasureDS1820Temp() {
}
pub((char*)(String(OW_TOPIC) + "/" + ds1820_addr[i]).c_str(), DS1820data);
delay(10);
# if defined(DEEP_SLEEP_IN_US) || defined(ESP32_EXT0_WAKE_PIN)
ready_to_sleep = true;
# endif
} else {
Log.trace(F("DS1820: Temperature for device %s didn't change, don't publish it." CR), (char*)ds1820_addr[i].c_str());
}
persisted_temp[i] = current_temp[i];
# ifdef ESP8266_DEEP_SLEEP_IN_US
ready_to_sleep = true;
# endif
}
}
}
Expand Down
63 changes: 63 additions & 0 deletions main/config_C37_YL83_HMRD.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
OpenMQTTGateway - ESP8266 or Arduino program for home automation
Act as a wifi or ethernet gateway between your RF/infrared IR signal and a MQTT broker
Send and receiving command by MQTT
This file sets parameters for the integration of C-37 YL-83 HM-RD water detection sensors
This file is part of OpenMQTTGateway.
OpenMQTTGateway is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenMQTTGateway is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef config_C37_YL83_HMRD_h
#define config_C37_YL83_HMRD_h

extern void setupZsensorC37_YL83_HMRD();
extern void C37_YL83_HMRDtoMQTT();
extern void MeasureC37_YL83_HMRDWater();

/*----------------------------USER PARAMETERS-----------------------------*/
/*-------------DEFINE YOUR MQTT PARAMETERS BELOW----------------*/
#define C37_YL83_HMRD_TOPIC "/WATERtoMQTT/c37_yk83_hmrd"
#define C37_YL83_HMRD_ALWAYS true // if false only published current water leak detection if has changed from previous reading
#ifndef C37_YL83_HMRD_INTERVAL_SEC
# define C37_YL83_HMRD_INTERVAL_SEC 10000 // time between C-37, YL-83, HM-RD readings (ms)
#endif
#ifndef C37_YL83_HMRD_RESOLUTION
# define C37_YL83_HMRD_RESOLUTION 10 // conversion times: 9 bit (93.75 ms), 10 bit (187.5 ms), 11 bit (375 ms), 12 bit (750 ms)
#endif
/*-------------------PIN DEFINITIONS----------------------*/

#ifndef C37_YL83_HMRD_Digital_GPIO
# if defined(ESP8266)
# define C37_YL83_HMRD_Digital_GPIO 14
# elif defined(ESP32)
# define C37_YL83_HMRD_Digital_GPIO GPIO_NUM_14
# else
# define C37_YL83_HMRD_Digital_GPIO 14
# endif
#endif

#ifndef C37_YL83_HMRD_Analog_GPIO
# if defined(ESP8266)
# define C37_YL83_HMRD_Analog_GPIO A0
# elif defined(ESP32)
# define C37_YL83_HMRD_Analog_GPIO GPIO_NUM_35
# else
# define C37_YL83_HMRD_Analog_GPIO A0
# endif
#endif

#endif
58 changes: 51 additions & 7 deletions main/main.ino
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,10 @@ unsigned long timer_sys_checks = 0;
#endif

/**
* Deep-sleep for the ESP8266 we need some form of indicator that we have posted the measurements and am ready to deep sleep.
* Deep-sleep for the ESP8266 & ESP32 we need some form of indicator that we have posted the measurements and am ready to deep sleep.
* Set this to true in the sensor code after publishing the measurement.
*/
#ifdef ESP8266_DEEP_SLEEP_IN_US
#if defined(DEEP_SLEEP_IN_US) || defined(ESP32_EXT0_WAKE_PIN)
bool ready_to_sleep = false;
#endif

Expand Down Expand Up @@ -147,6 +147,9 @@ struct GfSun2000Data {};
#ifdef ZsensorHCSR04
# include "config_HCSR04.h"
#endif
#ifdef ZsensorC37_YL83_HMRD
# include "config_C37_YL83_HMRD.h"
#endif
#ifdef ZsensorDHT
# include "config_DHT.h"
#endif
Expand Down Expand Up @@ -779,9 +782,32 @@ void setup() {
Log.notice(F("OpenMQTTGateway Version: " OMG_VERSION CR));
# endif

# ifdef ESP8266_DEEP_SLEEP_IN_US
/**
* Deep-sleep for the ESP8266 & ESP32 we need some form of indicator that we have posted the measurements and am ready to deep sleep.
* When woken set back to false.
*/
# if defined(DEEP_SLEEP_IN_US) || defined(ESP32_EXT0_WAKE_PIN)
ready_to_sleep = false;
# endif

# ifdef DEEP_SLEEP_IN_US
# ifdef ESP8266
Log.notice(F("Setting wake pin for deep sleep." CR));
pinMode(ESP8266_DEEP_SLEEP_WAKE_PIN, WAKEUP_PULLUP);
# endif
# ifdef ESP32
Log.notice(F("Setting duration for deep sleep." CR));
if (esp_sleep_enable_timer_wakeup(DEEP_SLEEP_IN_US) != ESP_OK) {
Log.error(F("Failed to set deep sleep duration." CR));
}
# endif
# endif

# ifdef ESP32_EXT0_WAKE_PIN
Log.notice(F("Setting EXT0 Wakeup for deep sleep." CR));
if (esp_sleep_enable_ext0_wakeup(ESP32_EXT0_WAKE_PIN, ESP32_EXT0_WAKE_PIN_STATE) != ESP_OK) {
Log.error(F("Failed to set deep sleep EXT0 Wakeup." CR));
}
# endif

/*
Expand Down Expand Up @@ -993,6 +1019,10 @@ void setup() {
setupADC();
modules.add(ZsensorADC);
#endif
#ifdef ZsensorC37_YL83_HMRD
setupZsensorC37_YL83_HMRD();
modules.add(ZsensorC37_YL83_HMRD);
#endif
#ifdef ZsensorDHT
setupDHT();
modules.add(ZsensorDHT);
Expand Down Expand Up @@ -1684,6 +1714,9 @@ void loop() {
#ifdef ZsensorTSL2561
MeasureLightIntensityTSL2561();
#endif
#ifdef ZsensorC37_YL83_HMRD
MeasureC37_YL83_HMRDWater(); //Addon for leak detection with a C-37 YL-83 H-MRD
#endif
#ifdef ZsensorDHT
MeasureTempAndHum(); //Addon to measure the temperature with a DHT
#endif
Expand Down Expand Up @@ -1794,13 +1827,24 @@ void loop() {
#endif

/**
* Deep-sleep for the ESP8266 - e.g. ESP8266_DEEP_SLEEP_IN_US 30000000 for 30 seconds.
* Deep-sleep for the ESP8266 & ESP32 - e.g. DEEP_SLEEP_IN_US 30000000 for 30 seconds / wake by ESP32_EXT0_WAKE_PIN.
* Everything is off and (almost) all execution state is lost.
*/
#ifdef ESP8266_DEEP_SLEEP_IN_US
#if defined(DEEP_SLEEP_IN_US) || defined(ESP32_EXT0_WAKE_PIN)
if (ready_to_sleep) {
Log.notice(F("Entering deep sleep for : %l us." CR), ESP8266_DEEP_SLEEP_IN_US);
ESP.deepSleep(ESP8266_DEEP_SLEEP_IN_US);
delay(250); //Give some time for last MQTT messages to be sent
# ifdef DEEP_SLEEP_IN_US
Log.notice(F("Entering deep sleep for %l us." CR), DEEP_SLEEP_IN_US);
# endif
# ifdef ESP32_EXT0_WAKE_PIN
Log.notice(F("Entering deep sleep, EXT0 Wakeup by pin : %l." CR), ESP32_EXT0_WAKE_PIN);
# endif
# ifdef ESP8266
ESP.deepSleep(DEEP_SLEEP_IN_US);
# endif
# ifdef ESP32
esp_deep_sleep_start();
# endif
}
#endif
}
Expand Down
30 changes: 28 additions & 2 deletions prod_env.ini.example
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,35 @@ build_flags =
'-DGateway_Name="OpenMQTTGatewayDS1820Pool"'
'-DZsensorDS1820="DS1820"'
'-DDS1820_OWBUS_GPIO=D2'
'-DESP8266_DEEP_SLEEP_IN_US=120000000'
'-DDEEP_SLEEP_IN_US=120000000'
'-DDS1820_RESOLUTION=12'
'-DDS1820_INTERVAL_SEC=15UL'
board_build.flash_mode = dout
custom_description = Pool temp sensor gateway
custom_hardware = Pool temp sensor first version
custom_hardware = Pool temp sensor first version

[env:wemos-d1-uno32-HM-RD-deepsleep-waterleak] ;C-37, YL-83, HM-RD leak detector powered by battery using ESP32 Deepsleep and EXT0 wake by sensor state
platform = ${com.esp32_platform}
board = wemos_d1_uno32
board_build.partitions = min_spiffs.csv
lib_deps =
${com-esp.lib_deps}
${libraries.wifimanager32}
build_flags =
${com-esp.build_flags}
'-UZmqttDiscovery' ; disables MQTT Discovery
; '-UZmqttDiscovery="HADiscovery"'
'-DvalueAsATopic=true' ; MQTT topic includes model and device
'-DGateway_Name="OpenMQTTGatewayMHRDWaterLeak"'
'-DZsensorC37_YL83_HMRD="HMRD"' ;Which type of sensor
'-DC37_YL83_HMRD_Digital_GPIO=GPIO_NUM_14'
'-DC37_YL83_HMRD_Analog_GPIO=GPIO_NUM_35'
'-DC37_YL83_HMRD_Analog_RESOLUTION=12'
'-DC37_YL83_HMRD_INTERVAL_SEC=3000'
'-DDEEP_SLEEP_IN_US=120000000' ; Deep sleep for a period of time to conserve battery
'-DESP32_EXT0_WAKE_PIN=C37_YL83_HMRD_Digital_GPIO' ;Should a leak be detected immediatly wake the ESP32 and report the problem
'-DESP32_EXT0_WAKE_PIN_STATE=0' ;Should water/leak be detected immediatly wake the ESP32 and report the problem, sensor state to look for wakeup
board_build.flash_mode = dout
custom_description = Water/Leak sensor gateway
custom_hardware = Water/Leak sensor first version
monitor_speed = 115200

0 comments on commit abeef87

Please sign in to comment.