Hello,
I've made a circuit to readout my home gas usage.
I took the water usage sketch from the mysensors site and changed S_WATER into S_GAS.
The readout on my serial port of the arduino is good, i also see this in Domoticz, but some parts don't look fermiliar or in good order, and i like to add something but don't know how..
This is the code:
/**
* 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 - Mark Verstappen
*
* DESCRIPTION
* Use this sensor to measure volume and flow of your house gasmeter.
* 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.
* http://www.mysensors.org/build/pulse_water
*/
// Enable debug prints to serial monitor
#define MY_DEBUG
// Enable and select radio type attached
#define MY_RADIO_NRF24
//#define MY_RADIO_RFM69
#include <Time.h>
#include <TimeLib.h>
#include <SPI.h>
#include <MySensor.h>
#define DIGITAL_INPUT_SENSOR 3 // The digital input you attached your sensor. (Only 2 and 3 generates interrupt!)
#define SENSOR_INTERRUPT DIGITAL_INPUT_SENSOR-2 // Usually the interrupt = pin -2 (on uno/nano anyway)
#define PULSE_FACTOR 100 // 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 0,1 // Max flow (l/min) value to report. This filters outliers.
#define CHILD_ID 1 // Id of the sensor child
unsigned long SEND_FREQUENCY = 30000; // Minimum time between send (in milliseconds). We don't want to spam the gateway.
MyMessage flowMsg(CHILD_ID,V_FLOW);
MyMessage volumeMsg(CHILD_ID,V_VOLUME);
MyMessage lastCounterMsg(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 =0;
double oldvolume =3987.67; // Oude meterstand
unsigned long lastSend =0;
unsigned long lastPulse =0;
void setup()
{
// initialize our digital pins internal pullup resistor so one pulse switches from high to low (less distortion)
pinMode(DIGITAL_INPUT_SENSOR, INPUT_PULLUP);
pulseCount = oldPulseCount = 0;
// Fetch last known pulse count value from gw
request(CHILD_ID, V_VAR1);
lastSend = lastPulse = millis();
attachInterrupt(SENSOR_INTERRUPT, onPulse, FALLING);
}
void presentation() {
// Send the sketch version information to the gateway and Controller
sendSketchInfo("Gas Meter", "1.0");
// Register this device as Gasflow sensor
present(CHILD_ID, S_GAS);
}
void loop()
{
unsigned long currentTime = millis();
// Only send values at a maximum frequency or woken up from sleep
if (SLEEP_MODE || (currentTime - lastSend > SEND_FREQUENCY))
{
lastSend=currentTime;
Serial.println("--------- Debug void loop ------------");
if (!pcReceived) {
//Last Pulsecount not yet received from controller, request it again
request(CHILD_ID, V_VAR1);
return;
}
if (!SLEEP_MODE && flow != oldflow) {
oldflow = flow;
Serial.print("m3/min:");
Serial.println(flow);
// Check that we dont get unresonable large flow value.
// could hapen when long wraps or false interrupt triggered
if (flow<((unsigned long)MAX_FLOW)) {
send(flowMsg.set(flow, 2)); // Send flow value to gw
}
}
// No Pulse count received in 2min
if(currentTime - lastPulse > 120000){
flow = 0;
}
// Pulse count has changed
if ((pulseCount != oldPulseCount)||(!SLEEP_MODE)) {
oldPulseCount = pulseCount;
Serial.println("flow: ");
Serial.print(flow);
// Serial.println(Time.now());
Serial.print("pulsecount: ");
Serial.println(pulseCount);
send(lastCounterMsg.set(pulseCount)); // Send pulsecount value to gw in VAR1
double volume = ((double)pulseCount/((double)PULSE_FACTOR));
if ((volume != oldvolume)||(!SLEEP_MODE)) {
oldvolume = volume;
Serial.print("volume: ");
Serial.println(volume, 3);
Serial.println("---------------------------------------------------");
send(volumeMsg.set(volume, 3)); // Send volume value to gw
}
}
}
if (SLEEP_MODE) {
sleep(SEND_FREQUENCY);
}
}
void receive(const MyMessage &message) {
if (message.type==V_VAR1) {
unsigned long gwPulseCount=message.getULong();
pulseCount += gwPulseCount;
flow=oldflow=0;
Serial.println("--------------- Debug void receive ---------------");
Serial.print("Received last pulse count from gw: ");
Serial.println(pulseCount);
Serial.println("---------------------------------------------------");
pcReceived = true;
}
}
void onPulse()
{
if (!SLEEP_MODE)
{
unsigned long newBlink = micros();
unsigned long interval = newBlink-lastBlink;
Serial.println("--------------- Debug void onPulse ---------------");
// Serial.println("newblink: ");
// Serial.print(newBlink);
// Serial.println("interval: ");
// Serial.print(interval);
// Serial.println();
if (interval!=0)
{
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;
Serial.println("flow = (60000000.0 /interval) / ppl");
Serial.println(flow);
Serial.println("---------------------------------------------------");
}
lastBlink = newBlink;
}
pulseCount++;
}
Domoticz shows this:
The sensor registers each cycle.
-
Pulse counts are 134 wich corrosponds to the 1.340 volume.
1m3 = 100 counts. (1 count is 0.01m3 ) -
What does the 0.230 value represent ??
-
The real count is more, is there a way to incorporate a option, to send a
command through the serial console, wich updates the counter?
For example when in a couple of months something goes wrong, you could update
the counter with the correct value without, changing the compleet sketch, and there
bij stopping the arduino etc.
So some kind of counter update (Adjust) command through the serial console. -
The flow isn't updated instantly, but each five minuts?
I want it to be triggerd when the flow starts, measure, remind all data and when the
flow stops report al the data at once. -
Mysensors uses V_VOLUME and V_FLOW just as bij S_WATER therefore it says
waterflow. So how could you change the type of the sensor (both aren't correct)?
The update (adjust) option would be nice not only for gas measuring but als for water and electricity. (If you want to do it now, you have to dive into the db of domoticz)