7.9 Button and LED

Share for us

Next try! Let’s connect the LED and the button and check what we can do.

Below are the schematic diagrams for a button and an LED.

Connect circuit based on the Fritzing image:

Save a copy of the code in last chapter as button_and_led.py.

And add the LED setting part in the code to turn on the LED when the button is pressed.

import RPi.GPIO as GPIO

import time

led_pin = 17

button_pin = 18

GPIO.setmode(GPIO.BCM)

# Set up LED as output with initial value GPIO.HIGH

GPIO.setup(led_pin, GPIO.OUT, GPIO.HIGH)

GPIO.setup(button_pin, GPIO.IN, GPIO.PUD_UP)

 

def my_callback(channel):

    button_status = GPIO.input(button_pin)

    if button_status == 0:

        # LED ON

        GPIO.output(led_pin, GPIO.LOW)

    else:

        # LED OFF

        GPIO.output(led_pin, GPIO.HIGH)

 

GPIO.add_event_detect(button_pin, GPIO.BOTH, my_callback, bouncetime=20) # Define a edge detection

 

while True:

    print "I'm so boring, nothing left to do."

    time.sleep(3)

To make the LED off when the program just starts to run, we can add an initial parameter in GPIO.OUT. Save the code and run to try.

As mentioned above, Python is an easy-to-understand language, and the low level code is easy to catch. However, a lousy programmer can write the code with Python in a mess, which few people can understand and he himself cannot do after some time like just a few days. Believe me, it happened.

So we propose that the Python code be written in a more readable way, making reading easier!

First, we can divide the code into parts by function. The function’s name suggests what the code does.

Then, split the function part into some detailed segments by more functions.

At last, a main function will just like a short passage, which you can infer even at a glance.

Step 1. Put all the setting lines in the setup() function, to set everything up.

def setup():

    global led_pin, button_pin, ON, OFF, PRESSED, RELEASED

    led_pin = 17

    button_pin = 18

    ON = "led_on"

    OFF = "led_off"

    PRESSED = 0

    RELEASED = 1

   

    GPIO.setmode(GPIO.BCM)

    GPIO.setup(led_pin, GPIO.OUT, GPIO.HIGH)

    GPIO.setup(button_pin, GPIO.IN, GPIO.PUD_UP)

    GPIO.add_event_detect(button_pin, GPIO.BOTH, check_button, bouncetime=20)

It uses a global statement to convert the followed variables to global ones, which means that they can be used in all the functions in this script. Each of the variables should be defined as global whenever they are changed in the code. But since only in setup() function they are changed, global only appears here.

Four variables including ON, OFF, PRESSED and RELEASED are added here to control the LED’s on and off. They will be used later.

Step 2. Write another function to control the LED:

# LED control function

def led(status):

    if status == ON:

        GPIO.output(led_pin, GPIO.LOW)

    elif status == OFF:

        GPIO.output(led_pin, GPIO.HIGH)

By doing this, we can use a readable statement led(ON)/led(OFF) to control the LED

Step 3. Change my_callback to check_button, which makes more sense:

# callback to check button

def check_button(channel):

    button_status = GPIO.input(button_pin)

    if button_status == PRESSED:

        led(ON)

    elif button_status == RELEASED:

        led(OFF)

Remember to change the LED control function to led(ON)/led(OFF).

And change the callback function in add_event_detect accordingly:

    GPIO.add_event_detect(button_pin, GPIO.BOTH, check_button, bouncetime=20)

Step 4. Include the while loop into the main function, indicating it is part of the main function:

# Main function

def main():

    while True:

        print "I'm so boring, doing nothing in main function."

        time.sleep(3)

 

Step 5. Write a destroy function to clean occupied program before stopping the script:

# "Destroy" everything before stopping the script

def destroy():

    led(OFF)

    GPIO.cleanup()

The GPIO.cleanup() is the best way to solve the problem of nonstop warning message. It will release the GPIO resources before the program ends, thus no message of occupied GPIO will appear when you run it next time.

Step 6. The if-__main__ statement is often used to execute the function in Python. This statement means the Python will run only when it is used as the main program, not called as a library.

if __name__ == "__main__":

    try:

        setup()

        main()

    except KeyboardInterrupt:

        destroy()

The try-except function, as the name suggests, means to try to run setup() and then main(); except when KeyboardInterrupt occurs, it will run destroy().

KeyboardInterrupt is a special parameter triggered when you press Ctrl + C. By using this function, the program would not stop at once when you press Ctrl + C, but go to the except statement and run destroy() to clear some occupied program before it exits.

Now the code is DONE. It will be like this:

import RPi.GPIO as GPIO

import time

 

# Setup the GPIO and stuff

def setup():

    global led_pin, button_pin, ON, OFF, PRESSED, RELEASED

    led_pin = 17

    button_pin = 18

    ON = "led_on"

    OFF = "led_off"

    PRESSED = 0

    RELEASED = 1

   

    GPIO.setmode(GPIO.BCM)

    GPIO.setup(led_pin, GPIO.OUT, GPIO.HIGH)

    GPIO.setup(button_pin, GPIO.IN, GPIO.PUD_UP)

    GPIO.add_event_detect(button_pin, GPIO.BOTH, check_button, bouncetime=20)

 

# LED control function

def led(status):

    if status == ON:

        GPIO.output(led_pin, GPIO.LOW)

    elif status == OFF:

        GPIO.output(led_pin, GPIO.HIGH)

 

# callback to check button

def check_button(channel):

    button_status = GPIO.input(button_pin)

    if button_status == PRESSED:

        led(ON)

    elif button_status == RELEASED:

        led(OFF)

 

# Main function

def main():

    while True:

        print "I'm so boring, doing nothing in main function."

        time.sleep(3)

 

# "Destroy" everything before stopping the script

def destroy():

    led(OFF)

    GPIO.cleanup()

   

if __name__ == "__main__":

    try:

        setup()

        main()

    except KeyboardInterrupt:

        destroy()

The whole code seems to be much longer in size, but you will find it’s easier to understand when you go over it. Good job!

Now, all the experiments come to the end. Bet you’ve learnt a lot in bot circuit and code. Congrats!