Python 树莓派上 GPIO 的回调问题
Python callback issue with GPIO on raspberry
我绝对是 python 新手,这是我的第一个覆盆子项目。我尝试构建一个简单的音乐播放器,其中每个输入按钮加载不同的专辑(8 张专辑)和 3 个按钮来控制播放(下一个、暂停、上一个)。
为了加载音乐,我使用 USB 驱动器,连接后会自动触发复制过程。
按钮使用回调函数去抖动。一切都很好,除了用 USB 驱动器加载新音乐后,按钮不再起作用。
这很可能是一个简单的编程问题,作为初学者,我只是看不到。
这是使用两个按钮的代码:
#!/usr/bin/env python
import RPi.GPIO as GPIO
import os
import pyudev
from time import sleep
from mpd import MPDClient
from socket import error as SocketError
# Configure MPD connection settings
HOST = 'localhost'
PORT = '6600'
CON_ID = {'host':HOST, 'port':PORT}
#Configure Buttons
Button1 = 25
Button2 = 24
GPIO.setmode(GPIO.BCM)
GPIO.setup(Button1, GPIO.IN)
GPIO.setup(Button2, GPIO.IN)
client = MPDClient()
#Function to check if USB is connected
def checkForUSBDevice(name):
res = ""
context = pyudev.Context()
for device in context.list_devices(subsystem='block', DEVTYPE='partition'):
if device.get('ID_FS_LABEL') == name:
res = device.device_node
return res
#Function to load music from USB
def loadMusic(client, con_id, device):
os.system("mount "+device+" /music/usb")
os.system("/etc/init.d/mpd stop")
os.system("rm -r /music/mp3/*")
os.system("cp -r /music/usb/* /music/mp3/")
os.system("umount /music/usb")
os.system("rm /music/mpd/tag_cache")
os.system("/etc/init.d/mpd start")
os.system("mpc clear")
os.system("mpc ls | mpc add")
os.system("/etc/init.d/mpd restart")
#Function to connect to MPD
def mpdConnect(client, con_id):
try:
client.connect(**con_id)
except SocketError:
return False
return True
#Function to load an Album
def loadAlbum(number):
mpdConnect(client, CON_ID)
if client.status()["state"] == "play" or client.status()["state"] == "pause": client.stop()
os.system("mpc clear")
os.system("mpc ls "+str(number)+" | mpc add")
client.play()
client.disconnect()
#Callback Function
def buttonPressed(channel):
if channel == Button1:
print('Button 1 HIT')
loadAlbum(1)
elif channel == Button2:
print('Button 2 HIT')
loadAlbum(2)
def main():
GPIO.add_event_detect(Button1, GPIO.RISING, callback=buttonPressed, bouncetime=200)
GPIO.add_event_detect(Button2, GPIO.RISING, callback=buttonPressed, bouncetime=200)
# This function just creates an endless loop which does
# nothing, in order for the button detection to work
try:
flag = 0
while flag == 0:
device = checkForUSBDevice("MUSIC") # MUSIC is the name of my thumb drive
if flag == 1:
flag = 0
else:
flag = 0
if device != "":
# USB thumb drive has been inserted, new music will be copied
print('USB erkannt, Musik wird kopiert.', device)
loadMusic(client, CON_ID, device)
print('Musik wurde kopiert, USB kann entfernt werden!', device)
while checkForUSBDevice("MUSIC") == device:
sleep(1.0)
print('USB wurde entfernt.')
loadAlbum(1)
except KeyboardInterrupt:
GPIO.cleanup()
if __name__ == "__main__":
main()
希望有人能帮助我吗?
马蒂亚斯
这就是我的诀窍。可能这不是最好的解决方案,但它可以解决问题。
只改变了主要功能。更改在行的开头突出显示并带有注释。
def main():
GPIO.add_event_detect(Button1, GPIO.RISING, callback=buttonPressed, bouncetime=200)
GPIO.add_event_detect(Button2, GPIO.RISING, callback=buttonPressed, bouncetime=200)
# This function just creates an endless loop which does
# nothing, in order for the button detection to work
try:
flag = 0
while flag == 0:
device = checkForUSBDevice("MUSIC") # MUSIC is the name of my thumb drive
if flag == 1:
flag = 0
else:
flag = 0
if device != "":
# USB thumb drive has been inserted, new music will be copied
print('USB erkannt, Musik wird kopiert.', device)
# Stop the callback before loading the files from the USB:
GPIO.remove_event_detect(Button1)
GPIO.remove_event_detect(Button2)
loadMusic(client, CON_ID, device)
print('Musik wurde kopiert, USB kann entfernt werden!', device)
while checkForUSBDevice("MUSIC") == device:
sleep(1.0)
print('USB wurde entfernt.')
loadAlbum(1)
# Recall the main function
main()
except KeyboardInterrupt:
GPIO.cleanup()
按钮不再起作用的原因是因为您仍在回调函数中 - 所以它无法再次触发。解决方案是使用回调函数简单地设置一个标志,让主等待循环检测标志并进行播放。但请注意,播放可能会阻塞,因此主循环也会在此期间停止。
我绝对是 python 新手,这是我的第一个覆盆子项目。我尝试构建一个简单的音乐播放器,其中每个输入按钮加载不同的专辑(8 张专辑)和 3 个按钮来控制播放(下一个、暂停、上一个)。
为了加载音乐,我使用 USB 驱动器,连接后会自动触发复制过程。
按钮使用回调函数去抖动。一切都很好,除了用 USB 驱动器加载新音乐后,按钮不再起作用。
这很可能是一个简单的编程问题,作为初学者,我只是看不到。
这是使用两个按钮的代码:
#!/usr/bin/env python
import RPi.GPIO as GPIO
import os
import pyudev
from time import sleep
from mpd import MPDClient
from socket import error as SocketError
# Configure MPD connection settings
HOST = 'localhost'
PORT = '6600'
CON_ID = {'host':HOST, 'port':PORT}
#Configure Buttons
Button1 = 25
Button2 = 24
GPIO.setmode(GPIO.BCM)
GPIO.setup(Button1, GPIO.IN)
GPIO.setup(Button2, GPIO.IN)
client = MPDClient()
#Function to check if USB is connected
def checkForUSBDevice(name):
res = ""
context = pyudev.Context()
for device in context.list_devices(subsystem='block', DEVTYPE='partition'):
if device.get('ID_FS_LABEL') == name:
res = device.device_node
return res
#Function to load music from USB
def loadMusic(client, con_id, device):
os.system("mount "+device+" /music/usb")
os.system("/etc/init.d/mpd stop")
os.system("rm -r /music/mp3/*")
os.system("cp -r /music/usb/* /music/mp3/")
os.system("umount /music/usb")
os.system("rm /music/mpd/tag_cache")
os.system("/etc/init.d/mpd start")
os.system("mpc clear")
os.system("mpc ls | mpc add")
os.system("/etc/init.d/mpd restart")
#Function to connect to MPD
def mpdConnect(client, con_id):
try:
client.connect(**con_id)
except SocketError:
return False
return True
#Function to load an Album
def loadAlbum(number):
mpdConnect(client, CON_ID)
if client.status()["state"] == "play" or client.status()["state"] == "pause": client.stop()
os.system("mpc clear")
os.system("mpc ls "+str(number)+" | mpc add")
client.play()
client.disconnect()
#Callback Function
def buttonPressed(channel):
if channel == Button1:
print('Button 1 HIT')
loadAlbum(1)
elif channel == Button2:
print('Button 2 HIT')
loadAlbum(2)
def main():
GPIO.add_event_detect(Button1, GPIO.RISING, callback=buttonPressed, bouncetime=200)
GPIO.add_event_detect(Button2, GPIO.RISING, callback=buttonPressed, bouncetime=200)
# This function just creates an endless loop which does
# nothing, in order for the button detection to work
try:
flag = 0
while flag == 0:
device = checkForUSBDevice("MUSIC") # MUSIC is the name of my thumb drive
if flag == 1:
flag = 0
else:
flag = 0
if device != "":
# USB thumb drive has been inserted, new music will be copied
print('USB erkannt, Musik wird kopiert.', device)
loadMusic(client, CON_ID, device)
print('Musik wurde kopiert, USB kann entfernt werden!', device)
while checkForUSBDevice("MUSIC") == device:
sleep(1.0)
print('USB wurde entfernt.')
loadAlbum(1)
except KeyboardInterrupt:
GPIO.cleanup()
if __name__ == "__main__":
main()
希望有人能帮助我吗?
马蒂亚斯
这就是我的诀窍。可能这不是最好的解决方案,但它可以解决问题。 只改变了主要功能。更改在行的开头突出显示并带有注释。
def main():
GPIO.add_event_detect(Button1, GPIO.RISING, callback=buttonPressed, bouncetime=200)
GPIO.add_event_detect(Button2, GPIO.RISING, callback=buttonPressed, bouncetime=200)
# This function just creates an endless loop which does
# nothing, in order for the button detection to work
try:
flag = 0
while flag == 0:
device = checkForUSBDevice("MUSIC") # MUSIC is the name of my thumb drive
if flag == 1:
flag = 0
else:
flag = 0
if device != "":
# USB thumb drive has been inserted, new music will be copied
print('USB erkannt, Musik wird kopiert.', device)
# Stop the callback before loading the files from the USB:
GPIO.remove_event_detect(Button1)
GPIO.remove_event_detect(Button2)
loadMusic(client, CON_ID, device)
print('Musik wurde kopiert, USB kann entfernt werden!', device)
while checkForUSBDevice("MUSIC") == device:
sleep(1.0)
print('USB wurde entfernt.')
loadAlbum(1)
# Recall the main function
main()
except KeyboardInterrupt:
GPIO.cleanup()
按钮不再起作用的原因是因为您仍在回调函数中 - 所以它无法再次触发。解决方案是使用回调函数简单地设置一个标志,让主等待循环检测标志并进行播放。但请注意,播放可能会阻塞,因此主循环也会在此期间停止。