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

请求协助合并PIR传感器与按钮控制的Python脚本

嘿,我来帮你搞定这个脚本合并的问题!你的核心需求是让PIR传感器默认控制灯光,但按下按钮后要强制开灯15分钟,期间忽略PIR的检测对吧?原来的问题出在两个脚本各自独立运行,按钮按下后只是临时开灯,但PIR的检测逻辑还在跑,没检测到移动就立刻关灯了。咱们可以通过引入一个状态变量来管理优先级,下面是整理好的合并脚本,还有详细的解释:

合并后的完整脚本

首先,先统一GPIO模式(注意:我这里把两个脚本的GPIO模式统一成了BCM,如果你原来的接线是用BOARD模式的话,记得对应调整引脚号!比如原来PIR接的BOARD引脚4对应BCM的2,按钮BCM18对应BOARD的12,你可以根据实际接线修改):

import RPi.GPIO as GPIO
import time

# 配置引脚(根据你的实际接线调整!)
PIR_PIN = 2  # 对应原来BOARD模式的引脚4
BUTTON_PIN = 18
FORCE_ON_DURATION = 15 * 60  # 15分钟,单位秒

# GPIO初始化
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(PIR_PIN, GPIO.IN)
# 按钮设置上拉电阻,按下时为低电平
GPIO.setup(BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)

# 状态变量:记录强制开灯的结束时间,初始为0表示未强制
force_light_on_end_time = 0
# 记录当前灯光状态,避免重复执行开关灯脚本
current_light_state = False

def turn_lights_on():
    global current_light_state
    if not current_light_state:
        print("Turning lights ON")
        # 替换成你原来的开灯逻辑,这里用exec读取文件,建议改成函数导入更安全
        exec(open("./LightsOn.py").read(), globals())
        current_light_state = True

def turn_lights_off():
    global current_light_state
    if current_light_state:
        print("Turning lights OFF")
        exec(open("./LightsOff.py").read(), globals())
        current_light_state = False

try:
    while True:
        # 先处理按钮输入(优先级更高)
        button_state = GPIO.input(BUTTON_PIN)
        if button_state == False:
            print("Button pressed - forcing lights ON for 15 minutes")
            # 设置强制开灯结束时间
            force_light_on_end_time = time.time() + FORCE_ON_DURATION
            turn_lights_on()
            # 防抖,避免重复触发
            time.sleep(0.2)
        
        # 检查是否处于强制开灯阶段
        current_time = time.time()
        if current_time < force_light_on_end_time:
            # 强制开灯中,保持灯亮
            turn_lights_on()
        else:
            # 回到PIR控制逻辑
            pir_state = GPIO.input(PIR_PIN)
            if pir_state == 1:
                print("Movement detected - turning lights ON")
                turn_lights_on()
                # PIR检测到移动后,保持灯亮15分钟(和按钮时长一致)
                time.sleep(FORCE_ON_DURATION)
            else:
                print("No movement detected - turning lights OFF")
                turn_lights_off()
        
        # 小延迟,避免循环太占用CPU
        time.sleep(0.1)

finally:
    # 程序退出时清理GPIO
    GPIO.cleanup()
    print("GPIO cleaned up")
关键改进点说明
  • 统一GPIO模式:原来两个脚本一个用BOARD一个用BCM,会导致引脚混乱,现在统一成BCM(你可以根据实际接线改成BOARD,记得对应修改引脚号)
  • 状态变量管理:用force_light_on_end_time记录强制开灯的结束时间,只要当前时间小于这个值,就忽略PIR的检测,保持灯亮
  • 避免重复操作:用current_light_state记录当前灯光状态,避免反复执行开关灯脚本,减少不必要的操作
  • 优先级处理:主循环里先检查按钮状态,确保按钮操作优先于PIR检测
  • GPIO清理:用try...finally块保证程序退出时自动清理GPIO,避免引脚异常
额外建议

如果可以的话,建议把LightsOn.py和LightsOff.py里的代码封装成函数,比如在LightsOn.py里写:

def turn_on():
    # 原来的开灯代码,比如控制继电器之类的

然后在主脚本里用from LightsOn import turn_on来调用,比用exec读取文件更安全、更易维护。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:00:06