I'm using Python on Raspbian (a type of linux) on the Raspberry Pi (an embedded processor board) to monitor GPIO inputs.
See simplified version of my code below. I have an infinite loop in the python script waiting for something to happen on a GPIO i/p. Is this the correct way to do it? I.e. does this mean that the CPU is running at full whack just going round this loop, leaving no CPU cycles for other stuff? Especially as I need to be running other things in parallel (e.g. the browser).
Also what happens if the CPU is busy doing something else and a GPIO i/p changes? Does the GPIO event get stored somewhere so it is eventually serviced, or does it just get lost?
Is there a better way of doing this?
(For your answers, please note that I'm new to linux, and v. new to python and real-time programming)
#!/usr/bin/python
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)
GPIO.setup(16, GPIO.IN, pull_up_down=GPIO.PUD_UP)
def ButtonHandler(channel):
print "Button pressed " + str(channel)
# do stuff here
GPIO.add_event_detect(16, GPIO.FALLING, callback=ButtonHandler, bouncetime=200)
while True:
pass
Yes, doing while True: pass
will burn 100% of your CPU (or as close to it as possible) doing nothing.
From what I understand (hopefully this is documented somewhere), the RPi.GPIO module spawns a background thread that waits on the GPIO and calls your callback
function for each event. So your main thread really has nothing to do. If you want this to run as a service, make it sleep
for long periods of time. If you want to run it interactively (in which case you probably want it easier to cancel), sleep
for shorter periods of time, maybe 0.5 seconds, and add some way to exit the loop.
It would be even nicer if you could do the GPIO select
in the main thread, or get a handle to the GPIO background thread that you can just join
, either of which would burn no CPU at all. However, the module doesn't seem to be designed in a way to make that easy.
However, looking at the source, there is a wait_for_edge
method. Presumably you could loop around GPIO.wait_for_edge
instead of setting a callback. But without the documentation, and without a device to test for myself, I'm not sure I'd want to recommend this to a novice.
Meanwhile:
Also what happens if the CPU is busy doing something else and a GPIO i/p changes? Does the GPIO event get stored somewhere so it is eventually serviced, or does it just get lost?
Well, while your thread isn't doing anything, the GPIO background thread seems to be waiting on select
, and select
won't let it miss events. (Based on the name, that wait_for_edge
function sounds like it might be edge-triggered rather than level-triggered, however, which is part of the reason I'm wary of recommending it.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With