Search code examples
pythonautomationraspberry-pi2

Raspberry waiting press microswitch


I'm creating my simple home automation with raspberry. Now I can open garage door, gate and read temperature. The server is a node js. Now I would like to detect when the garage door is opening. I think to use a microswitch, but how is the optimal way to detect when is pressed? An infinite loop in a python script? A polling script? Can you help me? Thanks


Solution

  • Basically what you are looking for is implementing GPIO interrupt, all you should need is RPi.GPIO module.

    However in RPi.GPIO module description, there is a warning:

    Note that this module is unsuitable for real-time or timing critical applications. This is because you can not predict when Python will be busy garbage collecting. It also runs under the Linux kernel which is not suitable for real time applications - it is multitasking O/S and another process may be given priority over the CPU, causing jitter in your program. If you are after true real-time performance and predictability, buy yourself an Arduino!

    I've found three ways of implementing your task (I believe there should be more):

    Polling is continually checking for something. For example, if you want to make sure your program reacts as quickly as possible to a button press, you can check the button status about ten thousand times per second. This is great if you need a quick reaction, but it uses quite a bit of the computer’s processing power. In the same way that you can’t fully focus when you’re expecting a delivery, a large part of your CPU is used up with this polling.

    #!/usr/bin/env python2.7
    # script by Alex Eames http://RasPi.tv/
    # http://raspi.tv/2013/how-to-use-interrupts-with-python-on-the-raspberry-pi-and-rpi-gpio
    import RPi.GPIO as GPIO
    GPIO.setmode(GPIO.BCM)
    
    # GPIO 23 set up as input. It is pulled up to stop false signals
    GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_UP)
    
    print "Make sure you have a button connected so that when pressed"
    print "it will connect GPIO port 23 (pin 16) to GND (pin 6)\n"
    raw_input("Press Enter when ready\n>")
    
    print "Waiting for falling edge on port 23"
    # now the program will do nothing until the signal on port 23
    # starts to fall towards zero. This is why we used the pullup
    # to keep the signal high and prevent a false interrupt
    
    print "During this waiting time, your computer is not"
    print "wasting resources by polling for a button press.\n"
    print "Press your button when ready to initiate a falling edge interrupt."
    try:
        GPIO.wait_for_edge(23, GPIO.FALLING)
        print "\nFalling edge detected. Now your program can continue with"
        print "whatever was waiting for a button press."
    except KeyboardInterrupt:  
        GPIO.cleanup()       # clean up GPIO on CTRL+C exit
    GPIO.cleanup()           # clean up GPIO on normal exit
    

    When an event is detected in the second thread, it communicates this back to the main thread (calls back). What we now have in RPi.GPIO is the ability to start a new thread for an interrupt and specify a set of instructions (function) that will run when the interrupt occurs in the second thread. This is a threaded callback function.

    #!/usr/bin/env python2.7  
    # script by Alex Eames http://RasPi.tv  
    
    import RPi.GPIO as GPIO  
    GPIO.setmode(GPIO.BCM)  
    
    # GPIO 23 & 24 set up as inputs. One pulled up, the other down.  
    # 23 will go to GND when button pressed and 24 will go to 3V3 (3.3V)  
    # this enables us to demonstrate both rising and falling edge detection  
    GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_UP)  
    GPIO.setup(24, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)  
    
    # now we'll define the threaded callback function  
    # this will run in another thread when our event is detected  
    def my_callback(channel):  
        print "Rising edge detected on port 24 - even though, in the main thread,"  
        print "we are still waiting for a falling edge - how cool?\n"  
    
    print "Make sure you have a button connected so that when pressed"  
    print "it will connect GPIO port 23 (pin 16) to GND (pin 6)\n"  
    print "You will also need a second button connected so that when pressed"  
    print "it will connect GPIO port 24 (pin 18) to 3V3 (pin 1)"  
    raw_input("Press Enter when ready\n>")  
    
    # The GPIO.add_event_detect() line below set things up so that  
    # when a rising edge is detected on port 24, regardless of whatever   
    # else is happening in the program, the function "my_callback" will be run  
    # It will happen even while the program is waiting for  
    # a falling edge on the other button.  
    GPIO.add_event_detect(24, GPIO.RISING, callback=my_callback)  
    
    try:  
        print "Waiting for falling edge on port 23"  
        GPIO.wait_for_edge(23, GPIO.FALLING)  
        print "Falling edge detected. Here endeth the second lesson."  
    
    except KeyboardInterrupt:  
        GPIO.cleanup()       # clean up GPIO on CTRL+C exit  
    GPIO.cleanup()           # clean up GPIO on normal exit
    

    Well actually, we’re not doing much that’s very different from last time, except, now there’s more of it. We’ll add another button and another threaded callback function the same as the first one (but on a different GPIO port). This is just to show that you can do multiple threaded callbacks in one program. After that, your imagination is the limit. (Well actually the number of GPIO ports is probably the limit.)

    #!/usr/bin/env python2.7  
    # script by Alex Eames http://RasPi.tv  
    # http://RasPi.tv/how-to-use-interrupts-with-python-on-the-raspberry-pi-and-rpi-gpio-part-3  
    import RPi.GPIO as GPIO  
    GPIO.setmode(GPIO.BCM)  
    
    # GPIO 23 & 17 set up as inputs, pulled up to avoid false detection.  
    # Both ports are wired to connect to GND on button press.  
    # So we'll be setting up falling edge detection for both  
    GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_UP)  
    GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_UP)  
    
    # GPIO 24 set up as an input, pulled down, connected to 3V3 on button press  
    GPIO.setup(24, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)  
    
    # now we'll define two threaded callback functions  
    # these will run in another thread when our events are detected  
    def my_callback(channel):  
        print "falling edge detected on 17"  
    
    def my_callback2(channel):  
        print "falling edge detected on 23"  
    
    print "Make sure you have a button connected so that when pressed"  
    print "it will connect GPIO port 23 (pin 16) to GND (pin 6)\n"  
    print "You will also need a second button connected so that when pressed"  
    print "it will connect GPIO port 24 (pin 18) to 3V3 (pin 1)\n"  
    print "You will also need a third button connected so that when pressed"  
    print "it will connect GPIO port 17 (pin 11) to GND (pin 14)"  
    raw_input("Press Enter when ready\n>")  
    
    # when a falling edge is detected on port 17, regardless of whatever   
    # else is happening in the program, the function my_callback will be run  
    GPIO.add_event_detect(17, GPIO.FALLING, callback=my_callback, bouncetime=300)  
    
    # when a falling edge is detected on port 23, regardless of whatever   
    # else is happening in the program, the function my_callback2 will be run  
    # 'bouncetime=300' includes the bounce control written into interrupts2a.py  
    GPIO.add_event_detect(23, GPIO.FALLING, callback=my_callback2, bouncetime=300)  
    
    try:  
        print "Waiting for rising edge on port 24"  
        GPIO.wait_for_edge(24, GPIO.RISING)  
        print "Rising edge detected on port 24. Here endeth the third lesson."  
    
    except KeyboardInterrupt:  
        GPIO.cleanup()       # clean up GPIO on CTRL+C exit  
    GPIO.cleanup()           # clean up GPIO on normal exit
    

    Hopefully this sequence of tutorials helped you understanding Raspberry Pi GPIO interrupts little bit more, but I suggest doing some research on Arduino, or at least lower level languages like C or C++, you can find great tutorial on interrupts there.

    Also you could join Raspberry Pi Stack Exchange community, maby you will find more help there.