RPi_Cam_Web_Interface icon indicating copy to clipboard operation
RPi_Cam_Web_Interface copied to clipboard

How to use a PIR sensor for motion detection instead of basic motion features (external/internal)

Open pdemeure opened this issue 2 years ago • 43 comments

Hello, I want to use RCWI for birds survey in my garden. In the scene are some trees with leaves, and when there is some wind that makes leaves moving, Motion detection starts and creates videos. I'd like to use a PIR sensor in orer to detect motion only for living subjects like birds. A PIR sensor is cheap and connects on the GPIO, but how to use it in RPI_Cam_Web_Interface instead of the standard motion detection methods ? Thanks in advance if you can help me on that project. Pierre

pdemeure avatar May 10 '22 08:05 pdemeure

There are two aspects here; sensing events from the PIR, and triggering activity in RCWI.

RCWI can be fully controlled by sending commands into its control pipe (FIFO) at /var/www/html/FIFO This is documented in the wiki and you can try things out by just using the echo command.

E.g. echo 'ca 1 10' > /var/www/html/FIFO

will capture a 10 second video

So if you have a program that detects motion events from the PIR then that event can send in commands to the FIFO to do whatever you want.

Probably the easiest is to use a python program to detect when the GPIO the PIR is connected to activates and then the program can send commands to the FIFO.

In python something like this should send that command

fifo = open("/var/www/html/FIFO", "a") fifo.write("ca 1 10") fifo.close()

There is also a slightly more sophisticated method which is to use the FIFO1 control pipe, This is monitored by the scheduler to detect motion events and then do whatever the scheduler has been configured to do. Writing a '1' to FIFO1 signals a motion start event. Writing a '0' signals a motion stop event. The advantage of doing it this way is that the commands that get sent to the camera are easily changed in the scheduler web interface rather tan being coded directly in your python program. You probably want to get the first method going first before trying this.

roberttidey avatar May 10 '22 10:05 roberttidey

Thanks for these infos. The echo command works perfectly well on my Raspberry config. I should receive tomorrow my PIR sensor and I'll connect it o the GPIO pins. What I need to know is if I have to configure it in Raspbian or if the sole connection o GPIO is enough to use it. If it is active, how can I set up RCWI in order that motion detection could use it ? Do I have to create and run a python script each time I power on the Raspberry or is RCWI able to use the motion detection with PIR only with its own motion detection settings ? When I'll have the PIR used for motion detection, my project will be ready for full use !

pdemeure avatar May 11 '22 12:05 pdemeure

Attaching a PIR to a GPIO will do nothing without a program or script to detect its signal and do something with it.

The program or script can be in any language that you like. I suggested python as that is probably the easiest to use for this. It should only be a few lines long. There are lots of examples of this on the web you can start from. If you don't have much experience with this then start from one of the examples that just prints out text messages when motion is detected so you can see how to do that and then add in the bit of python I suggested to send the command into the FIFO.

The RCWI allows use of external motion either by accepting commands as described or by sending in external motion start/stop signals into FIFO1 as described in the second part of my reply.

Note that if you have a python program to handle the PIR and trigger the camera activity then you can easily arrange for it to start automatically every time the raspberry boots so that you would not need to do that manually. Again there is lots of information on how to do this. One method is just add a command to the /etc/rc.local file which already has the commands to start up the RCWI software.

roberttidey avatar May 11 '22 20:05 roberttidey

Hi Robert, Yes I have python scripts that use PIR for test and display messages like "motion detected". But how to use the PIR or the script in order to get the info in FIFO, FIFO1 or FIFO0 ? Which settings to check in camera or motion detection or schedule in order that RCWI use the PIR instead of detection of changes in landscape ? I should get my PIR today and I'll try all that

pdemeure avatar May 12 '22 09:05 pdemeure

You don't really need to change anything in the RCWI set up as it listens to and obeys any instructions coming into FIFO or FIFO1 all the time. You do not need to activate motion detection. That is for the built in video motion detection.

Instead of the instruction to print "motion detected" in the script you need to replace that with the lines of python I showed to send a command into one of the FIFOs.

The RCWI include actions for both motion started and motion finished which is intended for motion detection like the built in video method which waits until the scene is still before signalling a motion stop. The PIR fires when it sees motion and its signal stays on for a fixed period of time before resetting to wait for the next motion. So it is probably easier to base the action on just the motion detected (start) and arrange that to capture a video of a fixed length whenever the PIR fires. The capture command (ca) allows for this by having a second optional parameter for the number of seconds of a fixed length recording. So "ca 1 10" will start a video recording and it will automatically terminate after 10 seconds.

Method 1 - Direct command Python Include following in the script when motion detected

fifo = open("/var/www/html/FIFO", "a") fifo.write("ca 1 10") fifo.close()

Method 2 - Via scheduler set up In scheduler set up put ca 1 10 in the motion start field; save settings. You don't need anything in motion stop field Include following in the script when motion detected. Doing it this way allows you to change the command and the length of the video from the web interface and leave the script alone.

fifo = open("/var/www/html/FIFO1", "a") fifo.write("1") fifo.close()

If you want to test method 2 manually then you can just use the echo command echo '1' > /var/www/html/FIFO1

which will simulate a motion start event.

Integration of the script Test the script manually first just by running it. When it is OK then you can start it automatically when the raspberry starts up. It is very important you put an & at the end of the line as this means the scripts runs in the background and allows other things to continue. If you leave it out the boot sequence will stall. There are many methods to start a script automatically. See https://www.dexterindustries.com/howto/run-a-program-on-your-raspberry-pi-at-startup/

Maybe use the /etc/rc.local method as that is already there. You can just use a simple sudo python myPIRscript.py &

roberttidey avatar May 12 '22 11:05 roberttidey

Hi, I've received my PIR. I made test with a python script and that works fine. But I tried to include your lines for fifo , and the script returns an error : (the addition of the 3 lines with fifo are the only change from the original scrpt wich works...)

OSError : [Error 29] Illegal seek


Here is my python script :

import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) PIR_PIN = 14 # Assign GPIO14 pin 8 to PIR GPIO.setup(PIR_PIN, GPIO.IN) # Setup GPIO pin PIR as input print('Sensor initializing . . .') time.sleep(60) # Give sensor time to start-up, 60 seconds print('Active') def pir(pin): print('Motion Detected!')

GPIO.add_event_detect(14, GPIO.FALLING, callback=pir, bouncetime=100) print('[Press Ctrl + C to end program!]') fifo=open("/var/www/html/FIFO","a") fifo.write("ca 1 10") fifo.close
try: while True: time.sleep(0.001)

except KeyboardInterrupt: print('\nScript ended') finally: GPIO.cleanup()

Also I don't know where to place the 3 lines fifo in this script. I tried at several paces, but always the same error occurs.

pdemeure avatar May 12 '22 12:05 pdemeure

I also tried this other script 👍

import RPi.GPIO as GPIO import time

GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) PIR_PIN = 14 GPIO.setup(PIR_PIN, GPIO.IN)

print('Starting up the PIR Module (click on STOP to exit)') time.sleep(1) print ('Ready')

while True: if GPIO.input(PIR_PIN): print('Motion Detected') time.sleep(1)


More simple but works fine. Now I just have to include instruction for writing into FIFO !

pdemeure avatar May 12 '22 13:05 pdemeure

I think you might need to use fifo = open("/var/www/html/FIFO1", "w")

instead of fifo = open("/var/www/html/FIFO1", "a")

The "a" means it is trying to append whereas the "w" just means write

roberttidey avatar May 12 '22 14:05 roberttidey

hello, With "w" it works. However with the 3 lines fifo=open("/var/www/html/FIFO","a") fifo.write("ca 1 10") fifo.close RCWI continuously records videos.... 1 new video every 5 secods... How can I ask to record video only if an event occurs ? If no event on PIR is it necessary to use another set of 3 lines, but with a different "ca N NN" ? I hope to be very clse to the ideal behaviour !

pdemeure avatar May 12 '22 14:05 pdemeure

That is because you have the send command stuff inside a loop while the PIR signal is active.

You need to arrange it so it only sends once when the PIR signal goes active and then waits until the PIR signal becomes inactive before then starting again. So you will need a loop waiting it to go inactive inside the loop.

roberttidey avatar May 12 '22 15:05 roberttidey

Something like this for the text version which should only print the message once per motion trigger `import RPi.GPIO as GPIO import time

GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) PIR_PIN = 14 GPIO.setup(PIR_PIN, GPIO.IN)

print('Starting up the PIR Module (click on STOP to exit)') time.sleep(1) print ('Ready')

while True: if GPIO.input(PIR_PIN): print('Motion Detected') time.sleep(1) while GPIO.input(PIR_PIN): pass `

roberttidey avatar May 12 '22 15:05 roberttidey

Here is my script. Could you help me to arrange it in order that it works like you say ? Many thanks

import RPi.GPIO as GPIO import time

GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) PIR_PIN = 14 GPIO.setup(PIR_PIN, GPIO.IN)

print('Starting up the PIR Module (click on STOP to exit)') time.sleep(1) print ('Ready') try: while True: if GPIO.input(PIR_PIN): print('Motion Detected') fifo = open("/var/www/html/FIFO1", "w") fifo.write("ca 1 10") fifo.close time.sleep(1)

except KeyboardInterrupt: print('\nScript ended') finally: GPIO.cleanup()

pdemeure avatar May 12 '22 15:05 pdemeure

Have you tried the version with the inner loop waiting for the PIR to go low?

roberttidey avatar May 12 '22 15:05 roberttidey

I tried your last script (ht one which ends with "pass"). But it returns errors and nothing works. <i don't see in it th fifo instructions. Perhaps the script was not enterely displayed in your comment...

pdemeure avatar May 12 '22 15:05 pdemeure

You need to get indenting right in python. If this gives errors then tell me what they are

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
PIR_PIN = 14
GPIO.setup(PIR_PIN, GPIO.IN)

print('Starting up the PIR Module (click on STOP to exit)')
time.sleep(1)
print ('Ready')

try: 
  while True:
    if GPIO.input(PIR_PIN):
      print('Motion Detected')
      time.sleep(1)
      while GPIO.input(PIR_PIN):
        pass
except KeyboardInterrupt:
  print('\nScript ended')
finally:
  GPIO.cleanup()

roberttidey avatar May 12 '22 16:05 roberttidey

I made the script just printing out the text. Once that works then replace the print with the lines to send the fifo commannd

roberttidey avatar May 12 '22 16:05 roberttidey

Here is a version with the fifo in. I removed all text printing which you don't want in a program running in the background and moved the delays around a bit. Note you send direct commands like ca 1 10 to FIFO. If you want to use the FIFO1 scheduler version then you need to send 1 not ca 1 10 as the scheduler determines what command to use.

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
PIR_PIN = 14
GPIO.setup(PIR_PIN, GPIO.IN)

time.sleep(1)

try: 
  while True:
    if GPIO.input(PIR_PIN):
      fifo = open("/var/www/html/FIFO", "w")
      fifo.write("ca 1 10")
      fifo.close
      while GPIO.input(PIR_PIN):
        time.sleep(1)
    time.sleep(1)
except KeyboardInterrupt:
  pass
finally:
  GPIO.cleanup()		  ```

roberttidey avatar May 12 '22 16:05 roberttidey

Hi, Sorry... This last script doesn't work. RCWI don't record videos....

pdemeure avatar May 12 '22 17:05 pdemeure

I have just tried the script but had to simulate the PIR trigger and it recorded a video for me OK Try one with some print statements so you can see what is going on.

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
PIR_PIN = 14
GPIO.setup(PIR_PIN, GPIO.IN)

time.sleep(1)
print('Starting up the PIR Module (click on STOP to exit)')

try: 
  while True:
    if GPIO.input(PIR_PIN):
      print('Motion Trigger started')
      fifo = open("/var/www/html/FIFO", "w")
      fifo.write("ca 1 10")
      fifo.close
      while GPIO.input(PIR_PIN):
        time.sleep(1)
      print('Motion Trigger ended')
    time.sleep(1)
except KeyboardInterrupt:
  pass
finally:
  GPIO.cleanup()

roberttidey avatar May 12 '22 21:05 roberttidey

Hi Robert, That's very strange. The script displays correctly the statements, but recording videos is not correct ! The video is recorder when I stop the script ! When script is run, I see all the statements, (many ones), but no video are recorded. It's when I Stop the script that a video is recorded ! What would be good were to record videos when PIR detects a motion. And not when script stops. Also, it should record further videos if new motions are detected. Once again, many thanks for your support. I hope that this discussion will lead to a good solution and help also other guys...

pdemeure avatar May 13 '22 08:05 pdemeure

I missed the brackets off the close call which means the write was just buffered and not flushed out

use fifo.close()

The script should then work as intended and do a recording for each pir trigger

roberttidey avatar May 13 '22 12:05 roberttidey

That's better. Now the script records videos when the PIR is triggered. However now the recording doesn't stop. ven without anything living in front of PIR, RWCI records videos continuously. In the html page, the button "record video" changes itself from blue to orange, theb=n orange to blue, then lue to orange and so on.

pdemeure avatar May 13 '22 13:05 pdemeure

Here is the script from the distributor of the PIR. It is very close to yours, but the method for checking detection seems different. Perhaps is that dur to the behaviour of the PIR which have High and Low signal level... You can see that they dont use "GPIO.input(PIR_PIN)" but this one : GPIO.add_event_detect(14, GPIO.FALLING, callback=pir, bouncetime=100)

Here is the full script

Script_PIR

pdemeure avatar May 13 '22 14:05 pdemeure

The PIR sensors I have used in the past go active high when movement is detected, stay high for a time period and then go active low and wait for the next movement.

Can you include a link for your sensor?

From the suggested script it seems to go active low when movement is detected and uses the GPIO.FALLING event to signal motion detection.

What you can try is to use that script and put the 3 lines to send the command into the same place as where it says print(Motion Detected) with the same level of indent.

The other thing to be aware of is that some PIR sensors can false trigger if they are too close to sources of wifi and can then continuously trigger even without movement. If you get continuous Motion Detected messages without real motion then try to move the sensor away from the Raspberry.

roberttidey avatar May 13 '22 20:05 roberttidey

Hi, I attach the pdf which explains the behaviour and the use of my PIR. I tried both FALLING and RISING options but both makes continuoumy recording... I also tried to use if/else in order to check/see the value of GPIO.Input. All that works but always continuously ecord video ! I've seen in the document that there is a composnent of the PI which increases or decrease the sensibility. Perhaps do I'll try to act on it. Currently, I make my tests with the raspberry and PIR just near from me. Even if the PIR "looks" at the opposite of me, perhaps do it detects something.

HC-SR501 PIR Sensor_EN.pdf

pdemeure avatar May 14 '22 07:05 pdemeure

in addition to previous comment. Hereunder is the def pir I wrote for testing the behaviour of the PIR. I used BOTH instead of FALLING in order to handled each level. That works, but always continuous recording. Perhaps could it be necessary to define a waiting time or instruction to stay at LOW level before restarting motion detection ? Also, as long as there is no first motion detection , in the script running, nothing is displayes after the statement 'Acive'. But if there is a first motion detection, that works like if PIR alway keeps signal High...

def pir(pin): if GPIO.input(14): print('Rising edge detected on 14') print('Motion Detected!') fifo = open("/var/www/html/FIFO", "w") fifo.write("ca 1 10") fifo.close() print('ca 1 10 envoye a FIFO') else: print('Falling edge detected on 14') GPIO.add_event_detect(14, GPIO.BOTH, callback=pir, bouncetime=100)

NOTE : if you want to test and work on this PIR Sensor, let me know and I'll offer one to you !

pdemeure avatar May 14 '22 09:05 pdemeure

The HC-S501 PIR sensor is known to continuously trip if there is rf signals around such as wifi. Being near to the Pi can cause problems.

You can try shielding it with some grounded metal foil.

I used to try to use that sensor but it was always tricky near other electronics.

For PIR applications I now use sensors based on AM312 which are much better. Their electronics is in the same shielded case as the sensor itself and they are pretty immune to rf interference problems.

The AM312 and the HC-S501 are both active high on detecting motion so the original script should be fine.

roberttidey avatar May 14 '22 12:05 roberttidey

Good... Do you have a link for purchase ? (I prefer on amazon...) Also is the am312 able to detect small birds or is it mainly done for detection oh humans ?

pdemeure avatar May 14 '22 13:05 pdemeure

If you search for am312 pir sensor on Amazon or eBay you will find lots of sellers. I usually use eBay for things like this as they can be faster. Sometimes items like this on Amazon come from overseas suppliers and take a while to come.

I don't have any experience of using PIR sensors with small birds. PIR sensors all work by detecting changes in the thermal radiation pattern. As birds are much smaller then you probably need the sensor to be reasonably close to the target. The AM312 would be helpful here as it is a lot smaller giving you more flexibility in positioning.

roberttidey avatar May 14 '22 14:05 roberttidey

Hi, I've ordered one at Amazon france and it should be delivered on next monday. I'll try all th scripts we disccused, and I'll see if that works better. For my birds survey, I just have to detect at 0,5 m. That should be good enough... I've also seen another PIR from Parallax. But I don't know if it is close to the am312 or close to the HC-5501 !

pdemeure avatar May 14 '22 16:05 pdemeure