RPi.GPIO is a popular Python module for accessing hardware GPIO pins on devices like Raspberry Pi. Unfortunately it has a threading bug that causes Python-side event callbacks executed in parallel in completely unexpected way.
Last week I worked on an app that was supposed to measure time difference between two electrical signals received by two GPIO pins. The code is based on the event-based handling of signals by using the function
GPIO.add_event_detect. The callbacks access some global variables and log messages into the standard output by using the standard
I connected switches to GPIO pins for testing and used them to test that everything works. I set 500ms software debounce time for the callbacks. However, while pressing the switches I saw weird anomalies in the logged messages. I then added messages at the start and at the end of the callbacks and it was a great surprise seeing that start/end messages were interleaved.
A part of the documentation says:
the callback functions are run sequentially, not concurrently. This is because there is only one thread used for callbacks, in which every callback is run, in the order in which they have been defined
It comes out that the issue is already reported. The offending block of code starts here. This is executed indirectly by
GPIO.add_event_detect and if you call the function multiple times "quick enough" then the
thread_running flag might not get set by the firstly started thread and multiple handler threads will be created.
I was able to work around the issue by adding a small delay between
GPIO.add_event_detect calls. This helps to ensure that the firstly created thread has set the flag in the condition.
GPIO.add_event_detect(channel1, GPIO.FALLING, callback=gpioCallback, bouncetime=500) time.sleep(1) GPIO.add_event_detect(channel2, GPIO.FALLING, callback=gpioCallback, bouncetime=500)
I rarely work with threads and prefer async IO. I wrote a MSc thesis on static thread analysis for C language and haven't used them since, unless there is no other choice. Threading is really hard. I hope that this post helps to solve some of the Raspberry GPIO anomalies you might have.