1
1
/*
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
+
19
19
*******************************
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
+ */
36
37
37
38
// Enable debug prints
38
39
#define MY_DEBUG
46
47
#include < MySensors.h>
47
48
48
49
#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.
50
51
#define SLEEP_MODE false // Watt value can only be reported when sleep mode is false.
51
52
#define MAX_WATT 10000 // Max watt value to report. This filters outliers.
52
53
#define CHILD_ID 1 // Id of the sensor child
53
54
54
55
uint32_t SEND_FREQUENCY =
55
56
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
57
58
bool pcReceived = false ;
58
59
volatile uint32_t pulseCount = 0 ;
59
- volatile uint32_t lastBlink = 0 ;
60
+ volatile uint32_t lastBlinkmicros = 0 ;
61
+ volatile uint32_t lastBlinkmillis = 0 ;
60
62
volatile uint32_t watt = 0 ;
61
63
uint32_t oldPulseCount = 0 ;
62
64
uint32_t oldWatt = 0 ;
63
65
double oldkWh;
64
66
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);
68
70
69
71
70
72
void setup ()
@@ -74,16 +76,16 @@ void setup()
74
76
75
77
// Use the internal pullup to be able to hook up this sketch directly to an energy meter with S0 output
76
78
// 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);
78
80
79
81
attachInterrupt (digitalPinToInterrupt (DIGITAL_INPUT_SENSOR), onPulse, RISING);
80
- lastSend= millis ();
82
+ lastSend = millis ();
81
83
}
82
84
83
85
void presentation ()
84
86
{
85
87
// Send the sketch version information to the gateway and Controller
86
- sendSketchInfo (" Energy Meter" , " 1.0 " );
88
+ sendSketchInfo (F ( " Energy Meter" ), F ( " 1.1 " ) );
87
89
88
90
// Register this device as power sensor
89
91
present (CHILD_ID, S_POWER);
@@ -97,9 +99,9 @@ void loop()
97
99
if (pcReceived && (SLEEP_MODE || sendTime)) {
98
100
// New watt value has been calculated
99
101
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
101
103
// could happen when long wraps or false interrupt triggered
102
- if (watt< ((uint32_t )MAX_WATT)) {
104
+ if (watt < ((uint32_t )MAX_WATT)) {
103
105
send (wattMsg.set (watt)); // Send watt value to gw
104
106
}
105
107
Serial.print (" Watt:" );
@@ -110,7 +112,7 @@ void loop()
110
112
// Pulse count value has changed
111
113
if (pulseCount != oldPulseCount) {
112
114
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));
114
116
oldPulseCount = pulseCount;
115
117
if (kWh != oldkWh) {
116
118
send (kWhMsg .set (kWh , 4 )); // Send kWh value to gw
@@ -119,9 +121,9 @@ void loop()
119
121
}
120
122
lastSend = now;
121
123
} 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.
123
125
request (CHILD_ID, V_VAR1);
124
- lastSend= now;
126
+ lastSend = now;
125
127
}
126
128
127
129
if (SLEEP_MODE) {
@@ -142,13 +144,21 @@ void receive(const MyMessage &message)
142
144
void onPulse ()
143
145
{
144
146
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
148
152
return ;
149
153
}
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;
152
162
}
153
163
pulseCount++;
154
164
}
0 commit comments