I'm working on a little Raspberry Pi security project that has LEDs, a piezoelectric buzzer, a 9 digit keypad, and an LCD screen (Full Source Here: https://github.com/kevbo423/RPHSP/blob/master/Keypad.py).
In short, when a user enters an incorrect password with the keypad, I want the LEDs to flash and the buzzer to go off at the same time. I can't for the life of me figure out how to make that happen. I have the functions for the LEDs and the Buzzer created and individually working, but can't get them to go off simultaneously.
# Function for error LED feedback
def errorLED():
for i in range(3):
GPIO.output(6,1)
time.sleep(0.2)
GPIO.output(6,0)
GPIO.output(12,1)
time.sleep(0.2)
GPIO.output(12,0)
# Function for Buzzer Alarm Output
def buzzerAlarm():
for i in range(3):
GPIO.output(21,1)
time.sleep(0.5)
GPIO.output(21,0)
time.sleep(0.5)
I looked into using the Threading module, but ran into issues when I tried to execute the thread for the Buzzer beeping multiple times. Below is the test code I created to try and run the Buzzer thread multiple times...
# Buzzer Test
buzzerSound = threading.Thread(target=buzzerAlarm())
buzzerSound.start()
time.sleep(3)
buzzerSound.start()
time.sleep(3)
buzzerSound.start()
time.sleep(3)
...and the error message I received.
Traceback (most recent call last):
File "Keypad.py", line 277, in <module>
buzzerSound.start()
File "/usr/lib/python2.7/threading.py", line 730, in start
raise RuntimeError("threads can only be started once")
RuntimeError: threads can only be started once
Am I on the right track with the threading module? If so, should I be killing the Buzzer thread inside of the BuzzerAlarm()
function or should I not be using .start()
to run the function? Or do I need to be doing something else entirely? If threading isn't the best way to go, I'm open to suggestions.
From the documentation:
start()
It must be called at most once per thread object.
Therefore you should create a new Thread
object if you want to start it again. For example:
buzzer_thread = threading.Thread(target=buzzerAlarm())
led_thread = threading.Thread(target=errorLED())
led_thread.start()
buzzer_thread.start()
time.sleep(3)
# Second time:
buzzer_thread = threading.Thread(target=buzzerAlarm())
led_thread = threading.Thread(target=errorLED())
led_thread.start()
buzzer_thread.start()
You may consider refactoring this into a function:
def buzzer_and_led():
buzzer_thread = threading.Thread(target=buzzerAlarm())
led_thread = threading.Thread(target=errorLED())
led_thread.start()
buzzer_thread.start()
# Wait until both the buzzer and the LED stop
while led_thread.is_alive() or buzzer_thread.is_alive():
pass