// 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++; } }