请求协助合并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
相关产品推荐
相关产品推荐

