Reputation: 43
I have a Rpi 3 with:
Magnetic Reed switch (pin 18) Oil Diffuser Ch1 relay hat Disco Ball Ch2 relay hat
I am trying to trigger the diffuser, and disco ball with the reed switch to start diffusing good smells while the disco ball spins and lights up.
The diffuser and ball are working perfectly, however when I play the mp3 with pygame it seems to loop the song in sync with sleep. I want the song to play uninterrupted until the reed switch is TRUE and play from beginning when it's false.
import RPi.GPIO as GPIO
import pygame
from time import sleep
pygame.mixer.init()
pygame.mixer.music.load("/home/sean/Downloads/song.mp3")
pygame.mixer.music.play()
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(26, GPIO.OUT)
GPIO.setup(20, GPIO.OUT)
try:
while (True):
if GPIO.input(18):
pygame.mixer.music.stop()
GPIO.output(26, 1)
GPIO.output(20, 1)
elif GPIO.input(18) == False:
pygame.mixer.music.play()
GPIO.output(26, 0)
GPIO.output(20, 0)
sleep(1)
except KeyboardInterrupt:
pygame.mixer.music.stop()
GPIO.cleanup()
Upvotes: 1
Views: 158
Reputation: 14924
pygame.mixer.music.play()
instructs the mixer to begin playing the audio. So what you're experiencing seems to match exactly what one would expect. Everytime .play()
is called, it starts again.
A nice way to do this is to use a threaded function to monitor the GPIO I/Os, and then send messages to the PyGame event loop. You do need to service the event loop, otherwise your program will be considered to be "not responding".
import pygame
import threading
import RPi.GPIO as GPIO
# Window size
WINDOW_WIDTH = 400
WINDOW_HEIGHT = 400
BLACK = ( 0, 0, 0)
GREEN = ( 0, 255, 0)
# custom event-loop events
MUSIC_ON_EVENT = pygame.USEREVENT + 1
MUSIC_OFF_EVENT = pygame.USEREVENT + 2
def GPIOHandlerThread():
global running
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(26, GPIO.OUT)
GPIO.setup(20, GPIO.OUT)
while ( running ):
gpio_18 = GPIO.input(18)
if ( gpio_18 ):
pygame.event.post( pygame.event.Event( MUSIC_OFF_EVENT ) )
GPIO.output(26, 1)
GPIO.output(20, 1)
else:
pygame.event.post( pygame.event.Event( MUSIC_ON_EVENT ) )
GPIO.output(26, 0)
GPIO.output(20, 0)
time.sleep( 0.5 ) # save some electricity
###
### MAIN
###
pygame.init()
window = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ), pygame.HWSURFACE )
pygame.display.set_caption("GPIO Events")
# Load some music
pygame.mixer.init()
pygame.mixer.music.load("/home/sean/Downloads/song.mp3")
# start a thread to handle GPIO events
gpio_thread = threading.Thread( target=GPIOHandlerThread, args=())
gpio_thread.start()
# Main loop
music_playing = False
clock = pygame.time.Clock()
running = True
while running:
# Handle user-input
for event in pygame.event.get():
if ( event.type == pygame.QUIT ):
running = False
elif ( event.type == MUSIC_ON_EVENT ):
# Start the music, if necessary
if ( not music_playing ):
pygame.mixer.music.play(-1) # start playback, but loop continuously
music_playing = True
elif ( event.type == MUSIC_OFF_EVENT ):
# Stop the music, if playing already
if ( music_playing ):
pygame.mixer.music.stop()
music_playing = False
# Paint the screen in a gradient centred about the mouse
if ( music_playing ):
window.fill( GREEN )
else:
window.fill( BLACK )
# TODO: Maybe draw kind of GUI, status etc.
pygame.display.flip()
# Clamp FPS
clock.tick(3) # slow update
pygame.quit()
This code has not been tested, errors should be expected.
Upvotes: 1