Craynerd
Posts: 37
Joined: Mon Nov 25, 2013 9:09 pm

Interrupt to count pulses on gpio pin every x seconds

Mon Feb 17, 2014 3:56 pm

Hello, I am helping the students at school with a weather station and to measure wind speed I have pulse on a gpio digital pin every rotation. I want to use an interrupt to capture the number of rotations say every 5 or 10 seconds and store this to a variable windSpeed. Pulses will be relatively slow as far as the code goes so a short debounce will be needed.

I'm not really into python and this does need to be in python!

Can anyone suggest a starting point code or even a link to a similar code you know of? I'd appreciate any advice or help.

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

Re: Interrupt to count pulses on gpio pin every x seconds

Mon Feb 17, 2014 5:05 pm

Any of the Python gpio modules should work.

This is how I'd do it using pigpio.

sudo pigpiod # if not already started
./tally.py

Code: Select all

#!/usr/bin/env python

# tally.py

import time

import pigpio

WIND_GPIO=4

pigpio.start()

pigpio.set_mode(WIND_GPIO, pigpio.INPUT)
pigpio.set_pull_up_down(WIND_GPIO, pigpio.PUD_UP)

wind_cb = pigpio.callback(WIND_GPIO, pigpio.FALLING_EDGE)

old_count = 0

while True:

   time.sleep(5)

   count = wind_cb.tally()
   print("counted {} pulses".format(count - old_count))
   old_count = count

pigpio.stop()
WIND_GPIO should be set to the Broadcom numbered gpio you are using.

You can test the software by simulating inputs by entering the following in another window after starting tally.py

pigs w 4 0 # set gpio to be an output
pigs pfs 4 0 # set 10Hz frequency
pigs p 4 128 # start 10 Hz pulses with 50% dutycycle

Change 4 to whatever gpio is being used.

extrememedia
Posts: 1
Joined: Thu Oct 30, 2014 11:12 pm

Re: Interrupt to count pulses on gpio pin every x seconds

Thu Oct 30, 2014 11:16 pm

This is what I did for a one minute interval, seems to work fine.


import threading
from threading import Thread
import time
import sys
from time import sleep
import RPi.GPIO as GPIO, time
import RPi.GPIO as gpio


print 'loading....'

count=0
var1 =1

GPIO.setmode(GPIO.BCM)

GPIO.setup(11, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)


def my_callback(channel):
global count
count=count+1
print count

GPIO.add_event_detect(11, GPIO.RISING, callback=my_callback) # add rising edge detection on a channel

def counter():
while (var1 == 1):
stamp1=count
sleep(60)
stamp2=count
print ('pulses per minute 1 ')
global ppm
ppm = (abs(stamp1 - stamp2))
print ppm



w2 = threading.Thread(name='counter', target=counter)
w4 = threading.Thread(name='runpost', target=runpost)


w2.start()
w4.start()
print "Started"

godlythomask
Posts: 3
Joined: Sat Nov 12, 2016 3:22 pm

Re: Interrupt to count pulses on gpio pin every x seconds

Fri Nov 18, 2016 8:41 pm

Continuation to this post, Can anyone tell any method to count the number of positive edge triggered pulses every say 20 microsecs . I dont think python time.sleep(20/1000000.0) will be reliable in that case.

richrarobi
Posts: 271
Joined: Sun Feb 08, 2015 1:13 pm

Re: Interrupt to count pulses on gpio pin every x seconds

Sat Nov 19, 2016 9:31 pm

It's a bit difficult to read your code because it isn't in a "code" block - notice that joan's post did this and it has all the indentation replicated.
However:- You are using threading. If you were to switch to multiprocessing, you would have each process running in its own process and able to run on a separate "core" (assuming you have a multi-core pi?) - You can have your counter process concentrating on that job, while other processes do other things (almost as though you have separate programs).
Multi-processsing is a little harder to setup (you need to use tools like HTOP - to ensure your processes are behaving as you want them to) but it is not a great deal different to threading.

A totally irrelevant example of multi-processing setup (initialises two waiting ports for zmq):

Code: Select all

.
.
def waiter(port):
    try:
        rp = Reply(port)
        while True:
            rp.wait()
#            print("looping")
    except KeyboardInterrupt:
        print ("{} ending".format(sys._getframe().f_code.co_name))
        return

if __name__ == "__main__":
# handle signal properly - found on stackoverflow
    signal.signal(signal.SIGTERM, lambda signum, stack_frame: sys.exit(1))
# ports for zmq reply
    ports=["5555", "5556"]
    jobs=[]
    try:
        for port in ports:
            j = Process(target=waiter, args=(port, ), daemon=True)
            jobs.append(j)
        for j in jobs:
#            print ("Starting {}".format(j))
            j.start()
            sleep(1)
        while True:
            sleep(60)
# Twiddle thumbs
#            print("looping")

    except KeyboardInterrupt:
        sleep(2)
        for j in jobs:
            print("{} is alive : {}".format(j, j.is_alive()))
            if (j.is_alive()):
                print ("Terminating {}".format(j))
                j.join()
                j.terminate()
(Also, if at all possible it would be better to use python3 - although they keep having to move the end of life for 2.7, (currently 2020) the documentation and many features are better with 3.4+++)

p.s. Although if you are using interrupts, you shouldn't need threading or multi-processing?
However much I look at it I can't see where your sleep statement fits. Can you explain?

Return to “Python”