this will be my first post here, hope it will go well!
I am new to both Raspberry Pi3 and Python, but I wanted to give it a try. I have connected my Pi to a button, and when I push it, I want to play a sound. When I run my code, everything looks ok, and when I push the button, VLC plays the wav-file. All good. But... VLC will only play the wav-file once, when I press the button again, only the "Now func1 is done" appears on the screen, but no more sound:(
I need to close and re-run my program to be able to hear the wav again, and only once. How do I get my program to run the wav everytime I push my button without restarting?
Thx!
import RPi.GPIO as GPIO
from time import sleep
import vlc
GPIO.setmode(GPIO.BOARD)
player = vlc.MediaPlayer("/home/pi/Desktop/ljud/aliengun.wav")
stime = 1
button = 11
GPIO.setup(button, GPIO.IN, pull_up_down=GPIO.PUD_UP)
def func1():
player.play()
print("Now func1 is done")
try:
while True:
input_state = GPIO.input(button)
if input_state != 1:
func1()
sleep(stime)
finally:
GPIO.cleanup()
Related
My project is to make a program that you can run while you are playing games or other programs in the background.
When you press a certain key, your notepad should open and also close after you press the same key again.
I have managed to open notepad with subprocess and that works fine but I have no idea to make it open only when a certain key is pressed.
Thanks for any help!
EDIT:
What I tried already:
import subprocess
import keyboard
if keyboard.is_pressed('k'):
subprocess.Popen('C:\\Windows\\System32\\notepad.exe')
input()
here it just doesn't detect any keyboard input, the input() at the end makes the program not close instantly
import subprocess
import keyboard
keyboard.add_hotkey('ctrl+k', print,args=("hello", "test"))
input()
Here if I press "ctrl+k it" will print hello test that means the hotkey works fine. When I switch this part "print,args=("hello", "test")" to "subprocess.Popen('C:\Windows\System32\notepad.exe')"(it should open the program instead of printing hello test) the notepad opens instantly after I run the program and when I press "ctrl+k" I get a big error.
A more complex, but still working example could be the following. With this code your program will be always listening the keyboard, not only when you are focused on the input, so may be mre practical in your case
from pynput import keyboard
import subprocess
import threading
class MyException(Exception): pass
class Listening:
"""Is allways waiting for the keyboard input"""
def __init__(self):
self.notepad_open = False # to know the state
with keyboard.Listener(
on_press=self.on_press) as listener:
try:
listener.join()
except:
pass
def on_press(self, key):
try:
if key.char == "k":
if not self.notepad_open:
self.subprocess = \
subprocess.Popen('C:\\Windows\\System32\\notepad.exe')
self.notepad_open = True # update state
else:
self.subprocess.kill()
self.notepad_open = False # update state
except: # special key was pressed
pass
thread = threading.Thread(target=lambda: Listening())
thread.start()
The problem is that you check for the key 'k' only once at the beginning. If you want the program to correctly work then you should try this:
import time
import subprocess
import keyboard
while True:
if keyboard.is_pressed('k'):
subprocess.Popen('C:\\Windows\\System32\\notepad.exe')
time.sleep(5)
-I used the time so that you can only open the program once 5 seconds(If you're curious, see what happens without it)-
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
Firstly not a multi-threading answer, this answer should still work either way.
Okay, quick answer. What you could do is combine the two functions
# 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)
This would become
#Combined function
def combined():
for i in range(3):
GPIO.output(6,1) #Error LED
GPIO.output(21,1) #Alarm Buzzer
time.sleep(0.25) #Notice times changed by 0.05 so it can do the combination easyer
GPIO.output(6,0)
GPIO.output(12,1)
time.sleep(0.25)
GPIO.output(12,0)
#Repeats Code
GPIO.output(6,1)
GPIO.output(21,0) #Only difference is turning off the buzzer/alarm
time.sleep(0.25)
GPIO.output(6,0)
GPIO.output(12,1)
time.sleep(0.25)
GPIO.output(12,0)
Tell me if this works, I have not used my Raspberry PI in a while
I would like to stop a loop with a button press in python on my raspberry pi.
I came with this code:
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
GPIO.setup(14, GPIO.OUT)
GPIO.setup(2,GPIO.OUT)
GPIO.setup(21,GPIO.IN)
break_prog=False
def key_press(key):
print("BREAK")
break_prog=True
GPIO.add_event_detect(21,GPIO.FALLING,callback=key_press,bouncetime=300)
for i in range(5):
if break_prog:
print("STOP THE LOOP")
break
else:
print("VERT")
GPIO.output(2,True)
GPIO.output(14,False)
time.sleep(3)
print("ROUGE")
GPIO.output(2,False)
GPIO.output(14,True)
time.sleep(6)
GPIO.cleanup()
When I press the button, 'BREAK' text clearly appears, but in my loop, the if break_prog part is not called, like the variable hasn't been set.
Any idea what I am doing wrong?
I try to develop some code on a machine without GPIO. As GPIO library I selected a gpiozero to be able to write my code without access to gpio of raspberry pi.
My problem, I cant get ride of .when_pressed event in the code.
I simulate state change of the button, but the function is not called.
Device.pin_factory = MockFactory()
def interrupt_Event(channel):
print("%s puted in the queue", channel)
InputPin.Device.pin_factory.pin(channel)
InputPin.when_pressed = interrupt_Event
def main():
try:
while True:
time.sleep(1)
InputPins[channel].pull=drive_high()
time.sleep(0.1)
print("State CHANNEL %s" % channel)
print(InputPins[channel].state)
InputPins[channel].drive_low()
Till now I have no Idea what is wrong.
when_pressed function should not have arguments (see 2.7 in https://gpiozero.readthedocs.io/en/stable/recipes.html).
You could define the callback using a loop :Creating functions in a loop
(use channel=channel to force early binding of channel value as in example below)
for channel in channels:
def onpress(channel=channel):
print("%s puted in the queue", channel)
InputPins[channel].when_pressed = onpress
I am not convinced that you are using drive_high and drive_low to simulate the button pushing.
I have a almost identical problem. using Mock pins to develop a Pi program on windows, I find that the callback routines are not called.
from gpiozero.pins.mock import MockFactory
from gpiozero import Device, Button, LED
from time import sleep
Device.pin_factory = MockFactory() # set default pin
factory
btn = Button(16)
# Get a reference to mock pin 16 (used by the button)
btn_pin = Device.pin_factory.pin(16)
def pressed(): # callback
print('pressed')
def released(): # callback
print('released')
btn.when_pressed = pressed
btn.when_released = released # callback routine
for i in range(3): # now try to signal sensor
print('pushing the button')
btn_pin.drive_high
sleep(0.1)
btn_pin.drive_low
sleep(0.2)
The output has no callbacks, just
pushing the button
pushing the button
pushing the button
>>>
I am creating a script on my raspberry pi that if you press a button the led on the button need to be flashing till I press the button again.
This is my code:
#!/usr/bin/python
import RPi.GPIO as GPIO
import threading
from time import sleep
GPIO.setmode(GPIO.BCM)
pushbutton = 2
led = 3
GPIO.setup(pushbutton, GPIO.IN)
GPIO.setup(led, GPIO.OUT)
class rpiThread(threading.Thread):
def __init__(self):
self.running = False
super(rpiThread, self).__init__()
def start(self):
self.running = True
super(rpiThread, self).start()
def run(self):
self.running = True
while (self.running == True):
GPIO.output(led, GPIO.HIGH)
print "HIGH"
sleep(0.05)
GPIO.output(led,GPIO.LOW)
print "LOW"
sleep(0.05)
def stop(self):
self.running = False
GPIO.output(led, GPIO.LOW)
def main():
myrpiThread = rpiThread()
pushed = GPIO.input(pushbutton)
try:
while(True):
if(pushed == False):
if(GPIO.input(pushbutton) == False):
sleep(0.5)
if(GPIO.input(pushbutton) == False):
myrpiThread.start()
pushed = True
print "The button is pushed"
else:
if(GPIO.input(pushbutton) == True):
GPIO.output(led, GPIO.LOW)
myrpiThread.stop()
pushed = False
print "The button is not pushed"
except KeyboardInterrupt:
print "QUIT"
main()
Always when I run my script my leds arn't flashing each 0.05 sec. Sometimes it takes 2 seconds before it turns on and sometime it just doesn't flash.
I dont know what I am doing wrong? Can someone please help me to figure out what the problem is?
Is it possible that GPIO pins are not made to use in multithreading?
I followed this tutorial when I needed to use threaded callbacks with GPIO:
how to use interrupts with python on the raspberry pi and rpi gpio. It also has a good discussion in the comments about how to avoid using global variables to pass a value back from the threads.
It would be helpful to know exactly how you have your button wired, and what type of button you are using so that I could answer your problem more specifically.
I wrote the following example code assuming that you have the button wired from GPIO 2 to +3.3v
If you have it wired to ground use "pull_up_down=GPIO.PUD_DOWN" and "GPIO.FALLING"
It also assumes you have a momentary push button. When the button push is detected it flips a global boolean value. That value is checked in the main loop, and the blink(led) function is called if pushed = True.
import RPi.GPIO as GPIO
from time import sleep
GPIO.setmode(GPIO.BCM)
pushbutton = 2
led = 3
GPIO.setup(pushbutton, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(led, GPIO.OUT)
pushed = False
# this will run in another thread when the button is pushed
def button_callback(channel):
pushed = not pushed
GPIO.add_event_detect(pushbutton, GPIO.RISING, callback=button_callback)
while True:
if pushed:
blink(led)
def blink(led):
GPIO.output(led, True)
sleep(0.5)
GPIO.output(led, False)
I don't have a raspberry Pi in front of me right now to test this code, but I will check it later. You may have to modify this for your specific set up, but hopefully it gets you in the right direction.