A few months ago, I deployed a SPWM-075-HD, hooked up to my raspberry pi, and figured I should write it all down for others, before I forgot how I did it

I had big plans for lots of improvements to make once I got the initial setup going, but since it's been a few months, and I haven't made those changes yet, I figured I shouldn't let perfection stand in the way of sharing what is good enough, so here's what I have, and some of the process.
* I'm using the pigpio library for counting interrupts - pigpio, from what I understand can handle very high frequency pulse counts, which is absolutely not required for this project... but I started with it, and so I stuck with it.
* pigpiod (pigpio daemon) must be started and running before my meter-reader script will work.
* I have this hooked up to a raspberry pi, and I configure all my raspberry pi with ramdisks for /tmp, /var/log, and a few other non-standard things (to minimize writes to the flash drive, and make the drive last longer). Because of this, I am logging changes to my "durable" storage, and live streamed log data to my ram disk (in /tmp). I had plans to send this to a DB, MQTT, etc, but haven't done that yet.
* I'm not a developer, and I know just enough to be dangerous, so I'm sure someone could have written better code, but this works great for me. After 4 months, I can say this is 100% accurate for me, with a small caveat

* The caveat - I have a well with 2,000ft of pipe, and 400ft of head, and this water meter is down near the bottom of the hill, which means when the pump kicks on, my water pressure goes from 60 psi - 80 psi for a brief second, which can cause the analog dial in the meter to jump, which triggers a reading, then fall back, which then triggers another reading. I have a log of all the time my pump has kicked on (since it's also controlled by a raspberry pi!), so when I subtract the number of times the pump has kicked on, I get a number that almost perfectly matches the physical meter read out. I haven't figured out how to filter these out in software, but in the end, it's a very small number, and accurate enough for me. The pulse counting is accurate though, it's just that a pulse is not necessarily indicative of usage.
* Like one of the other threads I found on this board, I also was getting jumpy pulse readings, so I implemented a 5,000 microsecond glitch filter, which eliminated the jumpy pulses.
* This thread was essential for getting started. EKM should publish this data more formally on the product page.
Installing and configuring pigpio daemon to run:
Code: Select all
root@rentalpi:~# apt-get install pigpio
root@rentalpi:~# cat /etc/systemd/system/multi-user.target.wants/pigpiod.service
[Unit]
Description=Daemon required to control GPIO pins via pigpio
[Service]
ExecStart=/usr/bin/pigpiod -l
ExecStop=/bin/systemctl kill pigpiod
Type=forking
[Install]
WantedBy=multi-user.target
root@rentalpi:~#
Code: Select all
root@rentalpi:~/watermeter# cat watermeter-pulse.py
#!/usr/bin/env python
import datetime
import time
import pigpio
import re
GPIO=27
pi = pigpio.pi()
if not pi.connected:
exit()
cb = pi.callback(GPIO)
pi.set_glitch_filter(27, 5000)
#prev = 0
### I need to add code here to verify this file exists
### If it doesn't exist, I need to set the defaults to 0 so it will at least start
# Read from durable log file.
with open('/root/watermeter-durable.txt') as f:
for line in f:
pass
last_line = line
f.close()
#Pull previous total from log file, to continue tallying from that point.
re_pattern = '^\d+\s(\d+)'
result = re.search(re_pattern, last_line)
durable_total = int(result.group(1))
prev = durable_total
while True:
#total = cb.tally()
total = durable_total + cb.tally()
diff = total - prev
prev = total
date_human = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
epoch_time = int(time.time())
print datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),"Running Total:",total,"Differiential:",diff
#Write all results to ephemeral ram disk
tmpfh = open("/tmp/watermeter.txt", "a")
tmpfh.write (str(diff) + ' ' + str(total) + ' ' + str(date_human) + ' ' + str(epoch_time) + '\n')
tmpfh.close()
# If there is activity, write it to durable log file.
if diff > 0:
durablefh = open("/root/watermeter-durable.txt", "a")
durablefh.write (str(diff) + ' ' + str(total) + ' ' + str(date_human) + ' ' + str(epoch_time) + '\n')
durablefh.close()
time.sleep(6)
root@rentalpi:~/watermeter# cat /etc/systemd/system/multi-user.target.wants/watermeter-pulse.service
[Unit]
Description=Water Meter pulse counter - requires pigpiod
[Service]
ExecStart=/usr/bin/python /root/watermeter/watermeter-pulse.py
StandardOutput=null
[Install]
WantedBy=multi-user.target
Alias=watermeter-pulse.service
root@rentalpi:~/watermeter#
root@rentalpi:~/watermeter# tail -10 /root/watermeter-durable.txt
6 40011 2019-09-02 22:53:51 1567464831
4 40015 2019-09-02 22:53:57 1567464837
1 40016 2019-09-02 22:54:09 1567464849
2 40018 2019-09-02 23:10:22 1567465822
2 40020 2019-09-02 23:10:28 1567465828
1 40021 2019-09-02 23:48:18 1567468098
1 40022 2019-09-02 23:49:12 1567468152
1 40023 2019-09-03 02:28:56 1567477736
1 40024 2019-09-03 02:33:38 1567478018
1 40025 2019-09-03 05:11:58 1567487518
root@rentalpi:~/watermeter#
root@rentalpi:~/watermeter# tail -10 /tmp/watermeter.txt
0 40025 2019-09-03 05:20:58 1567488058
0 40025 2019-09-03 05:21:05 1567488065
0 40025 2019-09-03 05:21:11 1567488071
0 40025 2019-09-03 05:21:17 1567488077
0 40025 2019-09-03 05:21:23 1567488083
0 40025 2019-09-03 05:21:29 1567488089
0 40025 2019-09-03 05:21:35 1567488095
0 40025 2019-09-03 05:21:41 1567488101
0 40025 2019-09-03 05:21:47 1567488107
0 40025 2019-09-03 05:21:53 1567488113
root@rentalpi:~/watermeter#
<Number of pulses detected> <Total running tally for life of meter> <Date in human readable format> <seconds since epoch - Unix time>
I also have a cron job which runs once a minute, and reads the log file, and sends data to zabbix, where I graph changes, and record the running tally of the meter. That script is really ugly, because I repurposed another script I wrote, so it's full of garbage, I won't post it here, but here is what it looks like in zabbix when there is water usage: And just for giggles, I also monitor my water tank depth, and well water depth, but it's not related to this stuff:
OH! almost forgot physical wiring. I have it configured as a switch with a pull up resistor,
water meters red wire goes to RPI Pin 13 (GPIO 27) via a 1k resistor, and RPI 3.3v supply via 10k resistor.
Black wire is hooked up to RPI ground.