0

I use the gpiozero.MotionSensor to detect motion and upon motion to change the state of GPIO pin 17 using RPi.GPIO.

This works well.

At the end of the script I clean up using RPi.GPIO.cleanup(), but then receive an error from gpiozero (see below) when it wants to shut down MotionSensor at the end of the script.

Can I avoid this error? Or can I omit the RPi.GPIO.clean() since it is called from gpiozero?

Error in atexit._run_exitfuncs:
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/gpiozero/devices.py", line 595, in _shutdown
    _devices_shutdown()
  File "/usr/lib/python3/dist-packages/gpiozero/devices.py", line 588, in _devices_shutdown
    dev.close()
  File "/usr/lib/python3/dist-packages/gpiozero/input_devices.py", line 299, in close
    super(SmoothedInputDevice, self).close()
  File "/usr/lib/python3/dist-packages/gpiozero/devices.py", line 540, in close
    self._pin.close()
  File "/usr/lib/python3/dist-packages/gpiozero/pins/rpigpio.py", line 137, in close
    GPIO.cleanup(self.number)
RuntimeError: Please set pin numbering mode using GPIO.setmode(GPIO.BOARD) or GPIO.setmode(GPIO.BCM)
Exception ignored in: <function GPIOBase.__del__ at 0xb618fbb8>
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/gpiozero/devices.py", line 151, in __del__
  File "/usr/lib/python3/dist-packages/gpiozero/input_devices.py", line 299, in close
  File "/usr/lib/python3/dist-packages/gpiozero/devices.py", line 540, in close
  File "/usr/lib/python3/dist-packages/gpiozero/pins/rpigpio.py", line 137, in close
RuntimeError: Please set pin numbering mode using GPIO.setmode(GPIO.BOARD) or GPIO.setmode(GPIO.BCM)
  • GPIOZero is a superset of RPi.GPIO. It uses the RPi.GPIO library. So you probably need to read the code for GPIOZero to see how it does the termination cleanup. Or ask the author at github.com/gpiozero/gpiozero/issues – Dougie Oct 26 at 15:05
1

It's not recommended to mix the two libraries, and gpiozero does an implicit cleanup anyway. Alternatively you can do a manual cleanup with pir.close().

From the docs:

Pin state cleanup is explicit in RPi.GPIO, and is done manually with GPIO.cleanup() but in GPIO Zero, cleanup is automatically performed on every pin used, at the end of the script. Manual cleanup is possible by use of the close() method on the device.

If your script terminates naturally, you don't need to do anything to clean up:

from gpiozero import MotionSensor

pir = MotionSensor(4)

print(pir.value)

If you have a while loop and you kill it with ctrl + c, the script will terminate without cleanup:

from gpiozero import MotionSensor
from time import sleep

pir = MotionSensor(4)

while True:
    print(pir.value)
    sleep(1)

To get around that you could catch KeyboardInterrupt and break out of the while loop:

from gpiozero import MotionSensor
from time import sleep

pir = MotionSensor(4)

while True:
    try:
        print(pir.value)
        sleep(1)
    except KeyboardInterrupt:
        break

That way it'll get cleaned up automatically.

(you could use pir.close() here instead of break but it won't make any difference because it gets cleaned up at the end anyway).

| improve this answer | |
  • Thanks for the answer - I removed RPi.GPIO and use gpiozero.LED to change the state of pin 17. Now the script exits cleanly. – Kurt Oct 26 at 18:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.