muckmuckmuck
Posts: 9
Joined: Fri Feb 12, 2016 6:22 am

Pulse output water meter (using pigpio?)

Fri Jun 21, 2019 6:35 am

Hi, I have an EKM water meter, with pulse output. It can output up to 6 pulses per second. I have it wired per the following diagram, using a pull up resistor to GPIO 27, pin 3 (on my pi3)
0SDVlAJ.jpg
0SDVlAJ.jpg (14.54 KiB) Viewed 1585 times
My ultimate goal is to increment the pulse count, which I will output to disk once per minute.

From what I can gather, using pigpio is a good (preferred?) method for reading pulses, and I've installed the daemon, but I'm hoping to find some example code for getting started, since I'm not really sure where to get started. I've checked the pigpio website, but as far as I can tell, none of the examples apply to my use case?

Thanks in advance!

User avatar
OutoftheBOTS
Posts: 711
Joined: Tue Aug 01, 2017 10:06 am

Re: Pulse output water meter (using pigpio?)

Fri Jun 21, 2019 9:48 pm

pigpio is definitely the only way to read fast pulses but considering your only get pulses up to 6Hz then software will easily keep up at this speed.

A simple python call back will get the job done :)

muckmuckmuck
Posts: 9
Joined: Fri Feb 12, 2016 6:22 am

Re: Pulse output water meter (using pigpio?)

Fri Jun 21, 2019 10:03 pm

OutoftheBOTS wrote: pigpio is definitely the only way to read fast pulses but considering your only get pulses up to 6Hz then software will easily keep up at this speed.

A simple python call back will get the job done :)
That makes sense. Do you know of a simple python script to get me started? I'm comfortable in bash, but not familiar with python, or have any practical experience with call backs. I don't mind learning, but would be helpful to start with a working example :)

User avatar
joan
Posts: 13998
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Pulse output water meter (using pigpio?)

Fri Jun 21, 2019 10:22 pm

As OutoftheBOTS says - any GPIO library/module will handle what you want.

Here is a simple pigpio script which prints the reading every 6 second.

Code: Select all

#!/usr/bin/env python

import time
import pigpio

GPIO=27

pi = pigpio.pi()
if not pi.connected:
   exit()

cb = pi.callback(GPIO)

prev = 0

while True:
   now = cb.tally()
   diff = now - prev
   prev = now
   print(diff)
   time.sleep(6)
   

muckmuckmuck
Posts: 9
Joined: Fri Feb 12, 2016 6:22 am

Re: Pulse output water meter (using pigpio?)

Sat Jun 22, 2019 5:51 am

joan wrote:
Fri Jun 21, 2019 10:22 pm
As OutoftheBOTS says - any GPIO library/module will handle what you want.

Here is a simple pigpio script which prints the reading every 6 second.

Code: Select all

#!/usr/bin/env python

import time
import pigpio

GPIO=27

pi = pigpio.pi()
if not pi.connected:
   exit()

cb = pi.callback(GPIO)

prev = 0

while True:
   now = cb.tally()
   diff = now - prev
   prev = now
   print(diff)
   time.sleep(6)
   
Thanks! I hooked up a button in place of my water meter, and when I press the button, I'm getting responses with the code above, but the numbers are way off. sometimes by 2 or 3x. If I press the button 3 times, I often get 7, 8, 9, or 11 as a value (with a few 3's thrown in). I tried switching to a pull down resistor instead of a pull up resistor, and the results are the same.

Any ideas on what could cause this?

User avatar
joan
Posts: 13998
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Pulse output water meter (using pigpio?)

Sat Jun 22, 2019 6:45 am

If you are usung a button rather than an actual water meter you are likely suffering from mechanical contact bounce.

As an experiment enter the following from the command line to filter the bounce.

pigs fg 27 5000 # filter out all bounce less than 5000 µs

pigs fg 27 0 # cancel filter when done

muckmuckmuck
Posts: 9
Joined: Fri Feb 12, 2016 6:22 am

Re: Pulse output water meter (using pigpio?)

Sat Jun 22, 2019 7:55 pm

joan wrote:
Sat Jun 22, 2019 6:45 am
If you are usung a button rather than an actual water meter you are likely suffering from mechanical contact bounce.

As an experiment enter the following from the command line to filter the bounce.

pigs fg 27 5000 # filter out all bounce less than 5000 µs

pigs fg 27 0 # cancel filter when done
Thanks, that indeed was the problem. I'm going to try hooking it up to my actual water meter today.

I've tried both pull up and pull down configuration during my testing, is there any reason one is better for my application over the other? My understanding is it wouldn't matter because the meter will "pulse" a full cycle of up/down, it's not holding up or holding down, so I'm just counting the pulse, and don't care about what state it is "left in". But I wanted to confirm.

P.S. Also, thanks for your code, it was the perfect starting point for me, and I now have something working (with push button) based on your code sample.

User avatar
joan
Posts: 13998
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Pulse output water meter (using pigpio?)

Sat Jun 22, 2019 8:26 pm

The need for a pull (up or down) is dependent on the electronics built in to your pulse meter.

The hobby ones I have used have so called open collector outputs. This means the output data line is connected to ground during each pulse and otherwise floats. You need to make sure it floats to something other than ground so you connect a pull-up to 3V3 to the data line. If you don't have a pull-up the output line will always read 0.

muckmuckmuck
Posts: 9
Joined: Fri Feb 12, 2016 6:22 am

Re: Pulse output water meter (using pigpio?)

Sat Jun 22, 2019 9:50 pm

joan wrote:
Sat Jun 22, 2019 8:26 pm
The need for a pull (up or down) is dependent on the electronics built in to your pulse meter.

The hobby ones I have used have so called open collector outputs. This means the output data line is connected to ground during each pulse and otherwise floats. You need to make sure it floats to something other than ground so you connect a pull-up to 3V3 to the data line. If you don't have a pull-up the output line will always read 0.
I connected it to my water meter (sold as commercial/landlord certified, fwiw - not "hobby", but they don't release specs because they just want to sell you their own pulse counter), and ran roughly the max volume of water through it, and it produced accurate numbers, with the following caveats:
* I had to use the filter you specified earlier. Without the filter I got a bunch of high flyers, similar to my push button test.
* I tried it in both pull up and pull down configuration, and it didn't make a difference. Accurate numbers with filter, high flyers without filter.

I'm going to go with pull up unless there's a reason to go otherwise?
Does the fact that I'm having to use the filter indicate something is wrong with my configuration?
IMG_1799.JPG
IMG_1799.JPG (19.09 KiB) Viewed 1440 times

User avatar
joan
Posts: 13998
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Pulse output water meter (using pigpio?)

Sat Jun 22, 2019 10:10 pm

Perhaps it is mechanical as well and their pulse counter also filters out the transients. I doubt your configuration could cause this problem.

You can set the filter from Python.

http://abyz.me.uk/rpi/pigpio/python.htm ... tch_filter

muckmuckmuck
Posts: 9
Joined: Fri Feb 12, 2016 6:22 am

Re: Pulse output water meter (using pigpio?)

Sun Jun 30, 2019 6:06 pm

I got my pi hooked up to my water meter "for real" yesterday, with normal household traffic going through it. It worked fine for about 8 hours with readings that make sense. Then it started going crazy and registering 24 pulses every 6 seconds for a few hours, that weren't actually happening. Killing, and restarting the program, immediately brought the readings back to their true value of 0.

I haven't setup a service yet, so I'm currently start with: nohup ./read-meter.py &

Sample of log file output when I killed it, and then re started it (You can see it switch from 24 pulses to 0 pulses):

Code: Select all

pulse-diff, pulse total (should match meter), date, time, epoch time
24 78003 2019-06-30 17:50:45 1561917045
24 78027 2019-06-30 17:50:51 1561917051
24 78051 2019-06-30 17:50:57 1561917057
24 78075 2019-06-30 17:51:03 1561917063
24 78099 2019-06-30 17:51:09 1561917069
24 78123 2019-06-30 17:51:15 1561917075
24 78147 2019-06-30 17:51:21 1561917081
24 78171 2019-06-30 17:51:27 1561917087
24 78195 2019-06-30 17:51:33 1561917093
24 78219 2019-06-30 17:51:39 1561917099
24 78243 2019-06-30 17:51:45 1561917105
0 78243 2019-06-30 17:51:54 1561917114
0 78243 2019-06-30 17:52:00 1561917120
0 78243 2019-06-30 17:52:06 1561917126
0 78243 2019-06-30 17:52:12 1561917132
0 78243 2019-06-30 17:52:18 1561917138
My python (2.7) code:

Code: Select all

#!/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 running total 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)
#print (result.group(1))
prev_total = int(result.group(1))
prev = prev_total
total = prev_total
while True:
   total = 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)

Any idea why I was getting the false readings?

User avatar
joan
Posts: 13998
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Pulse output water meter (using pigpio?)

Sun Jun 30, 2019 7:04 pm

Could be a bug. I'm busy at the moment so won't look now. Perhaps later.

I don't understand why you do total = total + tally. I'd only expect that if you were zeroing tally after every reading.

muckmuckmuck
Posts: 9
Joined: Fri Feb 12, 2016 6:22 am

Re: Pulse output water meter (using pigpio?)

Sun Jun 30, 2019 8:04 pm

joan wrote:
Sun Jun 30, 2019 7:04 pm
Could be a bug. I'm busy at the moment so won't look now. Perhaps later.

I don't understand why you do total = total + tally. I'd only expect that if you were zeroing tally after every reading.
I think you may be right about using total, and cb.talley() incorrectly. I don't understand why it looked like it was working for a while though, since I got what appeared to be legitimate numbers. Regardless I've now updated it, and will let it run for a bit. I'm mostly responding to say thanks for pointing out something potentially stupid that wasn't related at all to your library, so don't burn any cycles on looking for another mistake for now. Thanks :)

Code: Select all

#!/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)

Return to “Automation, sensing and robotics”