Search code examples
pythonbuttontkinterlight

LED to blink when a push button is NOT pressed and to be continually on when the button IS pressed (Python)


So, i have a LED controlled by a Raspy, and also a basic GUI with just a push button, I want it to behave as follows:

  • LED blinks when the push button IS NOT pressed.
  • LED should stay ON continually when the push button IS pressed.

When I execute light starts blinking, but the button does not show up. When I interrupt the program, the button shows up. Why?

from tkinter import *
import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BOARD)
GPIO.setup(8, GPIO.OUT)
GPIO.output(8, False)
buttonPressed = False

master = Tk()

def callback():
    GPIO.output(8, True)
    buttonPressed = True

w = Button(master, text="Turn on light", command = callback)
w.pack()

while True:
    if buttonPressed == False:
        GPIO.output(8, True)
        time.sleep(0.5)
        GPIO.output(8, False)
        time.sleep(0.5)
    else:
        GPIO.output(8, True)

Solution

  • I can't test it on RPi but I could be something like this.

    Normal command= can recognize only when you clicked button but it can't recognize when you released it - you need to bind events <ButtonPress> and <ButtonRelease> which will run functions on "mouse left button press" and "mouse left button release"

    I use after() to run function with delay so I don't need sleep() and while which can block mainloop() (and it can freeze all GUI).

    And I don't need also while loop because I run all inside on_press and on_release and later after() runs turn_off_led which use after() to run turn_on_led which use after() to run again turn_off_led so it works like loop.

    import tkinter as tk  # PEP8: `import *` is not preferred
    import RPi.GPIO as GPIO
    
    GPIO.setmode(GPIO.BOARD)
    GPIO.setup(8, GPIO.OUT)
    GPIO.output(8, False)
    
    button_pressed = False  # PEP8: preferred `lower_case_names`
    
    # --- functions ---
    
    def on_press(event):
        global button_pressed
    
        button_pressed = True
        GPIO.output(8, True)
    
    def on_release(event):
        global button_pressed
    
        button_pressed = False
        GPIO.output(8, True)
    
        # run after 500ms (0.5s) instead of `sleep`
        master.after(500, blink_off)
    
    def blink_off():
        if not button_pressed:
            GPIO.output(8, False)
            # run after 500ms (0.5s) instead of `sleep`
            master.after(500, blink_on)
    
    def blink_on():
        if not button_pressed:
            GPIO.output(8, True)
            # run after 500ms (0.5s) instead of `sleep`
            master.after(500, blink_off)
    
    # --- main ---
    
    master = tk.Tk()
    
    button = tk.Button(master, text="Turn on light")
    button.pack()
    
    # here "button" means "tk.Button" and "Button" means "mouse left button"
    button.bind('<ButtonPress>',   on_press)   # mouse left button pressed on tk.Button 
    button.bind('<ButtonRelease>', on_release) # mouse left button released on tk.Button
    
    # start blinking - it will use `after()` to loop
    blink_on()
    
    master.mainloop()