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 Overflow
Top answer
1 of 2
2

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)
2 of 2
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.

🌐
The Robotics Back-End
roboticsbackend.com › home › raspberry pi gpio interrupts tutorial
Raspberry Pi GPIO Interrupts Tutorial - The Robotics Back-End
December 30, 2021 - Here are 3 more code example to show you different ways to use GPIO interrupts on your Raspberry Pi. First, let’s add a LED to our circuit. Connect the shorter leg to the ground, and in between add a resistor (330 Ohm here). Then connect the longer leg of the LED to GPIO 20. Goal: power on the LED when the button is pressed, power off the LED when the button is released (you might have to tweak the bouncetime if you press the button very fast). #!/usr/bin/env python3 import signal import sys import RPi.GPIO as GPIO BUTTON_GPIO = 16 LED_GPIO = 20 def signal_handler(sig, frame): GPIO.cleanup()
Discussions

python - Problems with GPIO Edge Interrupts - Raspberry Pi Stack Exchange
I have the following circuit hooked up with a big button. Note: I am actually using a Pi Zero, not a Pi 2. I took some code from this example to run the following python script: #!/usr/bin/env pyt... More on raspberrypi.stackexchange.com
🌐 raspberrypi.stackexchange.com
May 4, 2016
python - RPi.GPIO interrupt - Raspberry Pi Stack Exchange
I don't use the Python libraries for programming my Pis, but in the other languages I do use, no, you cannot. You should however be able to set up some global variables and access them from within your ISR though... ... I am not sure about RPi.GPIO but Joan's pigpio library also offers callbacks so I will try to explain how this could be achieved with pigpio as an example ... More on raspberrypi.stackexchange.com
🌐 raspberrypi.stackexchange.com
July 22, 2017
python - Fastest Hardware Interrupt software? - Raspberry Pi Stack Exchange
I'm wiring my Raspberry pi to a USdigital encoder , especifically this model "H6BM-1000-500-IE-S-H" , it has 1000 signals per revolution , I've followed the tutorial on http://raspi.tv/2013/how-... More on raspberrypi.stackexchange.com
🌐 raspberrypi.stackexchange.com
April 22, 2016
gpio - How do I implement an interrupt service routine on Raspberry Pi? - Raspberry Pi Stack Exchange
There are several libraries like WiringPi, RPi and pigpio, claiming to implement interrupt handling for GPIO signals. But as far as I can estimate, they all do polling on the pins, therefore implem... More on raspberrypi.stackexchange.com
🌐 raspberrypi.stackexchange.com
January 11, 2021
🌐
RasPi.TV
raspi.tv › 2013 › how-to-use-interrupts-with-python-on-the-raspberry-pi-and-rpi-gpio-part-3
How to use interrupts with Python on the Raspberry Pi and RPi.GPIO – part 3
June 22, 2015 - Multiple threaded callback interrupts in Python We’ve been learning about interrupts this week because of the brand new interrupt capabilities of RPi.GPIO. We covered a simple “wait for…
🌐
Raspberry Pi
projects-raspberry.com › how-to-use-interrupts-with-python-on-the-raspberry-pi-and-rpi-gpio
How to use interrupts with Python on Raspberry Pi and RPi.GPIO
September 2, 2025 - This tutorial explains how to use interrupts with Python on the Raspberry Pi using the RPi.GPIO library. It covers configuring GPIO pins, setting up event detection, and writing callback functions to respond to input changes immediately.
🌐
Raspberry Pi Forums
forums.raspberrypi.com › board index › programming › python
how do interrupts work on rpi4 - Raspberry Pi Forums
March 14, 2023 - Linux does handle hardware interrupts, whether they are GPIO level changes or a timer etc. It does not poll for changes. Linux then notifies any software which has registered an interest in that interrupt. That might e.g. be a Python script or a C program etc. If the program is not running it will have to be scheduled to run. If the program is running the relevant thread within the program will have to be triggered. That is what introduces the latency. pigpio adds another method, it uses DMA to provide regular snapshots of the GPIO.
🌐
Quorten Blog 1
quorten.github.io › quorten-blog1 › blog › 2020 › 09 › 12 › rpi-gpio-int-uspace
A more elegant way to get Raspberry Pi GPIO interrupts in user-space | Quorten Blog 1
September 12, 2020 - 20200902/DuckDuckGo raspberry pi gpio interrupt 20200902/http://wiringpi.com/reference/priority-interrupts-and-threads/
🌐
Medium
medium.com › @rxseger › interrupt-driven-i-o-on-raspberry-pi-3-with-leds-and-pushbuttons-rising-falling-edge-detection-36c14e640fef
Interrupt-driven I/O on Raspberry Pi 3 with LEDs and pushbuttons: rising/falling edge-detection using RPi.GPIO | by R. X. Seger | Medium
August 22, 2016 - Sounds complicated, fortunately the RPi.GPIO Python module included in Raspbian supports interrupts nearly as easily as polling. Raspberrywebserver.com’s Using Interrupt Driven GPIO is a good introduction.
Find elsewhere
🌐
AB Electronics UK
abelectronics.co.uk › home › help and support › knowledge base › io pi plus tutorials › io pi plus tutorial 4 - more interrupts
IO Pi Tutorial 4 - More Interrupts IO Pi Interrupts
July 30, 2024 - The IO Pi Plus is supplied with Bus 1 on I2C address 0x20 and Bus 2 on 0x21; if you have changed the I2C addresses, you must update the code below to use the new I2C addresses. The AB Electronics Python library uses another library called python3-smbus; you can install it using apt-get with the following commands. sudo apt-get update sudo apt-get install python3-smbus · The RPi.GPIO library is needed to configure and listen for events on the Raspberry Pi’s GPIO header.
🌐
Raspberrypi-aa
raspberrypi-aa.github.io › session2 › input.html
Polled and Interrupt Driven Input - Introduction to Raspberry Pi
For a desired pin, the state of the input pin is checked for the input value. If the input value changes, the program can change its behavior. The simplest example of polled input is: GPIO.setup(pin15, GPIO.IN) while GPIO.input(pin15) == 1: time.sleep(.01) print "Pin 15 set low"
🌐
pytz
pythonhosted.org › RPIO › rpio_py.html
RPIO, the Python module - GPIO & TCP Interrupts
If debounce_timeout_ms is set, interrupt callbacks will not be started until the specified milliseconds have passed since the last interrupt. Adjust this to your needs (typically between 10ms and 100ms). The callback receives two arguments: the gpio number and the value (an integer, either 0 (Low) or 1 (High)).
🌐
SourceForge
sourceforge.net › home › browse › raspberry-gpio-python › wiki
raspberry-gpio-python / Wiki / Inputs
To debounce using software, add the bouncetime= parameter to a function where you specify a callback function. Bouncetime should be specified in milliseconds. For example: # add rising edge detection on a channel, ignoring further edges for 200ms for switch bounce handling GPIO.add_event_detect(channel, GPIO.RISING, callback=my_callback, bouncetime=200)
🌐
Intellamech
intellamech.com › RaspberryPi-projects › rpi_gpio.html
Basic GPIO on the Raspberry Pi - Intellamech
## python import smbus import os import RPi.GPIO as GPIO import time import random import boto3 # Pins LED_FLASH_LOW = 40 LED_GREEN = 38 LED_YELLOW = 37 LED_RED = 35 LED_FLASH_HIGH = 36 BUTTON = 33 LDR = 31 # Release RTC 3231 os.system('sudo rmmod rtc_ds1307') # Setup RTC 3231 for temperature reading bus = smbus.SMBus(1) address = 0x68 # Force a conversion and wait until it completes def convTemp(address): byte_control = bus.read_byte_data(address,0x0E) if byte_control & 32 == 0: bus.write_byte_data(address, 0x0E, byte_control|32) byte_control = bus.read_byte_data(address,0x0E) while byte_cont
🌐
Raspberry Pi Forums
forums.raspberrypi.com › board index › programming › bare metal, assembly language
Pi 4 bare metal GPIO interrupt example? - Raspberry Pi Forums
We've tested generating hundreds of thousands of interrupts per second on a Pi 4 using Ultibo but never millions of interrupts per second. Ultibo.org | Make something amazing https://ultibo.org Threads, multi-core, OpenGL, Camera, FAT, NTFS, TCP/IP, USB and more in 3MB with 2 second boot! ... This might be useful? It's tested on the RPi4, and I just published it tonight: https://github.com/isometimes/rpi4-osde ... interrupts This just hooks the system timer, but I'm sure it could be easily adapted for GPIO interrupts...
🌐
GitHub
gist.github.com › 37d598d6501214da58e0
gpio-interrupt - C routine for handling interrupts generated on GPIO · GitHub
September 1, 2022 - gpio-interrupt - C routine for handling interrupts generated on GPIO - gpio-interrupt.c
Top answer
1 of 2
3

Python may not be the best choice if you have high or sustained data rates. You would be much better off using C.

Try the following Python. It should capture all the interrupts although if you have sustained high interrupt rates it may take time for them all to be processed.

#!/usr/bin/env python

import time

import pigpio # http://abyz.me.uk/rpi/pigpio/python.html

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

cb = pi.callback(21)

while True:
   print(cb.tally())
   cb.reset_tally()
   time.sleep(1)
2 of 2
1

You can handle high speed interrupts on the R'Pi using Python easily if you make some configuration changes:

  1. Constrain operation to cpu 0,1,2 for the 'Pi
  2. Never do prints in the interrupt routines
  3. Set syscheckinterval to a large value to reduce overhead
  4. When you start your Python app, remap to cpu 3 and set the priority to realtime (-20)

This will allow you to get quite good response out to 5+kHz interrupt rates with no delays.

Here's some sample code:

#! /usr/bin/python2

##Interupt driven x1, x2 up/down encoder counter
##Jack Creasey

from RPi import GPIO
import os
import sys

##*********************************
#Define pin usage for encoder
#**********************************
phase_a = 21   
phase_a_dash= 16
phase_b = 20

##*********************************
#Define pin usage for PWM 
#**********************************
pwm_out = 12                #connect pin 12 to pin 24 to create a pwm timer interrupt
pwm_in = 24

#**********************************
#Setup GPIO
#**********************************

GPIO.setwarnings(False)
GPIO.cleanup()
GPIO.setmode(GPIO.BCM)
GPIO.setup(phase_a, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(phase_a_dash, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(phase_b, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(pwm_in, GPIO.IN, pull_up_down=GPIO.PUD_UP)

GPIO.setup(pwm_out, GPIO.OUT)  # Set GPIO pin 12 to output mode.
pwm = GPIO.PWM(pwm_out, 200)   # Initialize PWM pin and frequency
pwm.start(5)                   # Start PWM with 5% duty cycle


#**********************************
#Global variables
#**********************************
global counter
global lastcounter
global pwmticks
global lastpwmticks



def setup():

    #Find out our pid so we can remap to cpu 3
    mypid=os.getpid()
    myppid=os.getppid()

    print("My pid is "), mypid

    print('Setting cpu affinity to cpu 3')
    select_cpu="sudo taskset  -cp 3 "
    print('Setting priority to -20')
    set_priority="sudo renice -n -20 -p "

    #Call out to the os to remap the cpu and set priority high
    ret=os.system(set_priority+str(mypid))
    ret=os.system(select_cpu+str(mypid))

    sys.setcheckinterval(1000); ##no Python threading so just let Python run for a long time




def my_callback(channel):       #x1 sensing

    global counter

    if GPIO.input(phase_b):
            counter += 1
    else:
            counter -= 1

def my_callback1(channel):      #x2 sensing

    global counter

    if GPIO.input(phase_b):
            counter -= 1
    else:
            counter += 1

def my_callback2(channel):      #PWM interrupt 

    global pwmticks

    pwmticks += 1


setup()
counter = 0
lastcounter=counter

pwmticks=0
lastpwmticks=pwmticks

GPIO.add_event_detect(phase_a, GPIO.FALLING  , callback=my_callback)        #x1
GPIO.add_event_detect(phase_a_dash, GPIO.RISING  , callback=my_callback1)   #x2
GPIO.add_event_detect(pwm_in, GPIO.RISING  , callback=my_callback2)



try:

    while True:                             #busy work for Python main loop to do
        if counter != lastcounter:
            lastcounter=counter
            sys.stdout.write("\r" + str(counter) + "   \r")
            sys.stdout.flush()

        if pwmticks >= (lastpwmticks + 1000):
            lastpwmticks=pwmticks
            sys.stdout.write("\n Ticks= " + str(lastpwmticks) + "   \n")
            sys.stdout.flush()

except KeyboardInterrupt:
      print("Ctl C pressed - ending program") 
🌐
Adafruit
blog.adafruit.com › 2013 › 03 › 22 › how-to-use-interrupts-with-python-on-the-raspberry-pi-and-rpi-gpio
How to use interrupts with Python on the Raspberry Pi and RPi.GPIO
March 22, 2013 - How to use interrupts with Python on the Raspberry Pi and RPi.GPIO This is the first in a series of articles which aim to show you how to use this new interrupt facility in Python. Interrupts are a…