Hi guys.
I have a sketch for a battery powered node that sleeps a certain amount of time, let's say 2 minutes. unsigned long SLEEP_TIME = 120000; // Wait time between reads (in milliseconds) When it wakes up, it will check a few sensors and report new values (if any) to the gateway. So far so good.
However (there's always a but, isn't there?), the 2 minute sleep is allowed to be interrupted by the change of a pin. That pin is connected to a rain meter. Measuring the rain must be done instantly.
Every time that the loop() function runs, other sensors are checked.
That's OK if it rains normally but sometimes it rains like h*ll. I'm concerned that the rain meter will be tripped so frequently that there is no time to check other sensors and report them to the gateway.
I'm useless when it comes to explain things. But I'd like the rain sensor to report whenever the rain sensor is tripped. I would like the other sensors to report at the 2 minutes interval regardless of the rain sensor. As it is now, every time the rain sensor interrupts the sleep, all sensors gets checked. I would like it to report the rain and go back to sleep the REMAINING SLEEP TIME. I understand if my explanation is beyond what ca be understood (it's worse than Kurt Olsson) so I add the source below:
/**
* WeatherStation
*
* DESCRIPTION
* Arduino BH1750FVI Light sensor
* communicate using I2C Protocol
* this library enable 2 slave device addresses
* Main address 0x23
* secondary address 0x5C
* connect the sensor as follows :
*
* VCC >>> 5V
* Gnd >>> Gnd
* ADDR >>> NC or GND
* SCL >>> A5
* SDA >>> A4
* http://www.mysensors.org/build/light
https://forum.mysensors.org/topic/9359/soft-wdt-reset-on-esp8266-rfm69-gateway-after-find-parent/20
Connecting the BME280 Sensor:
Sensor -> Board
-----------------------------
Vin (Voltage In) -> 3.3V
Gnd (Ground) -> Gnd
SDA (Serial Data) -> A4
SCK (Serial Clock) -> A5
For temperature measurements we've selected the standard Dallas DS18B20.
*/
#define MY_NODE_ID 15
#define SKETCH_NAME "Weather Station"
#define SKETCH_VERSION "1.1"
#define DWELL_TIME 200 // this allows for radio to come back to power after a transmission, ideally 0
// Enable debug Serial.prints to serial monitor
//#define MY_DEBUG
#if defined MY_DEBUG
#define Sprintln(a) (Serial.println(a))
#define Sprint(a) (Serial.print(a))
#else
#define Sprintln(a)
#define Sprint(a)
#endif
// Enable and select radio type attached
#define MY_RADIO_NRF24
//#define MY_RADIO_RFM69
#include <SPI.h> // A communication backbone, the Serial Peripheral Interface.
#include <MySensors.h> // The MySensors library.
#include <Wire.h> // Enables the Wire communication protocol.
#include <DallasTemperature.h>
#include <OneWire.h>
#include <BH1750.h>
//#include <BME280I2C.h> // From Library Manager
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#undef BME280_ADDRESS // Undef BME280_ADDRESS from the BME280 library to easily override I2C address
#define BME280_ADDRESS (0x76) // Low = 0x76 , High = 0x77 (default on adafruit and sparkfun BME280 modules, default for library)
uint8_t tipSensorPin = 3; // Pin the tipping bucket is connected to. Must be interrupt capable pin
#define CHILD_ID_LIGHT 0
#define CHILD_ID_TEMP_1 1
#define CHILD_ID_TEMP_2 2 // Dallas DS18B20
#define CHILD_ID_HUM 3
#define CHILD_ID_BARO 4
#define CHILD_ID_RAIN 5
unsigned long SLEEP_TIME = 120000; // Wait time between reads (in milliseconds)
#define FORCE_TRANSMIT_CYCLE 30
uint8_t cycleCountLux = 0;
uint8_t cycleCountPressure = 0;
uint8_t cycleCountTemp2 = 0;
uint8_t cycleCountHum = 0;
int8_t interruptedBy = -1;
Adafruit_BME280 bme; // I2C
BH1750 lightSensor;
#define ONE_WIRE_BUS 5 // Digital pin where dallas sensor is connected
OneWire oneWire(ONE_WIRE_BUS); // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
DallasTemperature DS18B20sensor(&oneWire); // Pass the oneWire reference to Dallas Temperature.
uint16_t lastLux;
float lastPressure;
//float lastTemp1; // Temp from the BME280 Temp Hum Bar Sensor
float lastTemp2; // Dallas DS18B20. Temp
float lastHum;
float tempThreshold = 0.2; // How big a temperature difference has to minimally be before an update is sent. Makes the sensor less precise, but also less jittery, and can save battery.
uint8_t humThreshold = 1; // How big a humidity difference has to minimally be before an update is sent. Makes the sensor less precise, but also less jittery, and can save battery.
uint8_t presThreshold = 1;
uint8_t luxThreshold = 1;
MyMessage msgLight(CHILD_ID_LIGHT, V_LEVEL);
MyMessage msgTemp1(CHILD_ID_TEMP_1, V_TEMP);
MyMessage msgTemp2(CHILD_ID_TEMP_2, V_TEMP);
MyMessage msgHum(CHILD_ID_HUM, V_HUM);
MyMessage msgPressure(CHILD_ID_BARO, V_PRESSURE);
MyMessage msgRain(CHILD_ID_RAIN, V_TRIPPED);
void setup()
{
Wire.begin(); // Wire.begin(sda, scl) // starts the wire communication protocol, used to chat with the BME280 sensor.
Sprint(SKETCH_NAME);
Sprint(F(" version "));
Sprint(SKETCH_VERSION);
Sprint(F(" (using MY_NODE_ID: "));
Sprint(MY_NODE_ID);
Sprintln(F(") says hello!"));
delay(500);// just in case
Sprintln(F("Running bme.begin()"));
if (!bme.begin())
{
Serial.println("BME init failed!");
}
else Sprintln("BME init success!");
Sprintln(F("Running lightSensor.begin()"));
lightSensor.begin();
Sprintln(F("Running DS18B20sensor.begin()"));
DS18B20sensor.begin(); // Startup up the OneWire library used for Dallas DS18B20 Temp
DS18B20sensor.setWaitForConversion(false); // requestTemperatures() will not block current thread
pinMode(tipSensorPin, INPUT); // sets the rain sensor digital pin as input
}
void presentation() {
// Send the sketch version information to the gateway and Controller
sendSketchInfo(SKETCH_NAME, SKETCH_VERSION);
wait(DWELL_TIME);
// Register all sensors to gateway (they will be created as child devices)
present(CHILD_ID_LIGHT, S_LIGHT_LEVEL);
wait(DWELL_TIME);
//present(CHILD_ID_TEMP_1, S_TEMP); // Temp sensor on the BME280 multi sensor
//wait(DWELL_TIME);
present(CHILD_ID_TEMP_2, S_TEMP); // Dallas DS18B20. Temp
wait(DWELL_TIME);
present(CHILD_ID_HUM, S_HUM);
wait(DWELL_TIME);
present(CHILD_ID_BARO, S_BARO);
wait(DWELL_TIME);
present(CHILD_ID_RAIN, S_MOTION);
wait(DWELL_TIME);
}
void loop()
{
bool rainBucketTripped = (interruptedBy == digitalPinToInterrupt(tipSensorPin));
wait(500); // Give radio some time to warm up
cycleCountLux++;
cycleCountPressure++;
cycleCountTemp2++;
cycleCountHum++;
if (rainBucketTripped) {
Sprintln("Tipping bucket rain sensor was tripped");
send(msgRain.set(1)); // Send tripped value to gw
wait(DWELL_TIME);
}
// Fetch temperature from Dallas DS18B20 Temp sensor
DS18B20sensor.requestTemperatures();
// query conversion time and sleep until conversion completed
int16_t conversionTime = DS18B20sensor.millisToWaitForConversion(DS18B20sensor.getResolution());
// sleep() call can be replaced by wait() call if node need to process incoming messages (or if node is repeater)
sleep(conversionTime);
// Fetch and round temperature to one decimal
float temp2 = static_cast<float>(static_cast<int>((getControllerConfig().isMetric?DS18B20sensor.getTempCByIndex(0):DS18B20sensor.getTempFByIndex(0)) * 10.)) / 10.;
if (isnan(temp2)) {
Sprintln("Failed reading temp2");
} else if (((abs(temp2 - lastTemp2) >= tempThreshold) or (cycleCountTemp2 >= FORCE_TRANSMIT_CYCLE)) && temp2 != -127.00 && temp2 != 85.00) {
// Only send temp2 if it changed since the last measurement
lastTemp2 = temp2;
cycleCountTemp2 = 0;
Sprint("Temperature: ");
Sprint(temp2);
Sprintln("°C");
send(msgTemp2.set(temp2 ,1));
wait(DWELL_TIME);
}
uint16_t lux = lightSensor.readLightLevel();// Get Lux value
if (isnan(lux)) {
Sprintln("Failed reading lux");
} else if ((abs(lux - lastLux) >= luxThreshold) or (cycleCountLux >= FORCE_TRANSMIT_CYCLE)){
// Only send Lux if it changed since the last measurement
lastLux = lux;
cycleCountLux = 0;
Sprint("Light: ");
Sprint(lux);
Sprintln(" Lux");
send(msgLight.set(lux));
wait(DWELL_TIME);
}
double pres, hum;
pres=bme.readPressure()/100.0;
hum=bme.readHumidity();
if (isnan(hum)) {
Sprintln("Failed reading humidity");
} else {
hum = round(hum);
if ((abs(hum - lastHum) >= humThreshold) or (cycleCountHum >= FORCE_TRANSMIT_CYCLE)){
// Only send humidity if it changed since the last measurement
lastHum = hum;
cycleCountHum = 0;
Sprint("Humidity: ");
Sprint(hum);
Sprintln("% RH");
send(msgHum.set(hum, 0));
wait(DWELL_TIME);
}
}
if (isnan(pres)) {
Sprintln("Failed reading pressure");
} else {
pres = round(pres);
if ((abs(pres - lastPressure) >= presThreshold) or (cycleCountPressure >= FORCE_TRANSMIT_CYCLE)) {
// Only send pressure if it changed since the last measurement
lastPressure = pres;
cycleCountPressure = 0;
Sprint("Pressure: ");
Sprint(pres);
Sprintln(" hPa");
send(msgPressure.set(pres, 0));
wait(DWELL_TIME);
}
}
// Sleep until interrupt comes in on rain tip bucket sensor. Send update every SLEEP_TIME.
Sprintln(F("Waiting ")); Sprint(SLEEP_TIME /1000); Sprintln(F(" seconds before next reading."));
interruptedBy = sleep(digitalPinToInterrupt(tipSensorPin), CHANGE, SLEEP_TIME);
}
Another try to explain: When it rains heavily, I don't want to check and report humidity and temp. Humidity and temp should be reported in the interval that I've set in SLEEP_TIME.

Can it be done?