You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

树莓派3 Reed开关控制外设:PyGame音频循环异常修复问询

问题解决:树莓派磁簧开关控制音频与继电器

问题描述

使用树莓派3,配置磁簧开关(引脚18)、香薰机(Ch1继电器,引脚26)、迪斯科球(Ch2继电器,引脚20)。需求如下:

  • 磁簧开关状态为True时:停止音频播放,触发香薰机出香、迪斯科球旋转发光
  • 磁簧开关状态为False时:从头开始不间断播放音频(直到开关变为True),同时关闭香薰机和迪斯科球

当前代码存在音频与sleep()同步循环的问题,无法实现连续播放。

问题分析

原代码的核心问题:

  • 每次检测到开关为False时,都会重复调用pygame.mixer.music.play(),强制音频从头重启,配合sleep(1)导致音频每1秒循环一次
  • sleep(1)阻塞主循环,导致开关状态的响应延迟
  • 未判断音频当前播放状态,重复触发播放命令造成无效操作

修改后的代码

import RPi.GPIO as GPIO
import pygame
from time import sleep

# 初始化音频模块
pygame.mixer.init()
pygame.mixer.music.load("/home/sean/Downloads/song.mp3")
audio_playing = False  # 跟踪音频播放状态

# GPIO配置初始化
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:
        switch_state = GPIO.input(18)
        
        if switch_state:
            # 开关触发:停止音频,启动外设
            if pygame.mixer.music.get_busy():
                pygame.mixer.music.stop()
                audio_playing = False
            GPIO.output(26, 1)
            GPIO.output(20, 1)
        else:
            # 开关未触发:关闭外设,播放音频(仅当未播放时从头启动)
            GPIO.output(26, 0)
            GPIO.output(20, 0)
            if not audio_playing:
                pygame.mixer.music.play(-1)  # -1参数实现音频循环播放
                audio_playing = True
            # 短延时降低CPU占用,同时保证状态检测灵敏度
            sleep(0.1)
            
except KeyboardInterrupt:
    # 中断时清理资源
    pygame.mixer.music.stop()
    GPIO.cleanup()

关键改动说明

  1. 添加播放状态跟踪:用audio_playing变量记录音频状态,避免重复触发play()导致音频频繁重启
  2. 设置循环播放:调用play(-1)让音频持续循环,直到被主动停止
  3. 优化延时逻辑:将sleep(1)改为sleep(0.1),既减少CPU占用,又保证开关状态检测的及时性
  4. 统一状态读取:单次读取开关状态后再进行分支判断,避免重复读取导致的状态不一致
  5. 无效操作过滤:仅当音频正在播放时才调用stop(),减少不必要的系统调用

内容的提问来源于stack exchange,提问作者Sean

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 15:55:20