-
Notifications
You must be signed in to change notification settings - Fork 113
/
Copy pathWaterMeterPulseSensor2.ino
166 lines (133 loc) · 5.04 KB
/
WaterMeterPulseSensor2.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/*
Use this sensor to measure volume and flow of your house watermeter.
You need to set the correct pulsefactor of your meter (pulses per m3).
The sensor starts by fetching current volume reading from gateway (VAR 1).
Reports both volume and flow 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 flow.
Sensor on pin 3
Contribution: Hek, adapted by epierre to reed water meter
License: Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0)
*/
#include <MySensor.h>
#include <SPI.h>
#define DIGITAL_INPUT_SENSOR 3 // The digital input you attached your sensor. (Only 2 and 3 generates interrupt!)
#define PULSE_FACTOR 1000 // Nummber of blinks per m3 of your meter (One rotation/liter)
#define SLEEP_MODE false // flowvalue can only be reported when sleep mode is false.
#define MAX_FLOW 40 // Max flow (l/min) value to report. This filetrs outliers.
#define INTERRUPT DIGITAL_INPUT_SENSOR-2 // Usually the interrupt = pin -2 (on uno/nano anyway)
#define CHILD_ID 5 // Id of the sensor child
unsigned long SEND_FREQUENCY = 20000; // Minimum time between send (in seconds). We don't want to spam the gateway.
MySensor gw;
MyMessage flowMsg(CHILD_ID,V_FLOW);
MyMessage volumeMsg(CHILD_ID,V_VOLUME);
MyMessage pcMsg(CHILD_ID,V_VAR1);
double ppl = ((double)PULSE_FACTOR)/1000; // Pulses per liter
volatile unsigned long pulseCount = 0;
volatile unsigned long lastBlink = 0;
volatile double flow = 0;
boolean pcReceived = false;
unsigned long oldPulseCount = 0;
unsigned long newBlink = 0;
double oldflow = 0;
double volume;
double oldvolume;
unsigned long lastSend;
unsigned long lastPulse;
unsigned long currentTime;
boolean metric;
long lastDebounce = 0;
long debounceDelay = 500; // Ignore bounces under 1/2 second
void setup()
{
gw.begin(incomingMessage);
// Send the sketch version information to the gateway and Controller
gw.sendSketchInfo("Water Meter", "1.0 reed");
// Register this device as Waterflow sensor
gw.present(CHILD_ID, S_WATER);
// Fetch last known pulse count value from gw
gw.request(CHILD_ID, V_VAR1);
//Serial.print("Last pulse count from gw:");
//Serial.println(pulseCount);
// attachInterrupt(INTERRUPT, onPulse, RISING);
lastSend = millis();
// Setup the reed
pinMode(DIGITAL_INPUT_SENSOR,INPUT);
// Activate internal pull-up
digitalWrite(DIGITAL_INPUT_SENSOR,HIGH);
attachInterrupt(INTERRUPT, onPulse, FALLING);
//led blinking
pinMode(13, OUTPUT);
}
void loop()
{
gw.process();
currentTime = millis();
// Only send values at a maximum frequency or woken up from sleep
bool sendTime = currentTime - lastSend > SEND_FREQUENCY;
if (pcReceived && (SLEEP_MODE || sendTime)) {
// New flow value has been calculated
if (!SLEEP_MODE && flow != oldflow) {
// Check that we dont get unresonable large flow value.
// could hapen when long wraps or false interrupt triggered
if (flow<((unsigned long)MAX_FLOW)) {
gw.send(flowMsg.set(flow, 2)); // Send flow value to gw
}
//Serial.print("l/min:");
//Serial.println(flow);
oldflow = flow;
}
// No Pulse count in 2min
if(currentTime - lastPulse > 120000){
flow = 0;
}
// Pulse count has changed
if (pulseCount != oldPulseCount) {
gw.send(pcMsg.set(pulseCount)); // Send volumevalue to gw VAR1
double volume = ((double)pulseCount/((double)PULSE_FACTOR));
oldPulseCount = pulseCount;
if (volume != oldvolume) {
gw.send(volumeMsg.set(volume, 3)); // Send volume value to gw
oldvolume = volume;
}
}
lastSend = currentTime;
} else if (sendTime && !pcReceived) {
// No count received. Try requesting it again
gw.request(CHILD_ID, V_VAR1);
lastSend=currentTime;
}
if (SLEEP_MODE) {
gw.sleep(SEND_FREQUENCY);
}
}
void incomingMessage(const MyMessage &message) {
if (message.type==V_VAR1) {
pulseCount = oldPulseCount = message.getLong();
Serial.print("Received last pulse count from gw:");
Serial.println(pulseCount);
pcReceived = true;
}
}
void onPulse()
{
if (!SLEEP_MODE) {
unsigned long newBlink = micros();
unsigned long interval = newBlink-lastBlink;
lastPulse = millis();
if (interval<500000L) {
// Sometimes we get interrupt on RISING, 500000 = 0.5sek debounce ( max 120 l/min)
return;
}
flow = (60000000.0 /interval) / ppl;
lastBlink = newBlink;
}
if( (millis() - lastDebounce) > debounceDelay){
pulseCount++;
lastDebounce = millis();
digitalWrite(13, HIGH); // turn the LED on (HIGH is the voltage level)
delay(500); // wait for a second
digitalWrite(13, LOW); // turn the LED off by making the voltage LOW
}
}