I couldn't just lay down in the sofa so I started to test and now I got a code that seems to work. I have tested it for a few days and it seems to count correct.
I made some changes so it will send data every minute and it will send Watt-value even if it is the same value since last time.
I am using VAR2 for second energy meter since I don't know how to config Incomingmessage and seperate VAR1 from different Child_IDs.
I change corrupted interrupts from 10000L to 40000L otherwise it reported interrupts twice.
/**
* 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
* Use this sensor to measure kWh and Watt of your house meter
* You need to set the correct pulsefactor of your meter (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
*/
#include <SPI.h>
#include <MySensor.h>
unsigned long SEND_FREQUENCY = 60000; // Minimum time between send (in milliseconds). We don't want to spam the gateway.
#define SLEEP_MODE false // Watt-value can only be reported when sleep mode is false.
//sensor 1
#define DIGITAL_INPUT_SENSOR_1 2 // The digital input you attached your light sensor. (Only 2 and 3 generates interrupt!)
#define PULSE_FACTOR_1 1000 // Number of blinks per KWH of your meeter
#define MAX_WATT_1 10000 // Max watt value to report. This filters outliers.
#define INTERRUPT_1 DIGITAL_INPUT_SENSOR_1-2 // Usually the interrupt = pin -2 (on uno/nano anyway)
#define CHILD_ID_1 1 // Id of the sensor child
//sensor 2
#define DIGITAL_INPUT_SENSOR_2 3 // The digital input you attached your light sensor. (Only 2 and 3 generates interrupt!)
#define PULSE_FACTOR_2 10000 // Number of blinks per KWH of your meeter
#define MAX_WATT_2 10000 // Max watt value to report. This filters outliers.
#define INTERRUPT_2 DIGITAL_INPUT_SENSOR_2-2 // Usually the interrupt = pin -2 (on uno/nano anyway)
#define CHILD_ID_2 2 // Id of the sensor child
MySensor gw;
//sensor 1
double ppwh_1 = ((double)PULSE_FACTOR_1)/1000; // Pulses per watt hour
boolean pcReceived_1 = false;
volatile unsigned long pulseCount_1 = 0;
volatile unsigned long lastBlink_1 = 0;
volatile unsigned long watt_1 = 0;
unsigned long oldPulseCount_1 = 0;
unsigned long oldWatt_1 = 0;
double oldKwh_1;
unsigned long lastSend_1;
//sensor 2
double ppwh_2 = ((double)PULSE_FACTOR_2)/1000; // Pulses per watt hour
boolean pcReceived_2 = false;
volatile unsigned long pulseCount_2 = 0;
volatile unsigned long lastBlink_2 = 0;
volatile unsigned long watt_2 = 0;
unsigned long oldPulseCount_2 = 0;
unsigned long oldWatt_2 = 0;
double oldKwh_2;
unsigned long lastSend_2;
//sensor 1
MyMessage wattMsg_1(CHILD_ID_1,V_WATT);
MyMessage kwhMsg_1(CHILD_ID_1,V_KWH);
MyMessage pcMsg_1(CHILD_ID_1,V_VAR1);
//sensor 2
MyMessage wattMsg_2(CHILD_ID_2,V_WATT);
MyMessage kwhMsg_2(CHILD_ID_2,V_KWH);
MyMessage pcMsg_2(CHILD_ID_2,V_VAR2);
void setup()
{
gw.begin(incomingMessage);
// Send the sketch version information to the gateway and Controller
gw.sendSketchInfo("Energy Double", "1.0");
// Register this device as power sensor
//sensor 1
gw.present(CHILD_ID_1, S_POWER);
//sensor 2
gw.present(CHILD_ID_2, S_POWER);
//Send new VAR to Gateway
//gw.send(pcMsg_1.set(xxxxxxxxx)); // Send pulse count value to gw
//gw.send(pcMsg_2.set(1895931000)); // Send pulse count value to gw
// Fetch last known pulse count value from gw
//sensor 1
gw.request(CHILD_ID_1, V_VAR1);
//sensor 2
gw.request(CHILD_ID_2, V_VAR2);
//sensor 1
attachInterrupt(INTERRUPT_1, onPulse_1, RISING);
//sensor 2
attachInterrupt(INTERRUPT_2, onPulse_2, RISING);
lastSend_1=millis();
lastSend_2=millis();
}
void loop()
{
gw.process();
//sensor 1
unsigned long now_1 = millis();
// Only send values at a maximum frequency or woken up from sleep
bool sendTime_1 = now_1 - lastSend_1 > SEND_FREQUENCY;
if (pcReceived_1 && (SLEEP_MODE || sendTime_1)) {
// New watt value has been calculated
//if (!SLEEP_MODE && watt_1 != oldWatt_1) {
// Check that we dont get unresonable large watt value.
// could hapen when long wraps or false interrupt triggered
if (watt_1<((unsigned long)MAX_WATT_1)) {
gw.send(wattMsg_1.set(watt_1)); // Send watt value to gw
}
Serial.print("Watt_1:");
Serial.println(watt_1);
oldWatt_1 = watt_1;
//}
// Pulse cout has changed
if (pulseCount_1 != oldPulseCount_1) {
gw.send(pcMsg_1.set(pulseCount_1)); // Send pulse count value to gw
double kwh_1 = ((double)pulseCount_1/((double)PULSE_FACTOR_1));
oldPulseCount_1 = pulseCount_1;
//if (kwh_1 != oldKwh_1) {
gw.send(kwhMsg_1.set(kwh_1, 4)); // Send kwh value to gw
oldKwh_1 = kwh_1;
//}
}
lastSend_1 = now_1;
} else if (sendTime_1 && !pcReceived_1) {
// No count received. Try requesting it again
gw.request(CHILD_ID_1, V_VAR1);
lastSend_1=now_1;
}
//sensor 2
unsigned long now_2 = millis();
// Only send values at a maximum frequency or woken up from sleep
bool sendTime_2 = now_2 - lastSend_2 > SEND_FREQUENCY;
if (pcReceived_2 && (SLEEP_MODE || sendTime_2)) {
// New watt value has been calculated
//if (!SLEEP_MODE && watt_2 != oldWatt_2) {
// Check that we dont get unresonable large watt value.
// could hapen when long wraps or false interrupt triggered
if (watt_2<((unsigned long)MAX_WATT_2)) {
gw.send(wattMsg_2.set(watt_2)); // Send watt value to gw
}
Serial.print("Watt_2:");
Serial.println(watt_2);
oldWatt_2 = watt_2;
//}
// Pulse cout has changed
if (pulseCount_2 != oldPulseCount_2) {
gw.send(pcMsg_2.set(pulseCount_2)); // Send pulse count value to gw
double kwh_2 = ((double)pulseCount_2/((double)PULSE_FACTOR_2));
oldPulseCount_2 = pulseCount_2;
//if (kwh_2 != oldKwh_2) {
gw.send(kwhMsg_2.set(kwh_2, 4)); // Send kwh value to gw
oldKwh_2 = kwh_2;
//}
}
lastSend_2 = now_2;
} else if (sendTime_2 && !pcReceived_2) {
// No count received. Try requesting it again
gw.request(CHILD_ID_2, V_VAR2);
lastSend_2=now_2;
}
if (SLEEP_MODE) {
gw.sleep(SEND_FREQUENCY);
}
}
void incomingMessage(const MyMessage &message) {
if (message.type==V_VAR1) {
pulseCount_1 = oldPulseCount_1 = message.getLong();
Serial.print("Received_1 last pulse count from gw:");
Serial.println(pulseCount_1);
pcReceived_1 = true;
}
if (message.type==V_VAR2) {
pulseCount_2 = oldPulseCount_2 = message.getLong();
Serial.print("Received_2 last pulse count from gw:");
Serial.println(pulseCount_2);
pcReceived_2 = true;
}
}
void onPulse_1()
{
if (!SLEEP_MODE) {
unsigned long newBlink_1 = micros();
unsigned long interval_1 = newBlink_1-lastBlink_1;
if (interval_1<40000L) { // Sometimes we get interrupt on RISING
return;
}
watt_1 = (3600000000.0 /interval_1) / ppwh_1;
lastBlink_1 = newBlink_1;
}
//Serial.println(pulseCount_1);
pulseCount_1++;
//Serial.println(pulseCount_1);
}
void onPulse_2()
{
if (!SLEEP_MODE) {
unsigned long newBlink_2 = micros();
unsigned long interval_2 = newBlink_2-lastBlink_2;
if (interval_2<40000L) { // Sometimes we get interrupt on RISING
return;
}
watt_2 = (3600000000.0 /interval_2) / ppwh_2;
lastBlink_2 = newBlink_2;
}
//Serial.println(pulseCount_2);
pulseCount_2++;
//Serial.println(pulseCount_2);
}