Python实现变量值变化时仅单次触发事件(树莓派门磁场景)
英语并非我的母语,文中可能存在语法错误,敬请谅解。
我是编程新手,此前几乎没有接触过Python,日常主要编写JavaScript和PowerShell脚本,目前对Python语法还不熟悉。我搜索过相关问题,但已有的解答过于晦涩,且多绑定特定业务场景,很难理解参考。
我当前想要实现一个简易门磁传感器功能:使用树莓派读取GPIO引脚状态,当引脚被拉至接地(状态值0)时传感器触发,对应门为关闭状态;当引脚状态值为1时传感器未触发,对应门为打开状态。
我最初编写的代码可以检测引脚状态,但会在终端循环重复打印“门已打开”或“门已关闭”提示,直到程序停止;对接Telegram机器人后,程序会在门状态不变时重复发送相同的提示消息。
我最初编写的代码如下:
import RPi.GPIO as GPIO from time import sleep import telegram_send GPIO.setmode(GPIO.BCM) #sensor is connected to pin 21 sensor=21 #pull the sensor to 3.3v when not engaged GPIO.setup(sensor,GPIO.IN,pull_up_down=GPIO.PUD_UP) #send the message while(1): if GPIO.input(sensor)==1: print("The door is open") telegram_send.send(messages=["The door is open!"]) sleep(1) elif GPIO.input(sensor)==0: print("The door is closed") telegram_send.send(messages=["The door is closed!"]) sleep(1)
我的思路是每秒将传感器状态存入变量,仅当变量值发生变化时触发机器人发送一次消息。我原本以为需要两个循环,一个负责更新变量值,一个负责校验变量值、在满足条件时单次发送消息,但我始终不知道如何对比变量的当前状态和1秒前的历史状态。
我尝试编写代码后未能实现功能,搜索相关解答后反而更加困惑,YouTube上的相关教程也没有给出具体实现代码,我目前写出的半成品代码如下:
import RPi.GPIO as GPIO from time import sleep import telegram_send GPIO.setmode(GPIO.BCM) #sensor is connected to pin 21 sensor=21 #pull the sensor to 3.3v when not engaged GPIO.setup(sensor,GPIO.IN,pull_up_down=GPIO.PUD_UP) #store the status of the GPIO pin while True: status=GPIO.input(sensor) #check the status of the pin if status==0: print("Door is closed!") elif status==1: print("Door is open!")
我对家居自动化项目非常感兴趣,希望能得到大家的帮助,学习相关实现方法。
解决方案
# 导入所需依赖库 from time import sleep import RPi.GPIO as GPIO import telegram_send sensor = 21 # 传感器连接至GPIO21号引脚 OPEN_DOOR = 1 # 传感器返回值为1时对应门打开状态 CLOSED_DOOR = 0 # 传感器返回值为0时对应门关闭状态 DOOR_LAST_STATE = -1 if __name__ == '__main__': # 设置GPIO编号模式为BCM GPIO.setmode(GPIO.BCM) # 传感器未触发时上拉至3.3V,触发时会被拉至接地 GPIO.setup(sensor,GPIO.IN,pull_up_down=GPIO.PUD_UP) # 读取门当前状态作为初始基准状态 DOOR_LAST_STATE = GPIO.input(sensor) # 主事件循环 # ------------------------------------------------------------------------ print("程序启动!") while True: curr_state = GPIO.input(sensor) if curr_state == OPEN_DOOR: # 当前检测到门为打开状态 if DOOR_LAST_STATE == CLOSED_DOOR: # 上一次记录的状态为关闭 print("门已打开") telegram_send.send(messages=["The door is open!"]) DOOR_LAST_STATE = OPEN_DOOR # 更新历史状态为打开 elif DOOR_LAST_STATE == OPEN_DOOR: # 历史状态与当前状态一致,均为打开 print("门保持打开状态") # 不执行重复通知操作 else: print("门状态未知") elif curr_state == CLOSED_DOOR: # 当前检测到门为关闭状态 if DOOR_LAST_STATE == OPEN_DOOR: # 上一次记录的状态为打开 print("门已关闭") telegram_send.send(messages=["The door is closed!"]) DOOR_LAST_STATE = CLOSED_DOOR # 更新历史状态为关闭 elif DOOR_LAST_STATE == CLOSED_DOOR: # 历史状态与当前状态一致,均为关闭 print("门保持关闭状态") # 不执行重复通知操作 else: print("门状态未知") else: print("门状态未知") sleep(1) # 循环末尾固定休眠1秒,降低CPU占用 # ------------------------------------------------------------------------ # 循环结束
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

