I've written a short piece of code for my Raspberry Pi. The idea is to place the device in a room and when a group of people enter the room (it's a guided tour), the Pi is triggerd by the motion sensor and starts playing a video projected on the wall. So far this works.
When the movie is done playing, I set it to sleep for 10 minutes until the next group enters the room.
I've noticed that sometimes it takes less then 10 minutes before a new group enters the room but the Pi is still sleeping.
I want to solve this by adding a button to my device to manually trigger the loop again. I've wired it to my Pi and it works.
The idea is to manually start the loop when I press the button so the group can see the video. Afterwords the script should go back to normal so the motionsensor picks up the next group.
I can't figure out how to do this. A loop within the first loop? Cut out the 10 minutes sleep in the loop and place it somewhere else?
Hoping someone has some advice.
Thanks in advance.
Below my code:
from gpiozero import MotionSensor, LED, Button
from time import sleep
import vlc
playing = set([1,2,3,4])
# creating Instance class object
vlc_instance = vlc.Instance()
player = vlc_instance.media_player_new()
player.set_fullscreen(True)
#Motion Sensor
pir = MotionSensor(4)
#Led
led = LED(26)
#Button
button= Button(18)
led.off()
print("Sensor wordt geladen.")
pir.wait_for_no_motion()
sleep(5)
while True:
print("Ready")
pir.wait_for_motion()
sleep(1)
print("Motion detected")
led.on()
sleep(1)
led.off()
player.set_mrl("/media/pi/GROT/MOSA25.mp4")
player.play()
sleep(120)
while player.get_state() in playing:
sleep(1)
continue
print("Finished")
sleep(600)
continue
Related
EDIT : replaced GPIO.PUD_UP to GPIO.PUD_DOWN and while loop looks like this now :
playing = False
while True:
if GPIO.input(26)==False:
if not playing:
pygame.mixer.music.play()
playing = True
else:
if playing:
pygame.mixer.music.stop()
playing = False
I'm trying to play music while opening a door, doing it with a raspberry pi Zero WH and an Hall effect sensor. I'm rather new to python, but its fairly simple. But im stuck because i can't find how to do exactly what I want.
So I want to play music when the door is opened (GPIO is LOW), but i also want it to stop when it is closed (when GPIO is UP then). It seems that I can't find how to do it. Here's my code :
import RPi.GPIO as GPIO
import time
import pygame
import pygame.mixer
pygame.mixer.init()
pygame.init()
scary = pygame.mixer.Sound("scary.wav")
pygame.mixer.music.set_volume(0.1)
GPIO.setmode(GPIO.BCM)
GPIO.setup(26, GPIO.IN, pull_up_down=GPIO.PUD_UP)
while True:
if GPIO.input(26)==False:
pygame.mixer.music.play()
while GPIO.input(26)==False:
pass
else:
pygame.mixer.music.stop()
while GPIO.input(26)==True:
pass
I want music to play as soon as the door open, only once (its about a minute long), but can stop whenever the door close. How should I do it ? (time.sleep(x) just delays the whole loop, or maybe idk how to use it?) Thanks !
Addd a variable to keep track if the music is currently playing:
playing = False
while True:
if gpio is high:
if not playing:
play()
playing = True
else:
if playing:
stop()
playing = False
You can't rid of the indentation by using if/else with and/or statements.
The following python script is supposed to wait for a button press, print a button press message, and then exit.
However, when I press the button nothing is printed. Then when I press the enter key, the script prints "Button push detected" then stops.
How might I fix this code so that 'Button push detected' is printed when I push the button?
I followed a tutorial to make this code:
#Button input detection
#by
#Start date: 11th February 2021
#End date: 11th February 2021
#Importing GPIO andtime libraries as per usual with a python script making use of RPi GPIO
import RPi.GPIO as GPIO
import time
#Callback function to print 'Button push detected' when called
def button_callback(channel):
print("Button push detected")
#Disabling annoying GPIO warnings and setting GPIO mode to board
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(11, GPIO.IN, pull_up_down=GPIO.PUD_UP)
#GPIO event detector that detects a rising edge on pin 11
GPIO.add_event_detect(11,GPIO.FALLING,callback=button_callback)
#Command that does not stop until someone presses enter
quit = input("Press enter to quit")
#Clean up the pins used
GPIO.cleanup()
The problem is that your script needs a loop that waits until the button is pressed so that when the button press is detected, your script will be able to react to the event.
Right now your script sets the event detection but then sits waiting for input and as soon as the input is made, your script exits.
See this Raspberry Pi forum post, https://www.raspberrypi.org/forums/viewtopic.php?t=201747
which has a program for lighting an LED on and off with button presses.
However it looks to me like you would probably need to make a change to the call back function to raise an exception rather than light the LED if you want the script to end when you press the button.
See below the modified program with some additional annotation along with the LED light/unlight commented out.
However this modified program uses a busy loop that just runs continuously until the button is pressed. Using a busy loop, while it works for simple programs such as yours, is generally not a good idea.
An alternative is to use the GPIO.wait_for_edge() function that will pause the script until the button is pressed. See Raspberry Pi StackExchange - Pausing code execution till a button is pressed which removes the busy loop.
First the busy loop version.
import time
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
btn_input = 4; # button to monitor for button presses.
LED_output = 17; # LED to light or not depending on button presses.
# GPIO btn_input set up as input.
GPIO.setup(btn_input, GPIO.IN)
# GPIO.setup(LED_output, GPIO.OUT)
# handle the button event
def buttonEventHandler_rising (pin):
# turn LED on
# GPIO.output(LED_output,True)
raise Exception('button pressed')
def buttonEventHandler_falling (pin):
# turn LED off
# GPIO.output(LED_output,False)
raise Exception('button released')
# set up the event handlers so that when there is a button press event, we
# the specified call back is invoked.
# for your purposes you may only want to detect the falling
# indicating that the button was released.
# GPIO.add_event_detect(btn_input, GPIO.RISING, callback=buttonEventHandler_rising)
GPIO.add_event_detect(btn_input, GPIO.FALLING, callback=buttonEventHandler_falling)
# we have now set our even handlers and we now need to wait until
# the event we have registered for actually happens.
# This is an infinite loop that waits for an exception to happen and
# and when the exception happens, the except of the try is triggered
# and then execution continues after the except statement.
try:
while True : pass
except:
GPIO.cleanup()
See as well the explanations as to what is happening in these forum posts
https://www.raspberrypi.org/forums/viewtopic.php?t=128510
https://www.raspberrypi.org/forums/viewtopic.php?t=141520
And this article about exceptions in python. https://realpython.com/python-exceptions/
I am using a system based on a raspberry to control some stuff. At the moment I am just testing it with turning a led on and off.
My plan is: Press a button to open a valve. Press the button again to close it - but if the button is not pressed, close it after a set time. My current script is as follows: (I know that this will not turn the led off on the second press)
import RPi.GPIO as GPIO # Import Raspberry Pi GPIO library
import time,sched
s = sched.scheduler(time.time, time.sleep)
def button_callback(channel):
print("Button was pushed!")
print(time.time())
GPIO.output(18,GPIO.HIGH)
s.enter(10, 1, turnoff,argument='')
s.run()
def turnoff():
print "LED off"
print(time.time())
GPIO.output(18,GPIO.LOW)
btpin=22
ledpin=18
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(btpin, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(ledpin,GPIO.OUT)
GPIO.add_event_detect(btpin,GPIO.RISING,callback=button_callback)
message = input("Press enter to quit\n\n")
GPIO.cleanup()
If I press the button and then leaves things alone, the led will turn off after 10 secs. But, if I press the button again immideately, nothing happens before the scheduler has finished, then a new press is registered. I had expected that the scheduler was spun of in the background so that when I pressed the button again, the callback would have ran again so I would have gotten the "Button was pushed" message (and everything happening afterwards would not have had any effect as GPIO 18 already was high and the scheduled call to turnoff would have happened after turnoff already had run.
Is it possible to use the sched library to do what I want or do I have to use some other techniques? I know I can either do it the simple way, by looping looking for a pressed button rather than registering a callback, or probably a more complicated way by creating a new thread that will pull the GPIO down after a given time - but is there something I have not understood in sched or is there some other library that gives me what I want - a way to tell python do do something a bit in the future without interfering with what else is going on.
(I do not need a very accurate timing - and also, this is just a part of what I intend to make a more complex control system, I manage to do exactly what I want using an arduino, but that will limit the further development)
Thanks to the tip from #stovfl, I rewrote the first part of my code:
import time,threading
def button_callback(channel):
pin=18
print("Button was pushed!")
print(time.time())
GPIO.output(pin,GPIO.HIGH)
t = threading.Timer(10.0, turnoff)
t.start()
and it works just like I wanted
I've just picked up my first Raspberry Pi and 2 channel relay. I'm trying to learn how to code in Python so I figured a Pi to play with would be a good starting point. I have a question regarding the timing of my relays via the GPIO pins.
Firstly though, I'm using Raspbian Pixel and am editing my scripts via Gedit. Please see below for the script I have so far:
# !/usr/bin/python
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
# init list with pin numbers
pinList = [14]
# loop through pins and set mode and state to 'high'
for i in pinList:
GPIO.setup(i, GPIO.OUT)
GPIO.output(i, GPIO.HIGH)
# time to sleep between operations in the main loop
SleepTimeL = 60 #1 minute
# main loop
try:
GPIO.output(14, GPIO.LOW)
print "open"
time.sleep(SleepTimeL);
GPIO.cleanup()
#Reset GPIO settings
GPIO.cleanup()
# end program cleanly
except KeyboardInterrupt:
print "done"
Now that works pretty well, it opens the relay attached to pin 14 no problem. It cycles through 60 seconds as requested and then ends the program. Once the program has ended, the GPIO settings are reset and the relay closes, but that's the end of the program and it's where my problem starts.
What I want this script to do is open the relay for 60 seconds, then close it for 180 seconds. Once it reaches 180 seconds it must re-run the 'try' statement and open the relay for another 60 seconds and so on. In short, I would like an infinite loop that can only be interrupted by cancelling the script from running. I am unsure of how to tell Python to close the relay for 180 seconds and then re-run the try statement, or how to make it an infinite loop for that matter.
I'd really appreciate some input from the community. Any feedback or assistance is greatly appreciated. Thanks All.
Just use a while True loop, something like:
# main loop
while True:
GPIO.output(14, GPIO.LOW)
print "open"
time.sleep(SleepTimeL);
GPIO.cleanup()
print "done"
I agree with reptilicus, you just need to add a while loop. "while True" will run forever, until you hit ctrl-C to break. You just need to add a second delay to hold the relay off for 180 seconds before looping. You can create a different sleep time variable, or I just multiply the one you have by 2.
# main loop
while True:
try:
GPIO.output(14, GPIO.LOW)
print "open"
time.sleep(SleepTimeL);
GPIO.cleanup()
#Reset GPIO settings
GPIO.cleanup()
time.sleep(2*SleepTimeL)
# end program cleanly
except KeyboardInterrupt:
print "done"
I'm using a Raspberry Pi 2 and a breadboard to make a morse code interpreter. The circuit is a simple button that lights up an LED when pressed. How could I use functions to count how long the button is held down?
You haven't given sufficient details of your circuit to pin this down to your particular use case, so I'll suggest the following (on which I'll base my code):
Connect the LED (with series resistor) to GPIO 12
Connect a 10k resistor between GPIO 11 and the 3.3V rail (acts as a pull-up)
Connect the push-button between GPIO 11 and Ground (0V).
I'd then write the code to monitor the pin and log the time for each press into a list. You can read out the values in the same order which allows you to process the times and interpret the code from them.
import RPi.GPIO as GPIO
import time
# set up an empty list for the key presses
presses = []
# set up the GPIO pins to register the presses and control the LED
GPIO.setmode(GPIO.BOARD)
GPIO.setup(12, GPIO.OUT)
GPIO.setup(11, GPIO.IN)
# turn LED off initially
GPIO.output(12, False)
while True:
# wait for input to go 'low'
input_value = GPIO.input(11)
if not input_value:
# log start time and light the LED
start_time = time.time()
GPIO.output(12, True)
# wait for input to go high again
while not input_value:
input_value = GPIO.input(11)
else:
# log the time the button is un-pressed, and extinguish LED
end_time = time.time()
GPIO.output(12, False)
# store the press times in the list, as a dictionary object
presses.append({'start':start_time, 'end':end_time})
You'll finish up with a list that looks something like this:
[{start:123234234.34534, end:123234240.23482}, {start:123234289.96841, end:123234333.12345}]
The numbers you see here are in units of seconds (this is your system time, which is measured in seconds since the epoch).
You can then use a for loop to run through each item in the list, subtract each end time from the start time, and of course subtract the start of the next press from the end of the previous one, so that you can assemble characters and words based on the gaps between presses. Have fun :-)