There are several things going on in your code. I suspect that what's really causing the problem is that you need to exit the interrupt handler before another interrupt callback can be triggered...but there is also a confusing mix of callback-based handlers and the GPIO.event_detected method.
I think you can simplify things by performing less manipulation of your interrupt configuration. Just have a state variable that starts at 0, increment it to 1 on the first interrupt, so the next time the interrupt method is called you know it's the second interrupt. No need to try setting multiple handlers like that.
Keeping in mind that I don't actually know what you're trying to do...I imagine something like this:
import RPi.GPIO as GPIO
import time
state = 0
GPIO.setmode(GPIO.BCM)
GPIO.setup(26, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(19, GPIO.IN, pull_up_down=GPIO.PUD_UP)
def interrupt_handler(channel):
global state
print("interrupt handler")
if channel == 19:
if state == 1:
state = 0
print("state reset by event on pin 19")
elif channel == 26:
if state == 0:
state = 1
print("state set by event on pin 26")
GPIO.add_event_detect(26, GPIO.RISING,
callback=interrupt_handler,
bouncetime=200)
GPIO.add_event_detect(19, GPIO.RISING,
callback=interrupt_handler,
bouncetime=200)
while (True):
time.sleep(0)
Answer from larsks on Stack OverflowThere are several things going on in your code. I suspect that what's really causing the problem is that you need to exit the interrupt handler before another interrupt callback can be triggered...but there is also a confusing mix of callback-based handlers and the GPIO.event_detected method.
I think you can simplify things by performing less manipulation of your interrupt configuration. Just have a state variable that starts at 0, increment it to 1 on the first interrupt, so the next time the interrupt method is called you know it's the second interrupt. No need to try setting multiple handlers like that.
Keeping in mind that I don't actually know what you're trying to do...I imagine something like this:
import RPi.GPIO as GPIO
import time
state = 0
GPIO.setmode(GPIO.BCM)
GPIO.setup(26, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(19, GPIO.IN, pull_up_down=GPIO.PUD_UP)
def interrupt_handler(channel):
global state
print("interrupt handler")
if channel == 19:
if state == 1:
state = 0
print("state reset by event on pin 19")
elif channel == 26:
if state == 0:
state = 1
print("state set by event on pin 26")
GPIO.add_event_detect(26, GPIO.RISING,
callback=interrupt_handler,
bouncetime=200)
GPIO.add_event_detect(19, GPIO.RISING,
callback=interrupt_handler,
bouncetime=200)
while (True):
time.sleep(0)
That sleep(0) just causes the process to idle there while waiting for switch interrupts. Since nothing in there programmatically ends the process, doing a Ctl-C will stop it.
gpio - How do I implement an interrupt service routine on Raspberry Pi? - Raspberry Pi Stack Exchange
Need Interrupt Help
Jetson.GPIO interrupt processing on nano
How to handle multiple simultaneous interrupts in Python?
Videos
There is no way to call userspace code from an ISR. Unlike system calls which run on the stack of the userspace program, interrupt handlers use internal kernel memory for the stack. Since that memory is not visible in userspace, the system would crash the moment your ISR userspace function finishes or tries to use the stack for local variables (if not before, due to other reasons I have overlooked).
If you need to play with interrupts, you need to write a kernel driver.
wiringPi uses interrupts, e.g. with the wiringPiISR function.
pigpio uses interrupts, e.g. with the gpioSetISRFunc function.
lgpio uses interrupts. e.g. with the gGpioSetAlertsFunc function.
None of the above use polling or busy waits. I can only assume you are confused because at a low level they use a Linux function called poll. But this function does not poll the GPIO in the sense you mean.
Linux handles interrupts. As part of its interrupt handling it will eventually schedule one of the above functions.
pigpio can additionally use GPIO polling via DMA which happens to be more accurate and reliable for short (few µs) level changes.
Hello, so this question is about both the Raspberry Pi and Python. I'm building a monitoring circuit that needs to monitor multiple sensors at once, and report the data back over MQTT. The main problem I'm having is that the RPi.GPIO interrupts only support one thread at a time to run the callback function triggered by interrupts, and the callback functions can only be executed sequentially, not simultaneously. This won't work because I have multiple sensors that I need to count the rising edges for and calculate the amount of times they happen over a given time period.
I've tried using multiprocessing and multithreading a couple of different ways, but it's not quite working how I need it to. Here's the basic idea for the code:
# Global Variables
THREAD_EXECUTE = True # Used to tell the threads when to stop running
SENSOR_1_TRIGGERS = 0 # Used to track number of rising edge triggers
SENSOR_2_TRIGGERS = 0 # Used to track number of rising edge triggers
def callback_1(input_pin):
global THREAD_EXECUTE
global SENSOR_1_TRIGGERS
while THREAD_EXECUTE:
GPIO.wait_for_edge(input_pin, GPIO.RISING, bouncetime=100)
SENSOR_1_TRIGGERS += 1
def callback_2(input_pin):
global THREAD_EXECUTE
global SENSOR_2_TRIGGERS
while THREAD_EXECUTE:
GPIO.wait_for_edge(input_pin, GPIO.RISING, bouncetime=100)
SENSOR_2_TRIGGERS += 1
def main():
global THREAD_EXECUTE
try:
sensor_1_thread = Thread(target=callback_1, args=(pin_1,))
sensor_1_thread.start()
sensor_2_thread = Thread(target=callback_2, args=(pin_2,))
sensor_2_thread.start()
except KeyboardInterrupt:
THREAD_EXECUTE = False
finally:
sensor_1_thread.join()
sensor_2_thread.join()
GPIO.cleanup()
exit()Basically I just need a way to monitor multiple interrupts simultaneously, and handle the calculations in their own threads. The above code kind of works, but it's very slow and still doesn't really handle each sensor input independently. What's the best way to do this on the RPi with Python?
Edit for clarity: This project needs to monitor wind speed, wind direction, rainfall, temp, humidity, barometric pressure, battery voltage, and solar panel voltage. Also it needs to control a relay that powers an exhaust fan. The wind speed sensor and rainfall sensor are the two main sensors that really need fast interrupt responses. Everything else can be run on a polling schedule.