Search code examples
pythonraspberry-pidetectionled

a trivial Presence detector with raspberry using python


I want to build a presence detector using raspberry pi, to say if someone is present in a room or not.

So far, the principle is very simple and basic : I use a pir detector to detect movement. After this first step, I want to use a led (for example) which will be red if the room is full and green if it is free. I don't know what I can do after that, but I want to succed in that first. Using the net, I wrote this program (which works ) :

import RPi.GPIO as GPIO
import time
import urllib

GPIO.setmode(GPIO.BCM)

GPIO_PIR = 7

GPIO.setup(GPIO_PIR,GPIO.IN)

Current_State  = 0
Previous_State = 0

try:
    print "Attente detection..."
    while GPIO.input(GPIO_PIR)==1:
        Current_State = 0
    print " Pret"

    while True :

        Current_State = GPIO.input(GPIO_PIR)

        if Current_State==1 and Previous_State==0:
            print " Mouvement detecte !"
            time.sleep(5)
            Previous_State=1
        elif Current_State==0 and Previous_State==1:
            print " Pret "
            Previous_State=0

            time.sleep(1)

except KeyboardInterrupt:
    print " Quit"
GPIO.cleanup()

What I want to do now is to have a message which will contain the state of the room, so this message can be "room full" or "room empty".

For example, if a movement is detected (the terminal will print "movement detected" and after 5 seconds "ready for detection") the message should be "room full". And if no movement has been detected after 10 seconds, the message will switch to "room empty" etc.

That's it ! I know that it is very simple and basic to do it in python (it's not a raspberry question) but I'm not really familiar with python and I don't know how to using that with all this blocks of "if" and "while". Can you help me please to fix that, thank you


Solution

  • You're so close!

    Let's jump to what's correct first. In your second while True block, your code already sleeps (waits) for an interval before continuing. Here it is with some comments and formatting corrections:

    while True:
    
        # this reads from your GPIO to set a variable
        Current_State = GPIO.input(GPIO_PIR)
    
        # if it detected motion or if there wasn't motion last time we checked..
        if Current_State==1 and Previous_State==0:
            print " Mouvement detecte !"
    
            # wait five seconds so we're not checking as fast as the cpu
            # will allow!
            time.sleep(5)
            Previous_State=1
    
        # this block has the same logic as above, but in reverse!
        elif Current_State==0 and Previous_State==1:
            # if we don't detect motion on gpio, print ready
            # this is where we need to keep track of how many times we didn't
            # detect motion.
            print " Pret "
            Previous_State=0
    
            time.sleep(1)
    

    Now, let's make this work. You likely don't want the first while GPIO.input(GPIO_PIR)==1: block as it's going to just block the thread, setting Current_State, even though we just redefine it later (this is also likely blocking your program to getting to the actual While True: loop that does our work.

    Here's what a cleaned up version that implements the logic you want looks like:

    import RPi.GPIO as GPIO
    import time
    import urllib
    
    GPIO.setmode(GPIO.BCM)
    GPIO_PIR = 7
    GPIO.setup(GPIO_PIR,GPIO.IN)
    
    Previous_State = 0
    Pret_Counter = 0
    pret_message = None
    
    try:
        # this will only print the first time.
        print "Attente detection..."
    
        # this loop will continuously run
        while True:
    
            Current_State = GPIO.input(GPIO_PIR)
    
            # if we have a message, print it!
            if pret_message:
                print pret_message
    
            if Current_State and Previous_State==0:
                print "Mouvement detecte!"
                time.sleep(5)
                Previous_State=1
                # Someone moved.  reset detection counter.
                Pret_Counter = 0
    
            elif Pret_Counter > 9:
                # if we've been empty for 10 seconds,
                # don't bother incrementing our counter
                pret_message = "Room empty"
    
            elif Current_State==0 and Previous_State:
                print "Pret"
                Pret_Counter += 1
                Previous_State=0
                time.sleep(1)
    
    except KeyboardInterrupt:
        print "Quit"
    GPIO.cleanup()
    

    I don't have a raspberry pi on hand to test the behavior of the GPIO or the pir detector, but this should do the trick.

    Also, You probably want to play with the thresholds a bit -- as your code is now, you check for motion only once every 5 seconds. If no motion is detected twice, you're marking the room as empty. I'd suggest using a similar trick to your new empty logic -- check every 2 seconds maybe 10 times (sometimes meetings are boring and people take micronaps) before deciding it's empty.

    As a side note, you should go through a Python tutorial, such as the official Python 2 version if you want to keep learning an old version, or the Python 3 version to learn the current state of Python programming.