0

My python script waits for motion (with gpiozero MotionSensor wait_for_motion()) most of the time. But it also needs to react to SIGUSR1. The problem is: when SIGUSR1 is received wait_for_motion() is triggered. I have tried to put together a test case with the relevant parts of my script:

from gpiozero import MotionSensor, DigitalOutputDevice
import signal

mwms = MotionSensor(4, pull_up=True)
foco1 = DigitalOutputDevice(17, initial_value=False)
foco2 = DigitalOutputDevice(18, initial_value=False)

def foto():
  foco1.on()
  foco2.on()
  print("foto")
  foco1.off()
  foco2.off()

def signal_1(signalNumber, frame):
  foto()
  return

if __name__ == '__main__':
  signal.signal(signal.SIGUSR1, signal_1)

while True:
  try:
    mwms.wait_for_motion()
    print("Motion detected", flush=True)
    mwms.wait_for_no_motion()
    print("No motion", flush=True)

  except KeyboardInterrupt:
    print('\nKeyBInt')
    break
  except:
    print('\nError')
    break

When SIGUSR1 is received the function foto() is executed correctly but mwms.wait_for_motion() ends and "Motion detected" and "No motion" are printed.

Edit: As per @Milliways answer. Regarding the slow code: I do not use print, that is only for the test case, I use raspistill, so it would be even slower :-) I will try to figure out how to shorten the interrupt routine... Regarding the button: it is a web server that sends the signal, I do not know how to better communicate to the python script that it should execute the "foto" function. I had two separate python scripts before, one for the motion-sensor and the other as the web server cgi, but it looks like a bad idea to have two independent scripts dealing with GPIO, is not it?

4

1 Answer 1

0

This is to be expected - signal operates on the main thread.

wait_for_motion() - or ANY wait_for is poor practice as it blocks the main thread.

You would be better to use .when_motion or a callback https://gpiozero.readthedocs.io/en/stable/recipes.html#motion-sensor

You would be better to use the Button class and a button.when_pressed callback rather than signal to call foto and DO NOT include slow code e.g. print in interrupt routines.

2
  • Thank you for your answer. Yes, I know signal operates on the main thread. I have only the main thread do not I? I will try pause() instead of wait_for_motion, but I am afraid signal also ends the pause. Commented May 2, 2022 at 17:28
  • I edited the first post to better clarify the environment. Thanks again. Commented May 2, 2022 at 21:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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