user5740843 user5740843 - 6 months ago 13
Python Question

GPIO Momentary button controls relay

I'm wondering if it's possible to have my momentary button control a relay in Python whilst I'm holding the button down?

In essence, when the button is pushed, the relay is on, and when the button is released, the relay is off.

Currently, I'm able to control the relay with a small python script, switching it on for a duration of 5 secondes:

relay.py:

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)
GPIO.setup(4, GPIO.OUT)

GPIO.output(4, GPIO.LOW)
time.sleep(5)
GPIO.output(4, GPIO.HIGH)
GPIO.cleanup()

print "Done!"


And able to track when the momentary button is being hold down:

button.py:

import os
from time import sleep
import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)
GPIO.setup(25, GPIO.IN)

while True:
if (GPIO.input(25) == False):
print "Button being pushed!"
GPIO.output(4, GPIO.LOW)
sleep(0.025)


I've tried to combine the two in this fasion:

import os
from time import sleep
import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)
GPIO.setup(25, GPIO.IN)
GPIO.setup(4, GPIO.OUT)

while True:
if (GPIO.input(25) == False):
print "Button being pushed!"
GPIO.output(4, GPIO.LOW)
sleep(0.025)
GPIO.output(4, GPIO.HIGH)


But to no avail. Any help would be really appreciated!

jDo jDo
Answer

Sure, this should do the trick. I didn't test it so it might need some minor edits.

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)

# Added a software pull-up here for increased stability
GPIO.setup(25, GPIO.IN, GPIO.PUD_UP)
GPIO.setup(4, GPIO.OUT)
# The relay seems to be active low. Default to off.
GPIO.output(4, GPIO.HIGH)

# This function is run every time the button state changes 
# from low to high or high to low (GPIO.BOTH)
def callback_func(pin):
    # The button transitioned to high (released) 
    if GPIO.input(pin):
        # Relay off
        GPIO.output(4, GPIO.HIGH)
    else:
        # The button went low (it was pressed). Relay on.
        GPIO.output(4, GPIO.LOW)

# Set up threaded event detection (no constant polling of pin states).
# Fires on both high-to-low and low-to-high state changes.
# Added 200 milliseconds of debounce (because no mechanical switch is perfect)
GPIO.add_event_detect(25, GPIO.BOTH, callback=callback_func, bouncetime=200)

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

if __name__ == "__main__":
    main()

If GPIO.PUD_UP doesn't cause a rising edge when the button is released, you'll have to add a resistor to VCC. It's a good idea to do that anyway since it'll ensure that the relay remains in its default state even if the software should fail.

An uglier version that constantly writes to the relay GPIO when the button is pressed but should work without pull-ups:

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)

GPIO.setup(25, GPIO.IN, GPIO.PUD_UP)
GPIO.setup(4, GPIO.OUT)
GPIO.output(4, GPIO.HIGH)

def callback_func(pin):
    while not GPIO.input(pin):
        GPIO.output(4, GPIO.LOW)
    GPIO.output(4, GPIO.HIGH)

GPIO.add_event_detect(25, GPIO.FALLING, callback=callback_func, bouncetime=200)

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

if __name__ == "__main__":
    main()