As i understand, interrupts good enough for battery powered sensors.
And I guess, it is no possible or no needed to use interrupts at software debouncing with millis. Turned out like this:
//
// Use this sensor to measure volume and flow of your house watermeter.
// You need to set the correct pulsefactor of your meter (pulses per m3).
// The sensor starts by fetching current volume reading from gateway (VAR 1).
// Reports both volume and flow back to gateway.
//
#include <Relay.h>
#include <SPI.h>
#include <EEPROM.h>
#include <RF24.h>
#include <Sensor.h>
#include <DHT.h>
#define CHILD_ID_HUM 0
#define CHILD_ID_TEMP 1
unsigned long HUM_TEMP_SEND_FREQUENCY = 60; // Minimum time between send (in seconds). We don't want to spam the gateway.
#define HUMIDITY_SENSOR_DIGITAL_PIN 4
#define HOT_WATER_SENSOR_DIGITAL_PIN 5
#define COLD_WATER_SENSOR_DIGITAL_PIN 3
#define PULSE_FACTOR 1000 // Nummber of blinks per m3 of your meter (One rotation/liter)
#define CHILD_ID_HOT_WATER 5
#define CHILD_ID_COLD_WATER 4 // Id of the sensor child
unsigned long SEND_FREQUENCY = 20; // Minimum time between send (in seconds). We don't want to spam the gateway.
Sensor gw;
DHT dht;
float lastTemp;
float lastHum;
boolean metric = true;
double ppl = ((double)PULSE_FACTOR)/1000; // Pulses per liter
volatile unsigned long pulseCountHot = 0;
volatile unsigned long pulseCountCold = 0;
volatile unsigned long lastBlinkHot = 0;
volatile unsigned long lastBlinkCold = 0;
volatile double flowHot = 0;
volatile double flowCold = 0;
unsigned long oldPulseCountHot = 0;
unsigned long oldPulseCountCold = 0;
unsigned long newBlinkHot = 0;
unsigned long newBlinkCold = 0;
double oldflowHot = 0;
double oldflowCold = 0;
double volumeHot;
double volumeCold;
double oldvolumeHot;
double oldvolumeCold;
unsigned long lastSendHot;
unsigned long lastSendCold;
unsigned long lastSendHumTemp;
unsigned long lastPulseHot;
unsigned long lastPulseCold;
unsigned long currentTimeHot;
unsigned long currentTimeCold;
unsigned long currentHumTemp;
int lastSensorStateHot = 1; // the previous reading from the input pin
int sensorStateHot; // the current reading from the input pin
long lastDebounceTimeHot = 0; // the last time the output pin was toggled
long debounceDelayHot = 50; // the debounce time; increase if the output flickers
int lastSensorStateCold = 1; // the previous reading from the input pin
int sensorStateCold; // the current reading from the input pin
long lastDebounceTimeCold = 0; // the last time the output pin was toggled
long debounceDelayCold = 50; // the debounce time; increase if the output flickers
void setup() {
gw.begin();
dht.setup(HUMIDITY_SENSOR_DIGITAL_PIN);
// Send the sketch version information to the gateway and Controller
gw.sendSketchInfo("Water Meter", "1.0");
// Register this device as Waterflow sensor
gw.sendSensorPresentation(CHILD_ID_COLD_WATER, S_WATER);
gw.sendSensorPresentation(CHILD_ID_HOT_WATER, S_WATER);
gw.sendSensorPresentation(CHILD_ID_HUM, S_HUM);
gw.sendSensorPresentation(CHILD_ID_TEMP, S_TEMP);
// Fetch last known pulse count value from gw
pulseCountCold = oldPulseCountCold = atol(gw.getStatus(CHILD_ID_COLD_WATER, V_VAR1));
pulseCountHot = oldPulseCountHot = atol(gw.getStatus(CHILD_ID_HOT_WATER, V_VAR1));
Serial.print("Last pulse count from gw: Cold ");
Serial.print(pulseCountCold);
Serial.print(" Hot ");
Serial.println(pulseCountHot);
lastSendCold = millis();
lastSendHot = millis();
pinMode(COLD_WATER_SENSOR_DIGITAL_PIN, INPUT);
pinMode(HOT_WATER_SENSOR_DIGITAL_PIN, INPUT);
}
void loop() {
int readingCold = digitalRead(COLD_WATER_SENSOR_DIGITAL_PIN);
// If the switch changed, due to noise or pressing:
if (readingCold != lastSensorStateCold) {
// reset the debouncing timer
lastDebounceTimeCold = millis();
}
if ((millis() - lastDebounceTimeCold) > debounceDelayCold) {
// whatever the reading is at, it's been there for longer
// than the debounce delay, so take it as the actual current state:
// if the button state has changed:
if (readingCold != sensorStateCold) {
sensorStateCold = readingCold;
// only toggle the LED if the new button state is HIGH
if (sensorStateCold == 0) {
pulseCountCold++;
unsigned long newBlinkCold = micros();
unsigned long intervalCold = newBlinkCold-lastBlinkCold;
lastPulseCold = millis();
flowCold = (60000000.0 /intervalCold) / ppl;
lastBlinkCold = newBlinkCold;
Serial.print("flowCold");
Serial.println(flowCold);
}
}
}
int readingHot = digitalRead(HOT_WATER_SENSOR_DIGITAL_PIN);
// If the switch changed, due to noise or pressing:
if (readingHot != lastSensorStateHot) {
// reset the debouncing timer
lastDebounceTimeHot = millis();
}
if ((millis() - lastDebounceTimeHot) > debounceDelayHot) {
// whatever the reading is at, it's been there for longer
// than the debounce delay, so take it as the actual current state:
// if the button state has changed:
if (readingHot != sensorStateHot) {
sensorStateHot = readingHot;
// only toggle the LED if the new button state is HIGH
if (sensorStateHot == 0) {
pulseCountHot++;
unsigned long newBlinkHot = micros();
unsigned long intervalHot = newBlinkHot-lastBlinkHot;
lastPulseHot = millis();
flowHot = (60000000.0 /intervalHot) / ppl;
lastBlinkHot = newBlinkHot;
Serial.print("flowHot");
Serial.println(flowHot);
}
}
}
currentTimeCold = millis();
currentTimeHot = millis();
// No Pulse count in 2min reset flow
if(currentTimeCold - lastPulseCold > 120000){
flowCold = 0;
if (flowCold != oldflowCold) {
gw.sendVariable(CHILD_ID_COLD_WATER, V_FLOW, flowCold, 2); // Send flow value to gw
oldflowCold = flowCold;
Serial.println("flowCold Reset");
}
}
// No Pulse count in 2min reset flow
if(currentTimeHot - lastPulseHot > 120000){
flowHot = 0;
if (flowHot != oldflowHot) {
gw.sendVariable(CHILD_ID_HOT_WATER, V_FLOW, flowHot, 2); // Send flow value to gw
oldflowHot = flowHot;
Serial.println("flowHot Reset");
}
}
// Only send values at a maximum frequency
if ((currentTimeCold - lastSendCold > 1000*SEND_FREQUENCY) || (currentTimeHot - lastSendHot > 1000*SEND_FREQUENCY)){
// Pulse count has changed
if (pulseCountCold != oldPulseCountCold) {
gw.sendVariable(CHILD_ID_COLD_WATER, V_VAR1, pulseCountCold); // Send volumevalue to gw VAR1
double volumeCold = ((double)pulseCountCold/((double)PULSE_FACTOR));
oldPulseCountCold = pulseCountCold;
Serial.print("PulseCold count:");
Serial.println(pulseCountCold);
if (volumeCold != oldvolumeCold) {
gw.sendVariable(CHILD_ID_COLD_WATER, V_VOLUME, volumeCold, 3); // Send volume value to gw
Serial.print("m3Cold:");
Serial.println(volumeCold, 3);
oldvolumeCold = volumeCold;
}
if (flowCold != oldflowCold) {
gw.sendVariable(CHILD_ID_COLD_WATER, V_FLOW, flowCold, 2); // Send flow value to gw
Serial.print("l/min Cold:");
Serial.println(flowCold);
oldflowCold = flowCold;
}
lastSendCold = currentTimeCold;
}
// Pulse count has changed
if (pulseCountHot != oldPulseCountHot) {
gw.sendVariable(CHILD_ID_HOT_WATER, V_VAR1, pulseCountHot); // Send volumevalue to gw VAR1
double volumeHot = ((double)pulseCountHot/((double)PULSE_FACTOR));
oldPulseCountHot = pulseCountHot;
Serial.print("PulseHot count:");
Serial.println(pulseCountHot);
if (volumeHot != oldvolumeHot) {
gw.sendVariable(CHILD_ID_HOT_WATER, V_VOLUME, volumeHot, 3); // Send volume value to gw
Serial.print("m3Hot:");
Serial.println(volumeHot, 3);
oldvolumeHot = volumeHot;
}
if (flowHot != oldflowHot) {
gw.sendVariable(CHILD_ID_HOT_WATER, V_FLOW, flowHot, 2); // Send flow value to gw
Serial.print("l/min Hot:");
Serial.println(flowHot);
oldflowHot = flowHot;
}
lastSendHot = currentTimeHot;
}
}
lastSensorStateCold = readingCold;
lastSensorStateHot = readingHot;
currentHumTemp = millis();
if (currentHumTemp - lastSendHumTemp> 1000*HUM_TEMP_SEND_FREQUENCY) {
delay(dht.getMinimumSamplingPeriod());
float temperature = dht.getTemperature();
if (isnan(temperature)) {
Serial.println("Failed reading temperature from DHT");
} else if (temperature != lastTemp) {
lastTemp = temperature;
if (!metric) {
temperature = dht.toFahrenheit(temperature);
}
gw.sendVariable(CHILD_ID_TEMP, V_TEMP, temperature, 1);
Serial.print("T: ");
Serial.println(temperature);
}
float humidity = dht.getHumidity();
if (isnan(humidity)) {
Serial.println("Failed reading humidity from DHT");
} else if (humidity != lastHum) {
lastHum = humidity;
gw.sendVariable(CHILD_ID_HUM, V_HUM, humidity, 1);
Serial.print("H: ");
Serial.println(humidity);
}
lastSendHumTemp = currentHumTemp;
}
}
Sketch consists two water meter sensors for Cold, Hot water and DHT for humidity and temp.
Looks like, working fine for 24 hours for me.