When I finally moved into my new very own house, I couldn’t wait to start turning it into what is called “smart home”. The first thing that came to my mind was to track the energy consumption. As there are two major sources of energy in the house (power, and gas for heating up the house and water), I needed to figure out how to monitor both. For power there is a digital power meter that even has an IR based communication interface. As for the gas, a classical analog meter was installed by my local provider. For both devices you can buy ready to use sensors, but they’re quite expensive and I also prefer the #DIY way of handling it.
Although one can’t see it on the first sight, monitoring both the digital and analog is quite similar: Both simply count impulses when current or gas is streaming. The digital power meter has a red led that on my device blinks 500 times per 1 kWh whereas the analog gas meter has a clock with a magnetic impulse on every full pass where 100 impulses indicate 1 cubic meter of gas. To get the consumptions for each device, all one needs to do is count those impulses, calculate the delta between two impulses, do some basic calculations and here you are.
So the question was, how to get that running. For the led impulses a photoresistor came into my mind since I already had some in my nodemcu starter kit I bought the other day. As for the magnetic counter I discovered, that you can get a so called reed switch to do the job. A reed switch will close if a magnetic field is detected (called “normally open”, but there are also switches that open on magnetic fields called “normally closed”). You’ll probably know reed switches from door/window-sensors. And quite frankly, I ordered and re-designated such a door sensor to meet my purpose. Also it came with a handy little case that perfectly fit into the mounting point of the gas meter. At thingiverse.com I’ve even found a ready to print case for the reed switch that fits into the mounting interface of the gas meter (see link below) - which will save you additional 30-50€ for a professional case!
It was time to put everything together. Since I wanted to have a small sensor and not an additional Raspberry Pi sitting in the utility room (needing updates, you name it), I bought some tiny D1 mini units based on the ESP8266 microcontroller for the productive application. They’re really cheap (cost around 7€) and come with WiFi onboard. For prototyping, I used the bigger ESP8266 controller found in the starter kit. Using jumper wires the components were connected on a breadboard and it was about time to write the code needed to do listening to impulses, do the calculations and transmit everything over the air for further processing, collection and fancy presentation. The next paragraphs are more about things I learned in order to get the counter running.
To Interrupt or not to interrupt
Both the reed switch and the photoresistor are connected on input pins on the microcontroller. When an impulse occurs, it will change the state of that PIN. Usually the voltage will drop or raise on a digital PIN depending on the setup (Using a so called “PULL UP” method, the PIN is high on default and can be dropped by connecting it to ground through the photoresistor or the reed switch. When setting initially “PULL DOWN”, it’ll be low on default and can be raised to high, when you connect it to 3,3V over both photoresistor or the reed switch.), leading to the state 0 (or 1 in the other case). If you now calculate the delta between two impulses, you’ll get the usage - it’s that simple. There are two ways of checking the state of that PIN: the first one which is how I started, is to simply monitor the PIN permanently by checking if it\'s high or low (1 or 0). A more sophisticated way is to register an interrupt when the state changes and call an interrupt handler routine to do some calculations. The benefit of the latter theoretically is, that you won’t miss any impulse even if the microcontroller is doing something else (e.g. transmitting data via WiFi). The disadvantage in my power meter is that you need a clear 3.3V as high and since I only had a photoresistor, I’d never get a high enough voltage. Also the resistor is quite slow, so the optical impulse would be over before the voltage dropped low enough to become a 0. This wasn’t an issue for the reed switch though, so I decided to use the interrupt method for my gas meter and the non-interrupt method for the power meter. As I mentioned earlier, interrupt is better on paper: In my case there was some noise I couldn\'t find the source of, that lead to an oscillation from time to time, which would distort the status. That’s why I went the non-interrupt eventually for both sensors.
During many iterations I changed the code to mitigate problems that occured in daily production usage. I’ll give you a brief overview of what I was faced with in the following paragraphs.
There are interferences
What works in the lab, won’t probably work in real environments. Both detectors have to handle technical faults, random spikes and other interferences. For example on the optical sensor even the status led of the 8266 board or daylight led to wrong values. To mitigate this, I had to define thresholds. Since I used the analog input pin to connect the photoresistor, I had to define when the value is to be considered as 1 or 0. This is highly related to the power meters LED luminance - in my case a value around 70.
On both the magnetic and the optical sensors there was some kind of glitch from time to time so that spikes in consumptions seemed to happen. Since I new the Qmin (minimum usage detected) and Qmax (maximum usage detected by the meter) of both meters, I calculated the min and max deltas between two impulses. Every time the delta was too small, the value was stalled as it must have been wrong based on the specification of the meters: for the power meter, with the highest load possible (100A) the LED would blink 3 times a second. Therefore a delta below 300 ms was too low to be true. For the gas meter, with the highest gas flow possible (4 cubic meter per hour), I’d get up to one impuls every 9 seconds. This method didn’t work well for the interrupt based counting, though, so I switched back to non interrupt (but kept the code there for further investigations).
Don’t block with too many uploads
As mentioned above there might occur an impulse every 300 ms. Since I was uploading the measurement on every impulse in the first place, the transmission latency (connect to MQTT broker, wifi network latency) blocked further detections and led to missed impulses. Therefore I had to set a minimum frequency of transmission. I have chosen a value of 5 sec between uploads since there is no real benefit in uploading the data more frequently. Also don’t use a hard coded delay method, as this will block the processor so you end up missing impulses. To avoid this, one has to use state variables and go on with the processing and check again later.
When I reset the node, the impulses are lost and so the values are out of sync with the actual meter reading. I could persist the value in the node’s flash, but the many write operations would kill the flash pretty fast. Therefore I decided to use MQTT to push the last value back to the node - if needed.
#DIY #FTW. It’s fun to create your own sensors that have to work non blocking and very fast and operate in real time in order to detect highly frequent impulses. I’ve learned a lot and even had to get back into Kirchhoff’s circuits laws, Ohm’s laws, learn a bit of C++... That’s a fun hobby to have and I highly recommend this to everyone interested in sensor networks and IOT. Last but not least: it’s not that easy at all to build reliable and accurate sensors. Now I kind of understand the higher price of ready to use connected sensors. As to my sensors: Both are running without any problems (it’s been a long way) and actually never miss an impulse even over a longer period of time.