0

I'm having trouble programming the logic of 2 PIR sensors to print a message in console whenever a user place both hands on the PIR sensors.I have managed to successfully attach the PIR sensors to the raspberry pi using GPIO,GND and 5v port. The code that I currently have does print out a message in console whenever someone waves there hand across one but i'm having difficulty modifying the code to print an error message out when someone waves their hand on both the PIR sensors.

https://i.stack.imgur.com/3kURK.png

We can read input from the sensor using GP4 and GP17

import RPi.GPIO as GPIO
import time

sensor = 4
sensor2 = 17
GPIO.setmode(GPIO.BCM)
GPIO.setup(sensor, GPIO.IN, GPIO.PUD_DOWN)

previous_state = False
current_state = False

while True:
    time.sleep(0.1)
    previous_state = current_state
    current_state = GPIO.input(sensor)
    if current_state(TRUE) != previous_state(FALSE):
        new_state = "HIGH" if current_state else "LOW"
        print("GPIO pin %s is %s" % (sensor, new_state))

The program is pretty simple. The Raspberry Pi GPIO pins to allow us to use pin 4 as an input; it can then detect when the PIR module sends power. The pin continually check for any changes, uses a while True loop for this. This is an infinite loop so the program will run continuously unless we stop it manually with Ctrl + C.

Then use two Boolean variables (True or False) for the previous and current states of the pin, the previous state being what the current state was the preceding time around the loop.

Inside the loop we compare the previous state to the current state to detect when they're different. We don't want to keep displaying a message if there has been no change.

peter pan
  • 27
  • 8
  • What exactly do you have difficulty with? Accessing the second sensor or programming the logic to print out a message when both sensors detect something? – sietschie Apr 23 '16 at 13:41
  • @sietschie programming the logic to print out a message when both sensors detect – peter pan Apr 23 '16 at 13:41
  • @peterpan *"The pin continually check for any change (...)"* This is referred to as "polling" and it's best to avoid it if you can. Use `RPi.GPIO`'s `add_event_detect` interrupt driven callbacks instead. Then you can eliminate the infinite loop entirely and let the script do other stuff while still reacting to the sensors. You can use the time difference between rising edges to define what "simultaneously" means to you (a max difference of 1 second between sensor 1 and sensor 2 being triggered, for instance) – jDo Apr 23 '16 at 13:58
  • @jDo Would you able to show an example because I'm learning how to program in python and I don't know how to approach your logic – peter pan Apr 23 '16 at 13:59
  • @peterpan Yep, I've given similar answers several times. Looking through my answer history now to find something you can use – jDo Apr 23 '16 at 14:01
  • @jDo I looked through your answer history and the closes one I can one is this one http://stackoverflow.com/questions/36735925/gpio-over-raspberry-pi-3-model-b-using-node-js/36752267#36752267 but i don't know how to apply it to my case . Would you able to provide an example please – peter pan Apr 23 '16 at 14:06
  • @peterpan Yeah, I just realized that many of the questions were deleted (probably because they should have been asked on the Raspberry Pi stack exchange instead). Like this one "how can i run the loop of motion sensor and say we press the off button and the motion sensor turns off". Maybe I got some code locally. – jDo Apr 23 '16 at 14:08
  • @peterpan [Here's one](https://stackoverflow.com/questions/36438345/use-python-to-get-state-of-combustion-engine-based-on-spark-plug-actuation) – jDo Apr 23 '16 at 14:11
  • @jDo I see you only define 1 GPIO port. Sorry I don't get your script. What you mean via Use RPi.GPIO's add_event_detect interrupt driven callbacks instead. Then you can eliminate the infinite loop entirely and let the script do other stuff while still reacting to the sensors. You can use the time difference between rising edges to define what "simultaneously" means to you (a max difference of 1 second between sensor 1 and sensor 2 being triggered, for instance – peter pan Apr 23 '16 at 14:14
  • @jDo Would you able to post an example please because i don't understand how your script works! – peter pan Apr 23 '16 at 14:21

2 Answers2

0

You definde a second set of state variables for the second sensor for example

previous_state_sensor2 = False
current_state_sensor2 = False

and set them exactly like for the first sensor. Then you add a if condition like this:

if (current_state(TRUE) and current_state_sensor2(TRUE)) and
   (previous_state(FALSE) or previous_state_sensor2(FALSE)):
    print "both sensors detected something"

(I am not sure about the exact syntax since I am not familiar with this way of evaluating booleans: current_state(TRUE). But the idea should be the same.)

sietschie
  • 7,425
  • 3
  • 33
  • 54
  • You said you the problem is the logic and not, how you access the second sensor. I am not familiar with this specific python module. But I assume you have to call `setup` for the second sensor, too. – sietschie Apr 23 '16 at 13:56
0

I haven't checked the code for syntax errors and don't have access to a Pi at the moment, but it's an example of what I was referring to in this comment:

"Use RPi.GPIO's add_event_detect interrupt driven callbacks instead. Then you can eliminate the infinite loop entirely and let the script do other stuff while still reacting to the sensors. You can use the time difference between rising edges to define what "simultaneously" means to you (a max difference of 1 second between sensor 1 and sensor 2 being triggered, for instance)"

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.IN, GPIO.PUD_DOWN)
GPIO.setup(4, GPIO.IN, GPIO.PUD_DOWN)

pir1_last = pir2_last = time.time()

def callback_func(pin):
    global pir1_last
    global pir2_last
    t_now = time.time()

    if GPIO.input(17):
        pir1_last = t_now
    if GPIO.input(4):
        pir2_last = t_now

    t_diff = abs(pir1_last - pir2_last)
    if t_diff < 0.5:
        print "it's been less than 0.5 seconds since both PIRs were activated"

# change GPIO.RISING to GPIO.FALIING if your PIRs are active low 
GPIO.add_event_detect(17, GPIO.RISING, callback=callback_func)
GPIO.add_event_detect(4, GPIO.RISING, callback=callback_func)

def main():
    while True:
        print "Not blocking! You're free to do other stuff here"
        time.sleep(10)

I'm not completely sure that it's actually the pin number that's passed to the callback (that's why I'm also doing a reading of the pin states in the callback to make sure). If you add print(pin) to the callback function and it prints a pin number, there's no reason to do a reading and you can replace the callback with this:

def callback_func(pin):
    global pir1_last
    global pir2_last
    t_now = time.time()

    if pin == 17:
        pir1_last = t_now
    if pin == 4:
        pir2_last = t_now

    t_diff = abs(pir1_last - pir2_last)
    if t_diff < 0.5:
        print "it's been less than 0.5 seconds since both PIRs were activated"
jDo
  • 3,962
  • 1
  • 11
  • 30
  • @peterpan If you search online, you'll find out that `command not found` and `syntax error near unexpected token` are not python error messages. You're still in bash/shell/terminal and haven't actually run the code yet. Add a [python shebang](http://ubuntuforums.org/showthread.php?t=1648150) at the top of your script and make it executable or invoke the python interpreter directly instead of using `./` to run the script. – jDo Apr 25 '16 at 08:09
  • @peterpan If you have 2 resistors and 3 breadboard wires (which you do since that's what you need to connect a single PIR sensor), you could easily do some testing yourself. Simply increase `t_diff < 0.5:` to 5-10 seconds so you have a little more time and test it manually by connecting both GPIOs to 3v3 via the resistors. This is electronics 101 though and I'm afraid the comment section isn't the right place for that. If you don't understand the script, you should look up the lines/modules on google. Read, test, read, test and then read a little more... and don't forget the resistors! – jDo Apr 25 '16 at 10:13
  • @peterpan...and no, there wouldn't be any output if you only use one PIR – jDo Apr 25 '16 at 10:24
  • Hi @jDo, I can't seem to get the code working, when I execute the code, nothing appears even when I use 2 both sensors http://pastebin.com/raw/yPNdxHpc – peter pan May 08 '16 at 11:39
  • I executed both scripts and the command executed very quick and nothing appeared – peter pan May 08 '16 at 11:44
  • @peterpan Both scripts? The first code snippet is the actual script and the 2nd is an alternative callback function - not a stand-alone script. Why did you add `#!/bin/bash` to a python script? Anyway, there's a `while True` loop in the `main` function so it shouldn't exit - ever. Dumb question... Are you actually *calling* the `main` function or did you just copy/paste the code verbatim? Add `if __name__ == "__main__": main()` if that's what's going on. – jDo May 08 '16 at 16:44
  • Thank you jDo. I have managed to get it working. Sorry for the silly questions – peter pan May 08 '16 at 23:44