commit 991836005e6e07389a0de51c2eba961861f181b5 Author: Frank Date: Thu Dec 30 13:22:20 2021 +0100 Create Meterkast.ino diff --git a/Meterkast.ino b/Meterkast.ino new file mode 100644 index 0000000..acead1c --- /dev/null +++ b/Meterkast.ino @@ -0,0 +1,319 @@ +// Use this sensor to measure KWH and Watt of your house meeter +// You need to set the correct pulsefactor of your meeter (blinks per KWH). +// The sensor starts by fetching current KWH value from gateway. +// Reports both KWH and Watt back to gateway. +// +// Unfortunately millis() won't increment when the Arduino is in +// sleepmode. So we cannot make this sensor sleep if we also want +// to calculate/report watt-number. + +// Enable debug prints to serial monitor +#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 + +//#include +#include +#include + +#define P_DIGITAL_INPUT_SENSOR 3 // The digital input you attached your light sensor. (Only 2 and 3 generates interrupt!) +#define P_INTERRUPT P_DIGITAL_INPUT_SENSOR-2 // Usually the interrupt = pin -2 (on uno/nano anyway) +#define W_DIGITAL_INPUT_SENSOR 4 // The digital input you attached your sensor. (Only 2 and 3 generates interrupt!) + +//#define P_PULSE_FACTOR 1000 // Nummber of blinks per KWH of your meeter +#define W_PULSE_FACTOR 2000 // Nummber of blinks per m3 of your meter (One rotation/liter) + +#define SLEEP_MODE false // Watt-value can only be reported when sleep mode is false. +//#define MAX_WATT 10000 // Max watt value to report. This filetrs outliers. +#define W_MAX_FLOW 40 // Max flow (l/min) value to report. This filters outliers. + +//#define P_CHILD_ID 1 // Id of the sensor child +#define W_CHILD_ID 2 // Id of the sensor child + +//unsigned long P_SEND_FREQUENCY = 20000; // Minimum time between send (in milliseconds). We don't wnat to spam the gateway. +unsigned long W_SEND_FREQUENCY = 60000; // Minimum time between send (in milliseconds). We don't wnat to spam the gateway. + +//Deurbel +unsigned long T_DEURBEL_ON = 700; +unsigned long t_deurbel; +boolean deurbel_on = false; +boolean Bel_Disabled = false; + +//MySensor gw; +boolean W_pcReceived = false; + +double W_ppl = ((double)W_PULSE_FACTOR)/1000; // Pulses per liter +volatile unsigned long W_pulseCount = 0; +volatile unsigned long W_lastBlink = 0; +volatile double W_flow = 0; +unsigned long W_oldPulseCount = 0; +unsigned long W_newBlink = 0; +double W_oldflow = 0; +double W_volume =0; +double W_oldvolume =0; +unsigned long W_lastPulse =0; + +boolean W_puls = false; +boolean W_prevpuls = false; + +unsigned long W_lastSend; + +MyMessage flowMsg(W_CHILD_ID,V_FLOW); +MyMessage volumeMsg(W_CHILD_ID,V_VOLUME); +MyMessage lastCounterMsg(W_CHILD_ID,V_VAR1); + +//Deur en deurbel +#define d1_BUTTON_PIN 5 // Arduino Digital I/O pin for button/reed switch voordeur +#define d2_BUTTON_PIN 6 // Arduino Digital I/O pin for button/reed switch deurbel drukker +#define d1_CHILD_ID 11 // Id voordeur contact +#define d2_CHILD_ID 12 // Id deurbel drukker + +#define O_DEURBEL_PIN 7 // Output relais deurbel +#define O_BUZZER_PIN 8 // Output buzzer +#define BEL_CHILD_ID 12 // ID deurbel relais +#define DIS_DEURBEL_CHILD_ID 13 // ID deurbel disable +#define BUZZER_CHILD_ID 99 // ID Buzzer + +//Declare deuren +Bounce d1_debouncer = Bounce(); +int d1_oldValue=-1; +Bounce d2_debouncer = Bounce(); +int d2_oldValue=-1; + + +MyMessage d1_msg(d1_CHILD_ID,V_TRIPPED); +MyMessage d2_msg(d2_CHILD_ID,V_LIGHT); +MyMessage BEL_msg(BEL_CHILD_ID, V_LIGHT); +MyMessage DIS_DEURBEL_msg(DIS_DEURBEL_CHILD_ID, V_LIGHT); +MyMessage BUZZER_msg(BUZZER_CHILD_ID, V_LIGHT); + +void setup() +{ + pinMode(W_DIGITAL_INPUT_SENSOR, INPUT); // set pin to input + digitalWrite(W_DIGITAL_INPUT_SENSOR, HIGH); // turn on pullup resistors + + // Setup the door switchs 1 + pinMode(d1_BUTTON_PIN,INPUT); + // Activate internal pull-up + digitalWrite(d1_BUTTON_PIN,HIGH); + // After setting up the button, setup debouncer + d1_debouncer.attach(d1_BUTTON_PIN); + d1_debouncer.interval(100); + + // Setup the door switch 2 + pinMode(d2_BUTTON_PIN,INPUT); + // Activate internal pull-up + digitalWrite(d2_BUTTON_PIN,HIGH); + // After setting up the button, setup debouncer + d2_debouncer.attach(d2_BUTTON_PIN); + d2_debouncer.interval(20); + + // Setup the deurbel relais + pinMode(O_DEURBEL_PIN,OUTPUT); + digitalWrite(O_DEURBEL_PIN, false); + + // Setup the buzzer + pinMode(O_BUZZER_PIN,OUTPUT); + + W_lastSend=millis(); +} + +void presentation() +{ + // Send the sketch version information to the gateway and Controller + sendSketchInfo("Meterkast", "2.1"); + + // Register this device as power sensor + present(W_CHILD_ID, S_WATER); + + // Fetch last known pulse count value from gw + request(W_CHILD_ID, V_VAR1); + + //present Voordeur + present(d1_CHILD_ID, S_DOOR); + //present Deurbel drukknop + present(d2_CHILD_ID, S_LIGHT); + //present Deurbel disable + present(DIS_DEURBEL_CHILD_ID, S_LIGHT); + send(DIS_DEURBEL_msg.set(0)); + //present Deurbel relais + present(BEL_CHILD_ID, S_LIGHT); + //present BUZZER + present(BUZZER_CHILD_ID, S_LIGHT); +} + +void loop() +{ + unsigned long now = millis(); + //unsigned long currentTime = millis(); + + //Read watermeter input + W_puls = digitalRead(W_DIGITAL_INPUT_SENSOR); + if (W_puls != W_prevpuls) + { + Serial.println("Water puls ontvangen"); + W_onPulse(); + W_prevpuls = W_puls; + } + + // Only send values at a maximum frequency or woken up from sleep + bool W_sendTime = now - W_lastSend > W_SEND_FREQUENCY; + if (W_pcReceived && W_sendTime) + { + if (W_flow != W_oldflow) + { + W_oldflow = W_flow; + + Serial.print("l/min:"); + Serial.println(W_flow); + + // Check that we dont get unresonable large flow value. + // could hapen when long wraps or false interrupt triggered + if (W_flow<((unsigned long)W_MAX_FLOW)) + { + send(flowMsg.set(W_flow, 2)); // Send flow value to gw + } + } + + // No Pulse count received in 2min + if(now - W_lastPulse > 120000){ + W_flow = 0; + } + + // Pulse count has changed + if (W_pulseCount != W_oldPulseCount) { + W_oldPulseCount = W_pulseCount; + + Serial.print("W_pulsecount:"); + Serial.println(W_pulseCount); + + send(lastCounterMsg.set(W_pulseCount)); // Send pulsecount value to gw in VAR1 + + double W_volume = ((double)W_pulseCount/((double)W_PULSE_FACTOR)); + if (W_volume != W_oldvolume) { + W_oldvolume = W_volume; + + Serial.print("volume:"); + Serial.println(W_volume, 3); + + send(volumeMsg.set(W_volume, 3)); // Send volume value to gw + } + } + + W_lastSend = now; + } + else if (W_sendTime && !W_pcReceived) + { + // No count received. Try requesting it again + request(W_CHILD_ID, V_VAR1); + W_lastSend=now; + } + + //Door switch 1 + d1_debouncer.update(); + // Get the update value + int d1_value = d1_debouncer.read(); + //If door status changed + if (d1_value != d1_oldValue) + { + // Send in the new value + send(d1_msg.set(d1_value==HIGH ? 1 : 0)); + d1_oldValue = d1_value; + } + + //Door switch 2 - Deurbel + d2_debouncer.update(); + // Get the update value + int d2_value = d2_debouncer.read(); + //If door status changed + if (d2_value != d2_oldValue) + { + + if (d2_value == HIGH) + { + digitalWrite(O_DEURBEL_PIN, false); + deurbel_on = false; + } + else + { + if(Bel_Disabled==false) + { + Serial.print("!! Deurbel !!"); + digitalWrite(O_DEURBEL_PIN, true); + t_deurbel = millis(); + deurbel_on = true; + } + } + + // Send in the new value + send(d2_msg.set(d2_value==HIGH ? 0 : 1)); + d2_oldValue = d2_value; + } + + if(deurbel_on == true && (t_deurbel + T_DEURBEL_ON < now)) + { + digitalWrite(O_DEURBEL_PIN, false); + deurbel_on = false; + } + + if(W_lastSend > now) + W_lastSend = now; +} + + + +// Check incomming messages +void receive(const MyMessage &message) +{ + //If last know water value + if (message.sensor==W_CHILD_ID && message.type==V_VAR1) { + W_pulseCount = W_oldPulseCount = message.getLong(); + Serial.print("Received last W_pulse count from gw:"); + Serial.println(W_pulseCount); + W_pcReceived = true; + } + + //Message of type V_LIGHT ? + if (message.type==V_LIGHT) + { + if (message.sensor==DIS_DEURBEL_CHILD_ID) + { + if(message.getBool()==1) + { + Bel_Disabled = true; + Serial.println("Domoticz --> Deurbel Disabled !!"); + } + else + { + Bel_Disabled = false; + Serial.println("Domoticz --> Deurbel Enabled !!"); + } + } + + + } +} + +//Puls from watermeter +void W_onPulse() +{ + Serial.println("Watermeter"); + + unsigned long W_newBlink = micros(); + unsigned long W_interval = W_newBlink-W_lastBlink; + + W_lastBlink = W_newBlink; + + if (W_interval!=0) + { + W_lastPulse = millis(); + if (W_interval<250000L) + { + // Sometimes we get interrupt on RISING, 500000 = 0.5sek debounce ( max 120 l/min) + return; + } + W_flow = (60000000.0 /W_interval) / W_ppl; + W_pulseCount++; + } +}