Skip to content

Commit 896220b

Browse files
mfalkviddtekka007
authored andcommitted
Revert the revert 1306 energy meter pulse sensor itslav (#1313)
* Add support for less than 1 blink per hour * Apply Arduino IDE auto-formatting (readability++) * Minor spelling/grammar fixes * Fix copyright date regression
1 parent 40f4deb commit 896220b

File tree

1 file changed

+62
-52
lines changed

1 file changed

+62
-52
lines changed
Lines changed: 62 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,39 @@
11
/*
2-
* The MySensors Arduino library handles the wireless radio link and protocol
3-
* between your home built sensors/actuators and HA controller of choice.
4-
* The sensors forms a self healing radio network with optional repeaters. Each
5-
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
6-
* network topology allowing messages to be routed to nodes.
7-
*
8-
* Created by Henrik Ekblad <[email protected]>
9-
* Copyright (C) 2013-2019 Sensnology AB
10-
* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
11-
*
12-
* Documentation: http://www.mysensors.org
13-
* Support Forum: http://forum.mysensors.org
14-
*
15-
* This program is free software; you can redistribute it and/or
16-
* modify it under the terms of the GNU General Public License
17-
* version 2 as published by the Free Software Foundation.
18-
*
2+
The MySensors Arduino library handles the wireless radio link and protocol
3+
between your home built sensors/actuators and HA controller of choice.
4+
The sensors forms a self healing radio network with optional repeaters. Each
5+
repeater and gateway builds a routing tables in EEPROM which keeps track of the
6+
network topology allowing messages to be routed to nodes.
7+
8+
Created by Henrik Ekblad <[email protected]>
9+
Copyright (C) 2013-2019 Sensnology AB
10+
Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
11+
12+
Documentation: http://www.mysensors.org
13+
Support Forum: http://forum.mysensors.org
14+
15+
This program is free software; you can redistribute it and/or
16+
modify it under the terms of the GNU General Public License
17+
version 2 as published by the Free Software Foundation.
18+
1919
*******************************
20-
*
21-
* REVISION HISTORY
22-
* Version 1.0 - Henrik Ekblad
23-
*
24-
* DESCRIPTION
25-
* This sketch provides an example how to implement a LM393 PCB
26-
* Use this sensor to measure kWh and Watt of your house meter
27-
* You need to set the correct pulsefactor of your meter (blinks per kWh).
28-
* The sensor starts by fetching current kWh value from gateway.
29-
* Reports both kWh and Watt back to gateway.
30-
*
31-
* Unfortunately millis() won't increment when the Arduino is in
32-
* sleepmode. So we cannot make this sensor sleep if we also want
33-
* to calculate/report watt value.
34-
* http://www.mysensors.org/build/pulse_power
35-
*/
20+
21+
REVISION HISTORY
22+
Version 1.0 - Henrik Ekblad
23+
Version 1.1 - Peter Andersson added millis watt calculation if time between pulses > 1h
24+
25+
DESCRIPTION
26+
This sketch provides an example how to implement a LM393 PCB
27+
Use this sensor to measure kWh and Watt of your house meter
28+
You need to set the correct pulsefactor of your meter (blinks per kWh).
29+
The sensor starts by fetching current kWh value from gateway.
30+
Reports both kWh and Watt back to gateway.
31+
32+
Unfortunately millis() won't increment when the Arduino is in
33+
sleepmode. So we cannot make this sensor sleep if we also want
34+
to calculate/report watt value.
35+
http://www.mysensors.org/build/pulse_power
36+
*/
3637

3738
// Enable debug prints
3839
#define MY_DEBUG
@@ -46,25 +47,26 @@
4647
#include <MySensors.h>
4748

4849
#define DIGITAL_INPUT_SENSOR 3 // The digital input you attached your light sensor. (Only 2 and 3 generates interrupt!)
49-
#define PULSE_FACTOR 1000 // Number of blinks per of your meter
50+
#define PULSE_FACTOR 1000 // Number of blinks per kWh of your meter. Normally 1000.
5051
#define SLEEP_MODE false // Watt value can only be reported when sleep mode is false.
5152
#define MAX_WATT 10000 // Max watt value to report. This filters outliers.
5253
#define CHILD_ID 1 // Id of the sensor child
5354

5455
uint32_t SEND_FREQUENCY =
5556
20000; // Minimum time between send (in milliseconds). We don't want to spam the gateway.
56-
double ppwh = ((double)PULSE_FACTOR)/1000; // Pulses per watt hour
57+
double ppwh = ((double)PULSE_FACTOR) / 1000; // Pulses per watt hour
5758
bool pcReceived = false;
5859
volatile uint32_t pulseCount = 0;
59-
volatile uint32_t lastBlink = 0;
60+
volatile uint32_t lastBlinkmicros = 0;
61+
volatile uint32_t lastBlinkmillis = 0;
6062
volatile uint32_t watt = 0;
6163
uint32_t oldPulseCount = 0;
6264
uint32_t oldWatt = 0;
6365
double oldkWh;
6466
uint32_t lastSend;
65-
MyMessage wattMsg(CHILD_ID,V_WATT);
66-
MyMessage kWhMsg(CHILD_ID,V_KWH);
67-
MyMessage pcMsg(CHILD_ID,V_VAR1);
67+
MyMessage wattMsg(CHILD_ID, V_WATT);
68+
MyMessage kWhMsg(CHILD_ID, V_KWH);
69+
MyMessage pcMsg(CHILD_ID, V_VAR1);
6870

6971

7072
void setup()
@@ -74,16 +76,16 @@ void setup()
7476

7577
// Use the internal pullup to be able to hook up this sketch directly to an energy meter with S0 output
7678
// If no pullup is used, the reported usage will be too high because of the floating pin
77-
pinMode(DIGITAL_INPUT_SENSOR,INPUT_PULLUP);
79+
pinMode(DIGITAL_INPUT_SENSOR, INPUT_PULLUP);
7880

7981
attachInterrupt(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR), onPulse, RISING);
80-
lastSend=millis();
82+
lastSend = millis();
8183
}
8284

8385
void presentation()
8486
{
8587
// Send the sketch version information to the gateway and Controller
86-
sendSketchInfo("Energy Meter", "1.0");
88+
sendSketchInfo(F("Energy Meter"), F("1.1"));
8789

8890
// Register this device as power sensor
8991
present(CHILD_ID, S_POWER);
@@ -97,9 +99,9 @@ void loop()
9799
if (pcReceived && (SLEEP_MODE || sendTime)) {
98100
// New watt value has been calculated
99101
if (!SLEEP_MODE && watt != oldWatt) {
100-
// Check that we don't get unreasonable large watt value.
102+
// Check that we don't get unreasonable large watt value, which
101103
// could happen when long wraps or false interrupt triggered
102-
if (watt<((uint32_t)MAX_WATT)) {
104+
if (watt < ((uint32_t)MAX_WATT)) {
103105
send(wattMsg.set(watt)); // Send watt value to gw
104106
}
105107
Serial.print("Watt:");
@@ -110,7 +112,7 @@ void loop()
110112
// Pulse count value has changed
111113
if (pulseCount != oldPulseCount) {
112114
send(pcMsg.set(pulseCount)); // Send pulse count value to gw
113-
double kWh = ((double)pulseCount/((double)PULSE_FACTOR));
115+
double kWh = ((double)pulseCount / ((double)PULSE_FACTOR));
114116
oldPulseCount = pulseCount;
115117
if (kWh != oldkWh) {
116118
send(kWhMsg.set(kWh, 4)); // Send kWh value to gw
@@ -119,9 +121,9 @@ void loop()
119121
}
120122
lastSend = now;
121123
} else if (sendTime && !pcReceived) {
122-
// No pulse count value received. Try requesting it again
124+
// No pulse count value received from controller. Try requesting it again.
123125
request(CHILD_ID, V_VAR1);
124-
lastSend=now;
126+
lastSend = now;
125127
}
126128

127129
if (SLEEP_MODE) {
@@ -142,13 +144,21 @@ void receive(const MyMessage &message)
142144
void onPulse()
143145
{
144146
if (!SLEEP_MODE) {
145-
uint32_t newBlink = micros();
146-
uint32_t interval = newBlink-lastBlink;
147-
if (interval<10000L) { // Sometimes we get interrupt on RISING
147+
uint32_t newBlinkmicros = micros();
148+
uint32_t newBlinkmillis = millis();
149+
uint32_t intervalmicros = newBlinkmicros - lastBlinkmicros;
150+
uint32_t intervalmillis = newBlinkmillis - lastBlinkmillis;
151+
if (intervalmicros < 10000L && intervalmillis < 10L) { // Sometimes we get interrupt on RISING
148152
return;
149153
}
150-
watt = (3600000000.0 /interval) / ppwh;
151-
lastBlink = newBlink;
154+
if (intervalmillis < 360000) { // Less than an hour since last pulse, use microseconds
155+
watt = (3600000000.0 / intervalmicros) / ppwh;
156+
} else {
157+
watt = (3600000.0 / intervalmillis) /
158+
ppwh; // more thAn an hour since last pulse, use milliseconds as micros will overflow after 70min
159+
}
160+
lastBlinkmicros = newBlinkmicros;
161+
lastBlinkmillis = newBlinkmillis;
152162
}
153163
pulseCount++;
154164
}

0 commit comments

Comments
 (0)