FloKra 2fa26e7d15 documentation update, schematic/layout as image | 3 years ago | |
---|---|---|
.. | ||
Firmware_Arduino_ATmega328p | 3 years ago | |
Schematics | 3 years ago | |
README.md | 3 years ago |
Arduino based hardware for capturing impulses from S0 impulse meters.
The main reason for starting this project was, that counting S0 impulses directly with the Raspberry Pi GPIOs has proven me to be unreliable. I did this for a longer time and got intermittent impulses recorded regularly, so that the counters on the actual meters differed from the recorded values more and more over time. At least I made this experience using RasPi GPIO and a python program for reading them. On the other hand, on every downtime of the Raspberry, there are no data recorded at all, so that - again - the actual counters differ with the records with time.
compiled using Arduino 1.8
2 independent configurable S0 inputs/counters
direct implementation of UNITS- and IMPULSES- (between full unit) counters, so that the device can keep track of the actual meters for a long time without the need of an up and running host system, as long as there is electric power available. This was the main reason for me to start this project.
configurable impulses per unit and unit counter per input (currently supports 10/100/1000 imp/unit)
store current unit readings to EEPROM on every change
store impulses between units to EEPROM in configurable intervals
EEPROM endurance
as these values are written far more often we need some kind of wear leveling here
implemented as ring buffer which stores the value and a write counter, every time to another EEPROM cell, until the reserved memory area is full, then starts again at the beginning.
EEPROM area is currently hard coded and set to:
counter 1: 512 bytes or 128 values
counter 2: 128 bytes or 32 values
one dataset is 2 bytes data + 2 bytes write counter
protection against write failures: write counter is written after the data, on restore a valid write counter must be exactly 1 value bigger than the one before, so in every case a not too old value should be restorable
save on no-impulse-timeout (i.E. for gas counters which count several impulses and then be idle for a longer time when the heating has been switched off by the thermostat)
save on fixed interval
store all current unsaved data on power loss, implemented using:
measuring of duration in between impulses (which can then be used to calculate power/momentary usage)
data output via UART on every impulse and on no-impulse/fixed timeout
configuration via UART commands
intended to be used aside a Raspberry Pi or similar, logging data to an InfluxDB server with python program s0meters.py
software function to trigger MCU reset (via GPIO output connected to /RES input) in order to be able to update/flash the MCU without on-site intervention although the normal Arduino flash/reset method doesn´t work by design. This output is normally configured as input and has a pullup resistor (on the Pro Mini board), so that it does not prevent from normal flashing using a USB-UART Arduino interface. Of course this function saves all data to EEPROM before actually resetting the MCU.
WDT enabled, this possibly requires flashing another boot loader depending on the Arduino board used (Pro Minis usually come with a different boot loader than Unos, which does not support WDT - Optiboot works well - I use a custom Optiboot version with baud rate 57600 as is the default for early Pro Mini boards)
Schematics (KiCad) here: Schematics I also created a PCB layout, despite I only built a prototype on breadboard, as it speeds up this process by far. It can be found in schematics folder.
If configuration JSON = 1 (default), the module outputs a JSON formatted dataset on UART on every incoming impulse and on no-impulse-timeout:
{"C":CNUM,"reading":READING,"dTime":DTIME}
where:
default UART baud rate: 57600, 8 data bits, no parity, 1 stop bit
configure impulse counter inputs:
set conf c1 impPerUnit=1000
set conf c1 noImpTout=60
set conf c1 saveInt=15
or as a batch job:
set conf c1 impPerUnit=1000;noImpTout=60;saveInt=15
set conf c2 impPerUnit=100;noImpTout=60;saveIint=15
where:
saveInt in minutes
c1/c2 is the input/counter number
used for initial setting and value corrections
set reading cN UNITCOUNTER[.IMPULSES]
i.E.:
set reading c1 1023.423
where:
IMPULSES: optional, impulses since last unit counter rollover (or comma places on the actual meter)
if a valid value is given, EEPROM area belonging to counter number is formatted and new value stored instantly
Sets ADC value for "power good". POWER GOOD - monitors voltage in front of the onboard voltage regulator powering the AVR/Arduino in order to save all data to EEPROM before power is really gone. To make this possible, supply voltage is much higher than needed for an AVR/Arduino (9-12V) connected to a big (2200uF) capacitor over a decoupling diode (voltage drop 0.6-0.7V) and regulated to Vcc=5V by the Arduino onboard regulator. Vin is measured through a voltage divider of 56k/24k (after the diode). A value of 420 seems to be the minimum at ~7.5V supply voltage (in front of the decoupling diode). Below this the ADC value increases again due to voltage regulator drop out and therefore sinking Vref, so a reasonable safety margin is mandatory here. As we use a 12V supply we set this to 500 for now (which is about ~= 9.0V)
First check current ADC value using:
get pwrgood
Then set new value with a safety margin - do not use a too low value!
set pwrgood 500
command | description |
---|---|
get eeprom | print entire EEPROM content to UART (formatted) |
save data | save all unsaved current data |
debug [1|0] | switch on/off debug output |
format [all|c1|c2] | format EEPROM area (all, or only counter1/2) |
get readings | print current readings to UART as done on every impulse |
get imp cN | get current impulses count of counter N |
get pwrgood | print current power supply ADC value and configured "power good" value |
set pwrgood VALUE | set "power good" to an ADC value. If power supply falls below this value, all data will be saved to EEPROM once and further saving will be stopped until power is "good" again. |
set json 0|1 | enable/disable readings output in JSON format (1=default) |
get conf | print current counters configuration to UART |
get debounce | print current input debounce values (in ms) |
set debounce VALUE[,VALUE2] | set input debounce VALUE = debounce time in ms VALUE2 = debounce recovery time in ms (optional, comma separated) |
set conf cN | counter configuration for counter N, as described above |
save conf | to be called after all configuration changes to store them to EEPROM |
set reading cN | sets the current reading of counter N to value given as described above comma separator is '.' |
get wcount | print write counters of all counters |
reset DELAY | resets the MCU via GPIO output connected to /RESET input used for firmware flashing. [delay] is optional, can be used to fine tune successful flashing with avrdude. |