关于关闭PIR运动传感器检测功能的技术咨询
解决PIR传感器撤防后仍触发检测的问题
看起来你现在的核心困扰是撤防后PIR传感器还在持续检测并触发报警,代码里有几个关键逻辑错误导致功能失效,咱们一步步来修复:
先理清核心问题
- 你写了两个完全重复的
disarmAlarm函数,后面的会直接覆盖前面的,导致撤防逻辑混乱; pir_off函数里的GPIO.input(11) == False只是做了一次状态比较,根本没有改变传感器的工作状态——GPIO输入是传感器的输出信号,你没法强行把它设为False,只能停止检测它的状态;- 你用
Clock.schedule_interval定时调用callback来检测PIR,但撤防时没有取消这个定时任务,所以它会一直后台运行,持续读取传感器状态,自然会触发报警。
具体修复步骤
1. 保存定时任务引用,方便启停
首先在类的初始化方法里添加一个变量,用来保存PIR检测定时任务的引用,后续取消任务时会用到:
def __init__(self, **kwargs): super().__init__(**kwargs) self.pir_detect_task = None # 存储PIR检测的定时任务
2. 修正armAlarm函数的定时任务逻辑
你原来的布防逻辑里,启动检测的条件搞反了(应该是布防时启动检测,撤防时停止),同时要把定时任务的引用保存下来:
def armAlarm(self): global Activated, Armed if self.txt_display.text == str(pincode): Clock.schedule_once(lambda dt: self.indicated(), 3) Armed = True Activated = False GPIO.output(22, 0) GPIO.output(18, 1) GPIO.output(16,1) time.sleep(0.5) GPIO.output(16,0) # 如果之前有未取消的任务,先清理 if self.pir_detect_task: Clock.unschedule(self.pir_detect_task) # 布防成功,启动PIR检测 self.pir_detect_task = Clock.schedule_interval(lambda dt: self.callback(), 0.5) elif self.txt_display.text != str(pincode): Armed = False Activated = False self.txt_display.text = '' self.info.text = '**Incorrect Pin**' self.info.background_color = [1, 1, 1, 1] Clock.schedule_once(lambda dt: self.reset_notice(), 3) self.info.background_color = [0, 1, 0, 1] # PIN错误,停止检测 if self.pir_detect_task: Clock.unschedule(self.pir_detect_task) self.pir_detect_task = None
3. 合并并修复disarmAlarm函数
把两个重复的disarmAlarm合并成一个,覆盖所有撤防场景:
def disarmAlarm(self): global Activated, Armed # 先验证PIN码是否正确 if self.txt_display.text != str(pincode): self.info.text = '**Incorrect Pin**' self.info.background_color = [1, 1, 1, 1] Clock.schedule_once(lambda dt: self.reset_notice(), 3) self.txt_display.text = '' return # PIN正确,执行撤防操作 Armed = False Activated = False self.info.text = 'Alarm disarmed' self.info.background_color = [0, 1, 0, 1] self.txt_display.text = '' # 关闭所有GPIO输出设备 GPIO.output(16,0) GPIO.output(22, 0) GPIO.output(18, 0) # 取消PIR检测的定时任务,彻底停止检测逻辑 if self.pir_detect_task: Clock.unschedule(self.pir_detect_task) self.pir_detect_task = None print('Alarm deactivated')
4. 移除无效函数
你的pir_off和reset_alarm函数逻辑完全无效,直接删掉即可——停止PIR检测的核心是取消定时任务,而不是试图修改GPIO输入状态。
关键逻辑说明
- 定时任务的启停:用
Clock.schedule_interval启动检测后,必须用Clock.unschedule传入任务引用来停止,否则它会每隔0.5秒自动调用callback读取PIR状态; - 全局变量一致性:确保
Armed和Activated的状态在布防/撤防时同步更新,避免逻辑冲突; - GPIO输入本质:PIR的GPIO输入是传感器的输出信号,你没法强行设置它的状态,只能停止读取这个信号的逻辑。
这样修改后,当你输入正确PIN码执行撤防时,定时任务会被彻底取消,callback不再被调用,自然就不会检测到PIR的状态变化,报警也就不会触发了。
内容的提问来源于stack exchange,提问作者user12358221
相关产品推荐
相关产品推荐

