On the Gazpar and most (gas and water) meters, there a pulse for every rotation of the second wheel from the right. In this case, every 10 litres of gas (or 0.01 m3). This becomes the base unit for this circuit which doesn't count decimal values.
For example, on figure below, the value is 191675. The shift will have to be done on the computer.
Note also that the change of unit/pulse is sometimes done when the smallest value is "6", not "0". Which means that with the figure above, it would be as follow:
Either: "01916754" => 191675 and later "01916758" => 191676 (overshoot mode)
Or: "01916754" => 191674 and later "01916758" => 191675 (undershoot mode)
Your call. Confusing? Oh yes... but there is nothing to do about it. And it doesn't make much difference in the end.
The serial speed is unsually slow (by today's standards) for 2 main reasons:
The microcontroller has to be flashed to run at 1Mhz in order to keep consumption as low as possible and to work even at a low voltage
On these mini microcontollers, there is no hardware UART. It's basically a SoftwareSerial implementation
That said 1200 bit/s is more than enough in our case.
Relative: each pulse will increment the counter starting from zero (default mode). Values are prefixed by a star ('*')
Absolute: the counter is initialised to match the real/physical one. Values are prefixed by a superior sign ('>')
The idea of the relative is that in case of reset, by adding the value to the last known value, it is possible to track the reading.
For example, the last recorded value is 14568 on the computer. There is a reset of the microcontroller and it loses its memory. Next pulses will therefore return '*1 ', '*2 ', etc... The computer just has to add 14568 + 1 = 14569, 14568 + 2, etc... to guess the right values.
Initialising the value
Using a terminal (or from the reading software), just send a inferior sign ('<') followed by the value followed by Carriage Return with 5 seconds.
The stored value will be returned (absolute mode above).
Querying the value
Each pulse will send over the wire the new value but it is also possible to query it by sending a question mark ('?').
The stored value will be returned.
Idealy, the pulse meter should be within meters of the meter (sorry for the pun). The capacitance on the wires is not really an issue but it seems more logical this way (your point of view may be different).
Several possibillities of attachments are possible. Among them:
Using a ESP8266 as a relay
The same way I am using a ESP8266 to forward the reading from the electricity smart meter, it is possible to use it to send the reading periodically. Either by keeping the ESP8266 running, in the case the notification is Synchronous or by waking it up every x minutes and polling the current value (by sending a '?').
Using the serial port on the Raspberry
or a USB Serial adapter if the computer and the meter are not too far apart.
In this case, the shorter the better on the serial side but at 1200 bits/s the risk of trouble is low.
Using a RS-422 or RS-485 link
In this case, the distance can be quite long.
This solution was developped initially for a gas meter but it can be used for any kind of pulse meter: water, door, etc...
The code and schematics are available (AS IS) on github.
It is notorious that modules/chips sold on Chinese marketplaces can be fake ones. Most of the times, it's not much of an issue for non-industrial applications. As long as the components behave properly, it is almost impossible to check their quality/authenticity.
As I wanted to explore the programming of ATtiny85, I ordered a couple of them on AliExpress. Then time flew and a long time after the "return/complain" window was closed, I gave them a try.
Nothing... Impossible to do anything with them. I double-checked the wiring, but I always ended-up with the famous:
"Device signature = 0xffffff".
Reputable French shop on Ebay
Certainly puzzled, I ordered another pair, this time from a shop I previously used succesfully on ebay. Having received them the next day (one big advantage of buying local!), I tested them and they worked straightaway.
Fuses and quartz
One of the main reasons of a bad signature when programming seems that there is a setting of internal fuses to use external quartz at a specific frequency.
I tried my entire stock of quartz (6 "standards" values)... without success.
High voltage programming
The next step was to try "High" Voltage (meaning more that 5 volts, not mains BTW), using these solutions:
which indicate an ATtiny11! For a ATtiny85, it should be 0x930B...
The fuses were (always):
0x6C 0x80 0x6C
Unfortunately ATtiny11 is a very old series which is almost completely forgotten with low specs and can't be programmed easily (ATtiny13 is the replacement).
Photos of a real ATtiny85 :
Photos of a fake (?) ATtiny85 :
It was the first time I faced a deliberate forgery. I certainly bought a fair share of fakes and clones, sometimes knowningly ("Digispark rev3", etc...). The first thing is certainly to run a test ASAP. Apparently sellers are keen to reimburse immediately when notified there ware is not genuine.
Then, to consider real distributors, like in the old days:
Ebay (France): 48H delivery by post => 12€ inc VAT
Reichelt Elektronic: Delivery 2-6 day => 13€ inc VAT
Farnell Europe: Next day UPS delivery => 14.40€ inc VAT and surcharge if order < 30€ HT, only 6.12€ inc VAT otherwise
I always considered the "big" retailers (Mouser, RS, Farnell, Digi-key, ...) as professional only but in reality they seem more and more keen to accomodate small orders too. I far as I can tell, I could order a single unit for 9.50€ inc VAT and delivery. Not necessary the most cost effective but with a risk of counterfeit stuff certainly very low (but even for controlled supply-chains, the risk is never null).
The idea is to keep the counter in RAM and thus the microcontroller always on.
Low power consumption
One of the challenges was to send the ATtiny85 to sleep and waking up only when either a pulse is counted or a serial character is received. I ended-up writing my own code but heavily influenced by this, this, this, this and this. It looks daunting at first but makes sense quickly.
The "PCINT0_vect" in the Interrupt Service Routine meaning all Interrupts from PCINT0 to PCINT5 is a catch and loads of people seem also confused by it.
The first attempt was using a capacitor to debounce the input. It worked flawlessly with the gas meter but these days debouncing tends to be done by the microcontroller itself.
In this case, the counting (increment) is done in the interrupt function itself (The "PCINT0_vect" mentionned above).
This is were troubles started. Because it is not possible to use timers/delays in the interrupt function, the debouncing has to be done in the main loop.
After several iterations, mixing flags and jobs done half synchronally, half asynchronally, the final (working) solution is also the simplest.
In the end, the loop is fairly straightforward and could be summarised by:
Go to sleep.
If woken-up by a serial change, stay awake for 5s before going to sleep. If command received by serial port, read the command and send the reply.
If woken-up by a signal change, stay awake for 0.5s before going to sleep. Read current status of pin 7 (PB2). On a falling edge, increment the counter and publish the new value over the serial port. Wait for 100ms before going back to the loop. This prevents transitions faster than 200ms.
The development was done on the Arduino IDE using https://github.com/SpenceKonde/ATtinyCore using an Arduino Uno as the programmer.
Backup during power outages
The firt idea was to use a supercapacitor (something like 1.5F 5.5V) with a schottky diode in order to maintain the MCU powered.
In theory, it's easy to implement and should work like a treat (between for example 5V and 1.8V). In practice, there were some issues with the "initial" charging (big drop of voltage) and I was disappointed by the performances. Moreover, there is the issue of a big variation of voltage of the supercap (can drop under 2V) in relation to other pins (Vcc, serial).
I am pretty sure that there are good ways to deal with these matters but they certainly require more investigation. It could also explain why, even nowdays, RTC on motherboards are still mainly powered by battery cells rather than supercaps.
An alternative was to use a simple CR2032 lithium battery. These StackExchange answers were a good way to start. This AN1535 application note, also gives a complement (cf Figure 3).
This last document is were I was made aware that the reverse leakage current could be a big issue. I have no plans to have any of my circuits "UL approved" and don't have to follow any american requirements but at the same time, if a risk exists with batteries on the other side of the pond, it is the same over here.
I was planning to use BAT48 Schottky diodes but they may have a higher leakage current than the recommended value (1µA). Renasas Application Note mentions BAT54. The bad new is they exist only as SMD (SOT23-3). The good news is there is a "C" variant which incorporate 2 diodes.
In the end, I put a BAT48 + BAT54C.
Vcc and serial communication were also switched to 3.3V in order to keep all voltages as close as possible.
When running on battery, the following values were measured with a fresh cell:
Voltage of battery : 3.12V (A)
Voltage between GND and after BAT48 and BAT54 diodes (B) : 2.98V
Voltage between GND and Vcc PIN of ATtiny (C) : 2.87V
Which gives the following drops:
BAT48 = 0.14V
BAT54 = 0.11V
Note that drops are higher (~ .2V) when measured using a multimeter in diode mode. Possibly because the current is higher.
First foray into SMDs
As mentionned above, BAT54C diodes only exist in SOT23-3 format. Since even through-hole component can be challenging (specially with bad solder, but this is another issue), I have never been too keen in the SMD variants of components. That said, I discovered that this is a vast world with loads of different sizes (from doable to sheer madness).
Since I hadn't received my SOT23-3 to SIP-3 adapter boards, I decided to solder it directly on the 2.54mm pitch prototype board! Ugly but it worked fine on the first attempt so...
SMDs (at least the 1206 size) might not be evil after all!
Pins and ISP
Since PB0, PB1 and PB2 were available without anything else connected to them, I realised that I basically had almost everything ready for "In-system programming". So I added a "reset" pin (PB5). Et voilà.
Pin on board
Pin on chip
MOSI (Arduino 11)
MISO (Arduino 12)
SCK (Arduino 13)
Reset (Arduino 10)
As usual, this page is for informational purposes only... You assume total responsibility and use at your own risk!
Next time, I'll describe the installation in situ and the (very simple) communication protocol.
Here is some evolution about the Gas Meter 'Gazpar' for which I developped a generic battery backed-up solution.
As mentionned before, the "official" cable is for sale at a hefty price (for what it is) of ~20€. I would have gone for this cable, had the meter been outdoors or in a humid room, but since it is located in my kitchen, I simply used the trick found on some forums: Female dupont wires. And it works very well indeed.
One of the main differences between the electricity and gas smart meters, is that the former will deliver all the information (including current reading) in a continuous way. In case of power cut, upgrade or crash of the microcomputer/microcontroller, nothing is really lost and things will restart as soon as possible.
The gas meter, smart or not, will only give pulses... if nobody is listening, the information is lost and the status of the reading not longer accurate.
Keeping the value
The basic idea is to decouple the counting process from the processing unit. The counting unit should not need any update or needs to restart often.
One idea was to write the current value on a flash memory but these are notoriously bad as time goes by. Wear and tear could soon be an issue.
Apprently, there is a kind of memory called Ferroelectric RAM/FRAM for which the number of write cycle is not a problem. But these are not wildly sold (but can be found as breakout board) and certainly overkill for just keeping a counter.
So in the end, the easiest solution seemed to use a basic ATtiny85 powered and keeping the value in RAM. This solution will be described in the next post.