silvanmelchior / RPi_Cam_Web_Interface

A web interface for the RPi Cam
MIT License
1.52k stars 489 forks source link

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

Open pdemeure opened 2 years ago

pdemeure commented 2 years ago

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

roberttidey commented 2 years ago

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.

pdemeure commented 2 years ago

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 !

roberttidey commented 2 years ago

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.

pdemeure commented 2 years ago

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

roberttidey commented 2 years ago

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 &

pdemeure commented 2 years ago

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 commented 2 years ago

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 !

roberttidey commented 2 years ago

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

pdemeure commented 2 years ago

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 !

roberttidey commented 2 years ago

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 commented 2 years ago

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 `

pdemeure commented 2 years ago

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()

roberttidey commented 2 years ago

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

pdemeure commented 2 years ago

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...

roberttidey commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

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()          ```
pdemeure commented 2 years ago

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

roberttidey commented 2 years ago

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()
pdemeure commented 2 years ago

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...

roberttidey commented 2 years ago

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

pdemeure commented 2 years ago

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 commented 2 years ago

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

roberttidey commented 2 years ago

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.

pdemeure commented 2 years ago

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 commented 2 years ago

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 !

roberttidey commented 2 years ago

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.

pdemeure commented 2 years ago

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 ?

roberttidey commented 2 years ago

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.

pdemeure commented 2 years ago

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 !

roberttidey commented 2 years ago

As far as I can see the Parallax seems to be similar to HC-5501. The chip used looks similar and it is not shielded so it may well have same interference issues.

Hopefully the AM312 will work for your application.

The other thing worth mentioning is that when using the in-built motion detection. It is possible to apply an electronic mask to limit the area of the image where motion detection occurs. This can be helpful in some cases in eliminating triggers from motion outside of the areas of interest. Details on how to do this are in the wiki.

pdemeure commented 2 years ago

I've tried to use the system outdoor, far from my wifi box. Same continuously recording occurs... RCWI records videos even if nothing/nobody are in front of PIR. Then the sole wifi possibles is the one of the PI 3B.... Do you think that this could be the cause of the issue ? I look fordward to receive the am312 tomorrow...

roberttidey commented 2 years ago

It is the raspberry wifi that will cause retriggering. If you can put the senssor on extension leads and get it distant from the raspberry that might help, but the am312 is a better bet.

pdemeure commented 2 years ago

Yes I could put it on extension, but for my proect, it will always be near from the raspberry.... Then the better thing is to try the am312. Other solution : I could use a older raspberry without wifi, and just connect a wifi key when needded.

pdemeure commented 2 years ago

Hi, I'd like to test a raspberry pi model which is without wifi, but has an ethernet rj45 port. If you have one you don't use now, could you sell it to me ? Which is the best model ?

roberttidey commented 2 years ago

You don't need a different raspberry model. You can just disable wifi (and bluetooth).

See for example https://www.animmouse.com/p/how-to-disable-wifi-and-bluetooth-on-raspberry-pi/

pdemeure commented 2 years ago

Hello Robert I've received the am312 and connected it on my raspi. That works well !!! Just as intended. Motion detected---> REcording 10s video and stop until next motion detection. We've define ca 1 10 , that records 10s videos. Is it possible to recod video as long as a subject is in front of PIR ? (in one video, not in continuous independant videos like with RHC-5501)

roberttidey commented 2 years ago

If you want the camera to record whilst the PIR signal is active and to stop when it is inactive then

1) Change the command from ca 1 10 to ca 1 This will just turn the camera on.

2) repeat the 3 lines that send the command in the part after it has waited for the PIR to go low (where motion ended is printed) but make the command ca 0 which will stop the recording.

If you are using the version that uses the edge triggered then you will need the one that detects BOTH edges and add the 3 lines to turn the camera off in the part where it prints falling edge detected.

However, you may find that you get several short videos as any still period of more than a few seconds will stop the camera. in the first type of script not using the pir edge method, you could set a minimum time for a recording by putting a sleep after recording starts before it starts looking for PIR inactive.

pdemeure commented 2 years ago

Hi, I've contacted the distributor of thePIR and explained the issue. They told me to decrease sensibility and time output. But that was not satisfying. They'll send me a new PIR in replacement in case of the one is defective. I'll keep yu in touch when I'll test the new one.

Now, I need to automatically initialise the PIR when I power the raspberry. Can I use the script which works well aithe the am312 ? How to rn it automatically a stating time ? Thanks for all ! Pierre

roberttidey commented 2 years ago

One of the easiest ways to start the python program automatically at boot is to add an entry to the /etc/rc.local file

e.g. sudo nano /etc/rc.local

cursor down to just before the end and add

sudo python /path/to/pythonfile &

e.g. sudo python /home/pi/pirTrigger.py &

save the file and next time the raspberry is booted the script will be started

It is very important you put the space & on the end of the line as this ensures the script runs in the background.

pdemeure commented 2 years ago

I added this line after the instructions to Start RCWI. I wrote it Before the RCWI start instructions but that creates an errot in the view of RCWI

Then I wrote the line after RCWI Start instructions and that works fine !

Thank you for all !

roberttidey commented 2 years ago

It shouldn't matter whether it is before or after as it is starting a program independently of the camera stuff.

If putting it before causes an error in RCWI starting up then it sounds like something is wrong with how you entered the line. Make sure you entered the path correctly including the case of the letters

You can check whether the script is running by using the command

ps lww -C python

If it is running then you should see a process with the command line

pdemeure commented 2 years ago

Hi, Some feedback after many tries and settings. I got a replacement PIR sensor, but it had the same issues of unattended motion detection. I spent lot of time to set up the 2 components which set up Timeout and sensitivity. I no have the PIR working rather correctly. I still have unwanted detections, but they are due to lighting changes with sun or clouds. At 80% I get good detection, even with small birds lke robin !