Execute a function every minute while not blocing hardware interrupts?

Viewed 26

I'm making an energy meter using a Raspberry Pi, which gets its reading from a flashing LED (1000 flashes/kWh). It counts the flashes for 60 seconds through an interrupt and then it sends the data to a database. This works great, none of the flashes are missed this way, but because it just constantly checks if 60 seconds have passed it pegs the given thread to a 100% which is less than optimal for a 24/365 usecase.

Here is the important part of the code:

sampleFreqency = 60 #seconds
flashCount = 0
time1 = time.time()

import RPi.GPIO as GPIO  
GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_UP)  

def flashCounter(self):
    global flashCount
    if not GPIO.input(17):
        print("Light!")
        flashCount = flashCount + 1

GPIO.add_event_detect(17, GPIO.BOTH, callback=flashCounter, bouncetime=50)

while True:
    if time.time() > time1+sampleFreqency:
        energy = flashCount #Wh
        power = energy * 0.36/(sampleFreqency/10) # kW
        print("Power: " + str(power) + "kW, Energy: " + str(energy) + "Wh")
        logData(power, energy)
        flashCount = 0
        time1 = time.time()

I have tried using the threading Timer module without success, as it blocks everything else until it runs.

1 Answers

Turns out interrupts in fact do trigget while the program is doing time.sleep() , only my code was not functioning as I would have wanted it to. I have rewritten the ISR like this:

def flashCounter(self):
    global flashCount
    print("Light!")
    flashCount = flashCount + 1

GPIO.add_event_detect(17, GPIO.FALLING, callback=flashCounter, bouncetime=50)

Now it works flawlessly. The issue was that for sensing the blinking I'm using a photoresistor which has a slow reaction time, and when the interrupt triggered on the falling edge, the voltage probably has not had fallen to a level which would read as low, so the if statement did not get fulfilled.

Related