I finally built my set-up with the LDR (were lying in my working room for months...). Conclusion: it works!
htca
@htca
Best posts made by htca
-
RE: combining pulse counters
Latest posts made by htca
-
RE: combining pulse counters
I finally built my set-up with the LDR (were lying in my working room for months...). Conclusion: it works!
-
RE: combining pulse counters
I will give it a try. I ordered also the LDR variants of these.
M. -
RE: combining pulse counters
I use this one:
I used earlier which I made myself, but on a raspberry pi. Reading out analogue, passed it through a ADC and fed it to the pi.
Now use the one above and linked it to the mega. Adjusting the resistance by the pot-meter will get me always on or always off.
-
RE: combining pulse counters
I managed to get it working. First issue was to get the Mega working with the mega.
I needed to change MyConfig.h:
#define MY_RF24_CS_PIN 53
I used CE on pin 9 (and not 40) and further more:
My sketch:
// Enable debug prints #define MY_DEBUG // Enable and select radio type attached #define MY_RADIO_NRF24 #include <MySensors.h> // electricity #define DIGITAL_INPUT_SENSOR_e 18 // The digital input you attached your light sensor. (Only 2 and 3 generates interrupt!) #define PULSE_FACTOR_e 1000 // Nummber of blinks per KWH of your meeter #define SLEEP_MODE false // Watt-value can only be reported when sleep mode is false. #define MAX_WATT_e 10000 // Max watt value to report. This filetrs outliers. #define CHILD_ID_e 1 // Id of the sensor child // Water #define DIGITAL_INPUT_SENSOR_w 19 // The digital input you attached your sensor. (Only 2 and 3 generates interrupt!) #define PULSE_FACTOR_w 1000 // Nummber of blinks per m3 of your meter (One rotation/liter) #define MAX_FLOW_w 40 // Max flow (l/min) value to report. This filters outliers. #define CHILD_ID_w 2 // Id of the sensor child // Gas #define DIGITAL_INPUT_SENSOR_g 20 // The digital input you attached your sensor. (Only 2 and 3 generates interrupt!) #define PULSE_FACTOR_g 1000 // Nummber of blinks per m3 of your meter (One rotation/liter) #define MAX_FLOW_g 40 // Max flow (l/min) value to report. This filters outliers. #define CHILD_ID_g 3 // Id of the sensor child unsigned long SEND_FREQUENCY = 30000; // Minimum time between send (in milliseconds). We don't want to spam the gateway. //unsigned long SEND_FREQUENCY = 20000; // Minimum time between send (in milliseconds). We don't wnat to spam the gateway. double ppwh = ((double)PULSE_FACTOR_e)/1000; // Pulses per watt hour double pplw = ((double)PULSE_FACTOR_w)/1000; double pplg = ((double)PULSE_FACTOR_g)/1000; //electricity bool pcReceived_e = false; volatile unsigned long pulseCount_e = 0; volatile unsigned long lastBlink_e = 0; volatile unsigned long watt = 0; unsigned long oldPulseCount_e = 0; unsigned long oldWatt = 0; double oldKwh; unsigned long lastSend_e; // water volatile unsigned long pulseCount_w = 0; volatile unsigned long lastBlink_w = 0; volatile double flow_w = 0; bool pcReceived_w = false; unsigned long oldPulseCount_w = 0; unsigned long newBlink_w = 0; double oldflow_w = 0; double volume_w =0; double oldvolume_w =0; unsigned long lastSend_w =0; unsigned long lastPulse_w =0; // gas volatile unsigned long pulseCount_g = 0; volatile unsigned long lastBlink_g = 0; volatile double flow_g = 0; bool pcReceived_g = false; unsigned long oldPulseCount_g = 0; unsigned long newBlink_g = 0; double oldflow_g = 0; double volume_g =0; double oldvolume_g =0; unsigned long lastSend_g =0; unsigned long lastPulse_g =0; // electricity MyMessage wattMsg(CHILD_ID_e,V_WATT); MyMessage kwhMsg(CHILD_ID_e,V_KWH); MyMessage pcMsg(CHILD_ID_e,V_VAR1); // Water MyMessage waterflowMsg(CHILD_ID_w,V_FLOW); MyMessage watervolumeMsg(CHILD_ID_w,V_VOLUME); MyMessage waterlastCounterMsg(CHILD_ID_w,V_VAR2); // Gas MyMessage gasflowMsg(CHILD_ID_g,V_FLOW); MyMessage gasvolumeMsg(CHILD_ID_g,V_VOLUME); MyMessage gaslastCounterMsg(CHILD_ID_g,V_VAR3); void setup() { // Fetch last known pulse count value from gw request(CHILD_ID_e, V_VAR1); request(CHILD_ID_w, V_VAR2); request(CHILD_ID_g, V_VAR3); // Use the internal pullup to be able to hook up this sketch directly to an energy meter with S0 output // If no pullup is used, the reported usage will be too high because of the floating pin pinMode(DIGITAL_INPUT_SENSOR_e,INPUT_PULLUP); pinMode(DIGITAL_INPUT_SENSOR_w,INPUT_PULLUP); pinMode(DIGITAL_INPUT_SENSOR_g,INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR_e), onPulse_e, RISING); attachInterrupt(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR_w), onPulse_w, RISING); attachInterrupt(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR_g), onPulse_g, RISING); lastSend_e=millis(); lastSend_w=millis(); lastSend_g=millis(); } void presentation() { // Send the sketch version information to the gateway and Controller sendSketchInfo("Meterkast Marcel", "1.0"); // Register this device as power sensor present(CHILD_ID_e, S_POWER); present(CHILD_ID_w, S_WATER); present(CHILD_ID_g, S_GAS); } void loop() { unsigned long now = millis(); // Only send values at a maximum frequency or woken up from sleep bool sendTime = now - lastSend_e > SEND_FREQUENCY; if (pcReceived_e && (SLEEP_MODE || sendTime)) { // New watt value has been calculated if (!SLEEP_MODE && watt != oldWatt) { // Check that we dont get unresonable large watt value. // could hapen when long wraps or false interrupt triggered if (watt<((unsigned long)MAX_WATT_e)) { send(wattMsg.set(watt)); // Send watt value to gw } Serial.print("Watt:"); Serial.println(watt); oldWatt = watt; } // Pulse count has changed if (pulseCount_e != oldPulseCount_e) { send(pcMsg.set(pulseCount_e)); // Send pulse count value to gw double kwh = ((double)pulseCount_e/((double)PULSE_FACTOR_e)); oldPulseCount_e = pulseCount_e; if (kwh != oldKwh) { send(kwhMsg.set(kwh, 4)); // Send kwh value to gw oldKwh = kwh; } } lastSend_e = now; } else if (sendTime && !pcReceived_e) { // No count received. Try requesting it again request(CHILD_ID_e, V_VAR1); lastSend_e=now; } unsigned long currentTime = millis(); // Only send values at a maximum frequency or woken up from sleep if (SLEEP_MODE || (currentTime - lastSend_w > SEND_FREQUENCY)) { lastSend_w=currentTime; if (!pcReceived_w) { //Last Pulsecount not yet received from controller, request it again request(CHILD_ID_w, V_VAR2); return; } if (!SLEEP_MODE && flow_w != oldflow_w) { oldflow_w = flow_w; Serial.print("l/min:"); Serial.println(flow_w); // Check that we dont get unresonable large flow value. // could hapen when long wraps or false interrupt triggered if (flow_w<((unsigned long)MAX_FLOW_w)) { send(waterflowMsg.set(flow_w, 2)); // Send flow value to gw } } // No Pulse count received in 2min if(currentTime - lastPulse_w > 120000){ flow_w = 0; } // Pulse count has changed if ((pulseCount_w != oldPulseCount_w)||(!SLEEP_MODE)) { oldPulseCount_w = pulseCount_w; Serial.print("pulsecount_w:"); Serial.println(pulseCount_w); send(waterlastCounterMsg.set(pulseCount_w)); // Send pulsecount value to gw in VAR1 double volume_w = ((double)pulseCount_w/((double)PULSE_FACTOR_w)); if ((volume_w != oldvolume_w)||(!SLEEP_MODE)) { oldvolume_w = volume_w; Serial.print("volume_w:"); Serial.println(volume_w, 3); send(watervolumeMsg.set(volume_w, 3)); // Send volume value to gw } } } // Only send values at a maximum frequency or woken up from sleep if (SLEEP_MODE || (currentTime - lastSend_g > SEND_FREQUENCY)) { lastSend_g=currentTime; if (!pcReceived_g) { //Last Pulsecount not yet received from controller, request it again request(CHILD_ID_g, V_VAR3); return; } if (!SLEEP_MODE && flow_g != oldflow_g) { oldflow_g = flow_g; Serial.print("l/min:"); Serial.println(flow_g); // Check that we dont get unresonable large flow value. // could hapen when long wraps or false interrupt triggered if (flow_g<((unsigned long)MAX_FLOW_g)) { send(gasflowMsg.set(flow_g, 2)); // Send flow value to gw } } // No Pulse count received in 2min if(currentTime - lastPulse_g > 120000){ flow_g = 0; } // Pulse count has changed if ((pulseCount_g != oldPulseCount_g)||(!SLEEP_MODE)) { oldPulseCount_g = pulseCount_g; Serial.print("pulsecount_g:"); Serial.println(pulseCount_g); send(gaslastCounterMsg.set(pulseCount_g)); // Send pulsecount value to gw in VAR1 double volume_g = ((double)pulseCount_g/((double)PULSE_FACTOR_g)); if ((volume_g != oldvolume_g)||(!SLEEP_MODE)) { oldvolume_g = volume_g; Serial.print("volume_g:"); Serial.println(volume_g, 3); send(gasvolumeMsg.set(volume_g, 3)); // Send volume value to gw } } } if (SLEEP_MODE) { sleep(SEND_FREQUENCY); } } void receive(const MyMessage &message) { if (message.type==V_VAR1) { pulseCount_e = oldPulseCount_e = message.getLong(); Serial.print("Received last pulse count from gw_e:"); Serial.println(pulseCount_e); pcReceived_e = true; } if (message.type==V_VAR2) { unsigned long gwPulseCount_w=message.getULong(); pulseCount_w += gwPulseCount_w; flow_w=oldflow_w=0; Serial.print("Received last pulse count from gw_w:"); Serial.println(pulseCount_w); pcReceived_w = true; } if (message.type==V_VAR3) { unsigned long gwPulseCount_g=message.getULong(); pulseCount_g += gwPulseCount_g; flow_g=oldflow_g=0; Serial.print("Received last pulse count from gw_g:"); Serial.println(pulseCount_g); pcReceived_g = true; } } void onPulse_e() { if (!SLEEP_MODE) { unsigned long newBlink_e = micros(); unsigned long interval_e = newBlink_e-lastBlink_e; if (interval_e<10000L) { // Sometimes we get interrupt on RISING return; } watt = (3600000000.0 /interval_e) / ppwh; lastBlink_e = newBlink_e; } pulseCount_e++; } void onPulse_w() { if (!SLEEP_MODE) { unsigned long newBlink_w = micros(); unsigned long interval_w = newBlink_w-lastBlink_w; if (interval_w!=0) { lastPulse_w = millis(); if (interval_w<500000L) { // Sometimes we get interrupt on RISING, 500000 = 0.5sek debounce ( max 120 l/min) return; } flow_w = (60000000.0 /interval_w) / pplw; } lastBlink_w = newBlink_w; } pulseCount_w++; } void onPulse_g() { if (!SLEEP_MODE) { unsigned long newBlink_g = micros(); unsigned long interval_g = newBlink_g-lastBlink_g; if (interval_g!=0) { lastPulse_g = millis(); if (interval_g<500000L) { // Sometimes we get interrupt on RISING, 500000 = 0.5sek debounce ( max 120 l/min) return; } flow_g = (60000000.0 /interval_g) / pplg; } lastBlink_g = newBlink_g; } pulseCount_g++; }
I still got one issue; my led on the meter does not give enough light to have a n interrupt. does anybody have a suggestion how to get the interrupt?
-
RE: combining pulse counters
@ericvdb What's the difference between a interrupt and a digital input (I am a civil engineer with some programming background)
-
RE: combining pulse counters
@ericvdb So the only solution is to use 2 nano's?
-
RE: combining pulse counters
@ericvdb but it should be possible to make a 3rd one available I think?
-
RE: combining pulse counters
I managed to have the script compiled without errors. But I found out that the 3rd sensor is not checked or giving interrupts (the led on the sensor indicates that there are pulses). With playing around and checking some regular sketches, I made a mistake on my breadboard and I burnt my nano :-(. So I ordered a new one.....
Script so far is shown below, but it might be that I have to built a script from scratch with mysensors api. If anyone has any directions to follow on this, it would be great!/** * The MySensors Arduino library handles the wireless radio link and protocol * between your home built sensors/actuators and HA controller of choice. * The sensors forms a self healing radio network with optional repeaters. Each * repeater and gateway builds a routing tables in EEPROM which keeps track of the * network topology allowing messages to be routed to nodes. * * Created by Henrik Ekblad <henrik.ekblad@mysensors.org> * Copyright (C) 2013-2015 Sensnology AB * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors * * Documentation: http://www.mysensors.org * Support Forum: http://forum.mysensors.org * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * ******************************* * * REVISION HISTORY * Version 1.0 - Henrik EKblad * * DESCRIPTION * This sketch provides an example how to implement a distance sensor using HC-SR04 * 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. * http://www.mysensors.org/build/pulse_power */ // Enable debug prints #define MY_DEBUG // Enable and select radio type attached #define MY_RADIO_NRF24 //#define MY_RADIO_RFM69 #include <MySensors.h> #define SLEEP_MODE false // values can only be reported when sleep mode is false. //electriciteit #define DIGITAL_INPUT_SENSOR_e 2 // The digital input you attached your light sensor. (Only 2 and 3 generates interrupt!) #define PULSE_FACTOR_e 1000 // Nummber of blinks per KWH of your meeter #define MAX_WATT 10000 // Max watt value to report. This filetrs outliers. #define CHILD_ID_e 1 // Id of the sensor child //water #define DIGITAL_INPUT_SENSOR_w 3 // The digital input you attached your light sensor. (Only 2 and 3 generates interrupt!) #define PULSE_FACTOR_w 1000 // Nummber of blinks per KWH of your meeter #define MAX_WATER 10000 // Max watt value to report. This filetrs outliers. #define CHILD_ID_w 2 // Id of the sensor child //gas #define DIGITAL_INPUT_SENSOR_g 4 // The digital input you attached your light sensor. (Only 2 and 3 generates interrupt!) #define PULSE_FACTOR_g 1000 // Nummber of blinks per KWH of your meeter #define MAX_GAS 10000 // Max watt value to report. This filetrs outliers. #define CHILD_ID_g 3 // Id of the sensor child unsigned long SEND_FREQUENCY = 20000; // Minimum time between send (in milliseconds). We don't wnat to spam the gateway. double ppwh_e = ((double)PULSE_FACTOR_e)/1000; // Pulses per watt hour double ppwh_w = ((double)PULSE_FACTOR_w)/1000; // Pulses per watt hour double ppwh_g = ((double)PULSE_FACTOR_g)/1000; // Pulses per watt hour bool pcReceived = false; volatile unsigned long pulseCount_e = 0; volatile unsigned long pulseCount_w = 0; volatile unsigned long pulseCount_g = 0; volatile unsigned long lastBlink_e = 0; volatile unsigned long lastBlink_w = 0; volatile unsigned long lastBlink_g = 0; volatile unsigned long watt = 0; volatile unsigned long waterflow = 0; volatile unsigned long gasflow = 0; unsigned long oldPulseCount_e = 0; unsigned long oldPulseCount_w = 0; unsigned long oldPulseCount_g = 0; unsigned long oldWatt = 0; unsigned long oldWaterf = 0; unsigned long oldgasf = 0; double oldKwh; double oldwater; double oldgas; unsigned long lastSend; MyMessage wattMsg(CHILD_ID_e,V_WATT); MyMessage kwhMsg(CHILD_ID_e,V_KWH); MyMessage pcMsg(CHILD_ID_e,V_VAR1); MyMessage waterMsg(CHILD_ID_w,V_FLOW); MyMessage watervolumeMsg(CHILD_ID_w,V_VOLUME); MyMessage lastCounterwaterMsg(CHILD_ID_w,V_VAR2); MyMessage gasMsg(CHILD_ID_g,V_FLOW); MyMessage gasvolumeMsg(CHILD_ID_g,V_VOLUME); MyMessage lastCountegasrMsg(CHILD_ID_g,V_VAR3); void setup() { // Fetch last known pulse count value from gw request(CHILD_ID_e, V_VAR1); request(CHILD_ID_w, V_VAR2); request(CHILD_ID_g, V_VAR3); // Use the internal pullup to be able to hook up this sketch directly to an energy meter with S0 output // If no pullup is used, the reported usage will be too high because of the floating pin pinMode(DIGITAL_INPUT_SENSOR_e,INPUT_PULLUP); pinMode(DIGITAL_INPUT_SENSOR_w,INPUT_PULLUP); pinMode(DIGITAL_INPUT_SENSOR_g,INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR_e), onPulse_e, RISING); attachInterrupt(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR_w), onPulse_w, RISING); attachInterrupt(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR_g), onPulse_g, RISING); lastSend=millis(); } void presentation() { // Send the sketch version information to the gateway and Controller sendSketchInfo("Marcel Meterkast", "1.0"); // Register this device as power sensor present(CHILD_ID_e, S_POWER); present(CHILD_ID_w, S_WATER); present(CHILD_ID_g, S_GAS); } void loop() { unsigned long now = millis(); // Only send values at a maximum frequency or woken up from sleep bool sendTime = now - lastSend > SEND_FREQUENCY; if (pcReceived && (SLEEP_MODE || sendTime)) { // New watt value has been calculated // electricity first if (!SLEEP_MODE && watt != oldWatt) { // Check that we dont get unresonable large watt value. // could hapen when long wraps or false interrupt triggered if (watt<((unsigned long)MAX_WATT)) { send(wattMsg.set(watt)); // Send watt value to gw } Serial.print("Watt:"); Serial.println(watt); oldWatt = watt; } // send water if (!SLEEP_MODE && waterflow != oldWaterf) { // Check that we dont get unresonable large watt value. // could hapen when long wraps or false interrupt triggered if (waterflow<((unsigned long)MAX_WATER)) { send(wattMsg.set(waterflow)); // Send watt value to gw } Serial.print("water:"); Serial.println(waterflow); oldWaterf = waterflow; } // send gas if (!SLEEP_MODE && gasflow != oldgasf) { // Check that we dont get unresonable large watt value. // could hapen when long wraps or false interrupt triggered if (gasflow<((unsigned long)MAX_GAS)) { send(wattMsg.set(gasflow)); // Send watt value to gw } Serial.print("gas:"); Serial.println(gasflow); oldgas = gasflow; } // Pulse cout has changed if (pulseCount_e != oldPulseCount_e) { send(pcMsg.set(pulseCount_e)); // Send pulse count value to gw double kwh = ((double)pulseCount_e/((double)PULSE_FACTOR_e)); oldPulseCount_e = pulseCount_e; if (kwh != oldKwh) { send(kwhMsg.set(kwh, 4)); // Send kwh value to gw oldKwh = kwh; } } if (pulseCount_w != oldPulseCount_w) { send(pcMsg.set(pulseCount_w)); // Send pulse count value to gw double water = ((double)pulseCount_w/((double)PULSE_FACTOR_w)); oldPulseCount_w = pulseCount_w; if (water != oldwater) { send(watervolumeMsg.set(water, 4)); // Send watervolume value to gw oldwater = water; } } if (pulseCount_g != oldPulseCount_g) { send(pcMsg.set(pulseCount_g)); // Send pulse count value to gw double gas = ((double)pulseCount_g/((double)PULSE_FACTOR_g)); oldPulseCount_g = pulseCount_g; if (gas != oldgas) { send(gasvolumeMsg.set(gas, 4)); // Send gas value to gw oldgas = gas; } } lastSend = now; } else if (sendTime && !pcReceived) { // No count received. Try requesting it again request(CHILD_ID_e, V_VAR1); request(CHILD_ID_w, V_VAR2); request(CHILD_ID_g, V_VAR3); lastSend=now; } if (SLEEP_MODE) { sleep(SEND_FREQUENCY); } } void receive(const MyMessage &message) { if (message.type==V_VAR1) { pulseCount_e = oldPulseCount_e = message.getLong(); Serial.print("Received last pulse count from gw for:"); Serial.println(pulseCount_e); pcReceived = true; } } void onPulse_e() { Serial.println("electricity pulse!"); if (!SLEEP_MODE) { unsigned long newBlink = micros(); unsigned long interval = newBlink-lastBlink_e; if (interval<10000L) { // Sometimes we get interrupt on RISING return; } watt = (3600000000.0 /interval) / ppwh_e; lastBlink_e = newBlink; } pulseCount_e++; } void onPulse_w() { Serial.println("water pulse!"); if (!SLEEP_MODE) { unsigned long newBlink = micros(); unsigned long interval = newBlink-lastBlink_w; if (interval<10000L) { // Sometimes we get interrupt on RISING return; } waterflow = (3600000000.0 /interval) / ppwh_w; lastBlink_w = newBlink; } pulseCount_w++; } void onPulse_g() { Serial.println("gas pulse!"); if (!SLEEP_MODE) { unsigned long newBlink = micros(); unsigned long interval = newBlink-lastBlink_g; if (interval<10000L) { // Sometimes we get interrupt on RISING return; } gasflow = (3600000000.0 /interval) / ppwh_g; lastBlink_g = newBlink; } pulseCount_w++; }```
-
combining pulse counters
I am trying to combine 3 pulse counters on 1 nano. I have a regular pulse counter based on a LDR, which counts the led pulses on the electricity meter and I have two pulse counters (one on the gas and one on the watermeter) counting the mirrors passages on the wheels.
I would like to combine those on one nano and I started with the example of the electricity meter and modified it for 3 sensors. Than I got stuck...My errors starts here:
MyMessage flowMsg(CHILD_ID_g,V_FLOW); MyMessage volumeMsg(CHILD_ID_g,V_VOLUME); MyMessage lastCounterMsg(CHILD_ID_g,V_VAR3);
The full script:
/** * The MySensors Arduino library handles the wireless radio link and protocol * between your home built sensors/actuators and HA controller of choice. * The sensors forms a self healing radio network with optional repeaters. Each * repeater and gateway builds a routing tables in EEPROM which keeps track of the * network topology allowing messages to be routed to nodes. * * Created by Henrik Ekblad <henrik.ekblad@mysensors.org> * Copyright (C) 2013-2015 Sensnology AB * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors * * Documentation: http://www.mysensors.org * Support Forum: http://forum.mysensors.org * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * ******************************* * * REVISION HISTORY * Version 1.0 - Henrik EKblad * * DESCRIPTION * This sketch provides an example how to implement a distance sensor using HC-SR04 * 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. * http://www.mysensors.org/build/pulse_power */ // Enable debug prints #define MY_DEBUG // Enable and select radio type attached #define MY_RADIO_NRF24 //#define MY_RADIO_RFM69 #include <MySensors.h> #define SLEEP_MODE false // values can only be reported when sleep mode is false. //electriciteit #define DIGITAL_INPUT_SENSOR_e 2 // The digital input you attached your light sensor. (Only 2 and 3 generates interrupt!) #define PULSE_FACTOR_e 1000 // Nummber of blinks per KWH of your meeter #define MAX_WATT_e 10000 // Max watt value to report. This filetrs outliers. #define CHILD_ID_e 1 // Id of the sensor child //water #define DIGITAL_INPUT_SENSOR_w 3 // The digital input you attached your light sensor. (Only 2 and 3 generates interrupt!) #define PULSE_FACTOR_w 1000 // Nummber of blinks per KWH of your meeter #define MAX_WATER 10000 // Max watt value to report. This filetrs outliers. #define CHILD_ID_w 2 // Id of the sensor child //gas #define DIGITAL_INPUT_SENSOR_g 4 // The digital input you attached your light sensor. (Only 2 and 3 generates interrupt!) #define PULSE_FACTOR_g 1000 // Nummber of blinks per KWH of your meeter #define MAX_GAS 10000 // Max watt value to report. This filetrs outliers. #define CHILD_ID_g 3 // Id of the sensor child unsigned long SEND_FREQUENCY = 20000; // Minimum time between send (in milliseconds). We don't wnat to spam the gateway. double ppwh_e = ((double)PULSE_FACTOR_e)/1000; // Pulses per watt hour double ppwh_w = ((double)PULSE_FACTOR_w)/1000; // Pulses per watt hour double ppwh_g = ((double)PULSE_FACTOR_g)/1000; // Pulses per watt hour bool pcReceived = false; volatile unsigned long pulseCount_e = 0; volatile unsigned long pulseCount_w = 0; volatile unsigned long pulseCount_g = 0; volatile unsigned long lastBlink_e = 0; volatile unsigned long lastBlink_w = 0; volatile unsigned long lastBlink_g = 0; volatile unsigned long watt = 0; volatile unsigned long waterflow = 0; volatile unsigned long gasflow = 0; unsigned long oldPulseCount_e = 0; unsigned long oldPulseCount_w = 0; unsigned long oldPulseCount_g = 0; unsigned long oldWatt = 0; unsigned long oldWater = 0; unsigned long oldGas = 0; double oldKwh; double oldwater; double oldgas; unsigned long lastSend; MyMessage wattMsg(CHILD_ID_e,V_WATT); MyMessage kwhMsg(CHILD_ID_e,V_KWH); MyMessage pcMsg(CHILD_ID_e,V_VAR1); MyMessage flowMsg(CHILD_ID_w,V_FLOW); MyMessage volumeMsg(CHILD_ID_w,V_VOLUME); MyMessage lastCounterMsg(CHILD_ID_w,V_VAR2); MyMessage flowMsg(CHILD_ID_g,V_FLOW); MyMessage volumeMsg(CHILD_ID_g,V_VOLUME); MyMessage lastCounterMsg(CHILD_ID_g,V_VAR3); void setup() { // Fetch last known pulse count value from gw request(CHILD_ID_e, V_VAR1); request(CHILD_ID_w, V_VAR2); request(CHILD_ID_g, V_VAR3); // Use the internal pullup to be able to hook up this sketch directly to an energy meter with S0 output // If no pullup is used, the reported usage will be too high because of the floating pin pinMode(DIGITAL_INPUT_SENSOR_e,INPUT_PULLUP); pinMode(DIGITAL_INPUT_SENSOR_w,INPUT_PULLUP); pinMode(DIGITAL_INPUT_SENSOR_g,INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR_e), onPulse_e, RISING); attachInterrupt(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR_w), onPulse_w, RISING); attachInterrupt(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR_g), onPulse_g, RISING); lastSend=millis(); } void presentation() { // Send the sketch version information to the gateway and Controller sendSketchInfo("Marcel Meterkast", "1.0"); // Register this device as power sensor present(CHILD_ID_e, S_POWER); present(CHILD_ID_w, S_WATER); present(CHILD_ID_g, S_GAS); } void loop() { unsigned long now = millis(); // Only send values at a maximum frequency or woken up from sleep bool sendTime = now - lastSend > SEND_FREQUENCY; if (pcReceived && (SLEEP_MODE || sendTime)) { // New watt value has been calculated // electricity first if (!SLEEP_MODE && watt != oldWatt) { // Check that we dont get unresonable large watt value. // could hapen when long wraps or false interrupt triggered if (watt<((unsigned long)MAX_WATT)) { send(wattMsg.set(watt)); // Send watt value to gw } Serial.print("Watt:"); Serial.println(watt); oldWatt = watt; } // send water if (!SLEEP_MODE && waterflow != oldWater) { // Check that we dont get unresonable large watt value. // could hapen when long wraps or false interrupt triggered if (waterflow<((unsigned long)MAX_WATER)) { send(wattMsg.set(waterflow)); // Send watt value to gw } Serial.print("Gas:"); Serial.println(gasflow); oldWater = waterflow; } // send gas if (!SLEEP_MODE && gasflow != oldGas) { // Check that we dont get unresonable large watt value. // could hapen when long wraps or false interrupt triggered if (gasflow<((unsigned long)MAX_GAS)) { send(wattMsg.set(gasflow)); // Send watt value to gw } Serial.print("gas:"); Serial.println(gasflow); oldGas = gasflow; } // Pulse cout has changed if (pulseCount_e != oldPulseCount_e) { send(pcMsg.set(pulseCount_e)); // Send pulse count value to gw double kwh = ((double)pulseCount_e/((double)PULSE_FACTOR_e)); oldPulseCount_e = pulseCount_e; if (kwh != oldKwh) { send(kwhMsg.set(kwh, 4)); // Send kwh value to gw oldKwh = kwh; } } if (pulseCount_w != oldPulseCount_w) { send(pcMsg.set(pulseCount_w)); // Send pulse count value to gw double water = ((double)pulseCount_w/((double)PULSE_FACTOR_w)); oldPulseCount_w = pulseCount_w; if (water != oldwater) { send(kwhMsg.set(kwh, 4)); // Send kwh value to gw oldwater = water; } } if (pulseCount_g != oldPulseCount_g) { send(pcMsg.set(pulseCount_g)); // Send pulse count value to gw double gas = ((double)pulseCount_g/((double)PULSE_FACTOR_g)); oldPulseCount_g = pulseCount_g; if (gas != oldgas) { send(kwhMsg.set(gas, 4)); // Send kwh value to gw oldgas = gas; } } lastSend = now; } else if (sendTime && !pcReceived) { // No count received. Try requesting it again request(CHILD_ID_e, V_VAR1); request(CHILD_ID_w, V_VAR2); request(CHILD_ID_g, V_VAR3); lastSend=now; } if (SLEEP_MODE) { sleep(SEND_FREQUENCY); } } void receive(const MyMessage &message) { if (message.type==V_VAR1) { pulseCount = oldPulseCount = message.getLong(); Serial.print("Received last pulse count from gw for:"); Serial.println(pulseCount); pcReceived = true; } } void onPulse_e() { if (!SLEEP_MODE) { unsigned long newBlink = micros(); unsigned long interval = newBlink_e-lastBlink_e; if (interval<10000L) { // Sometimes we get interrupt on RISING return; } watt = (3600000000.0 /interval) / ppwh_e; lastBlink_e = newBlink_e; } pulseCount_e++; } void onPulse_w() { if (!SLEEP_MODE) { unsigned long newBlink = micros(); unsigned long interval = newBlink-lastBlink_w; if (interval<10000L) { // Sometimes we get interrupt on RISING return; } waterflow = (3600000000.0 /interval) / ppwh_w; lastBlink_w = newBlink; } pulseCount_w++; } void onPulse_g() { if (!SLEEP_MODE) { unsigned long newBlink = micros(); unsigned long interval = newBlink-lastBlink_g; if (interval<10000L) { // Sometimes we get interrupt on RISING return; } gasflow = (3600000000.0 /interval) / ppwh_g; lastBlink_g = newBlink; } pulseCount_w++; }