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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 21:27:25