This sensor node is attached to the gas meter in my home. It uses a 2,4 GHz RF link to a MySensors-to-MQTT gateway to report natural gas consumption data to my home automation controller. The gas meter is of the type that creates magnetic pulses when the meter dial moves, so the connection is contact-less, and works without access to the inside of the “official” meter from the utility company.
Initially, MyGasMeter only reports incremental data:
- frequently, it reports the incremental pulse count since the last report.
- once per hour, it reports flow [liters/hour] calculated from pulse count.
Once it has received a base count value from the controller (see below), it also starts reporting absolute data:
- frequently, it reports the absolute pulse count, i.e. base value + pulses since power on.
- once per hour, it reports total gas volume [liters] consumed, i.e. (base value + pulses since power on) * liters/pulse.
With this two-stage approach, the node will always report correct absolute pulse count, even if the gateway misses a message now and then. Also, you can replace the battery on the node and then re-initialize it for the correct absolute pulse count, without relying on EEPROM memory.
In my home automation setup, this is integrated with openHAB, but it should also be usable with other controllers, because all communication is done via MQTT.
The node must be battery-powered (read: low supply current, sleep as much as possible), but it can’t use the MySensors sleep() function, because it needs a fairly accurate time base so it can report flow in liters per hour.
It uses the (not so accurate) internal RC oscillator of the AVR to clock the CPU, but a (much more accurate) external 32768 Hz crystal to clock Timer2, which generates interrupts every 10ms, so it can debounce the reed switch, and do all other housekeeping as needed.
In between interrupts, it sleeps in SLEEP_MODE_PWR_SAVE mode, which stops most of the processor’s peripherals, except for Timer2. During sleep, Timer0 as used by the Arduino framework is stopped, so we can’t rely on the Arduino millis() function for timing. Instead, we use a milliseconds counter incremented by the Timer2 ISR for timing purposes (has an hour passed? should we report pulse count or flow or climate?).
Source code and schematics are available in Github. For a more detailed technical description , please visit my blog.