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

树莓派3B+多GPIO输入输出扩展:Python脚本优化问询

多GPIO按键监控与继电器控制扩展方案

需求说明

希望在Raspberry Pi 3B+上运行Python脚本,监控多个GPIO引脚的外部按键按下事件。当按键按下(短路至0伏)时,触发对应GPIO引脚控制Sainsmart继电器板瞬时动作,并发送告警邮件。目前已实现单输入单输出的功能,需要扩展多组GPIO输入输出,避免运行多个独立脚本。

优化后的多通道实现代码

import RPi.GPIO as GPIO
import time
import smtplib
from email.mime.text import MIMEText

# 配置参数:输入GPIO -> 对应输出GPIO、告警描述
GPIO_CONFIG = {
    17: {"output_pin": 2, "alert_msg": "按键1(GPIO17)被按下,继电器(GPIO2)触发"},
    27: {"output_pin": 3, "alert_msg": "按键2(GPIO27)被按下,继电器(GPIO3)触发"},
    22: {"output_pin": 4, "alert_msg": "按键3(GPIO22)被按下,继电器(GPIO4)触发"}
}

# 邮件配置
EMAIL_SETTINGS = {
    "smtp_server": "server.com",
    "smtp_port": 587,
    "sender": "user@server.com",
    "password": "passwordhere",
    "recipients": ["recip1@domain1.com", "recip2@domain2.com"]
}

def send_alert_email(subject, content):
    """封装告警邮件发送函数"""
    msg = MIMEText(content, "plain", "utf-8")
    msg["Subject"] = "GPIO告警通知"
    msg["From"] = EMAIL_SETTINGS["sender"]
    msg["To"] = ", ".join(EMAIL_SETTINGS["recipients"])
    
    try:
        smtp = smtplib.SMTP(EMAIL_SETTINGS["smtp_server"], EMAIL_SETTINGS["smtp_port"])
        smtp.ehlo()
        smtp.starttls()
        smtp.login(EMAIL_SETTINGS["sender"], EMAIL_SETTINGS["password"])
        smtp.sendmail(EMAIL_SETTINGS["sender"], EMAIL_SETTINGS["recipients"], msg.as_string())
        smtp.quit()
        print("告警邮件发送成功")
    except Exception as e:
        print(f"邮件发送失败: {str(e)}")

def init_gpio():
    """初始化所有GPIO引脚"""
    GPIO.setmode(GPIO.BCM)
    GPIO.setwarnings(False)
    
    # 配置输入引脚(上拉电阻)
    for input_pin in GPIO_CONFIG.keys():
        GPIO.setup(input_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
    
    # 配置输出引脚,初始高电平(继电器默认断开)
    for config in GPIO_CONFIG.values():
        output_pin = config["output_pin"]
        GPIO.setup(output_pin, GPIO.OUT)
        GPIO.output(output_pin, GPIO.HIGH)

def main():
    init_gpio()
    # 记录按键上次触发时间,用于防抖
    last_trigger_time = {pin: 0 for pin in GPIO_CONFIG.keys()}
    DEBOUNCE_DELAY = 2  # 防抖延迟,单位秒
    
    try:
        while True:
            current_time = time.time()
            for input_pin, config in GPIO_CONFIG.items():
                input_state = GPIO.input(input_pin)
                # 按键按下(低电平),且超过防抖延迟
                if input_state == False and (current_time - last_trigger_time[input_pin]) > DEBOUNCE_DELAY:
                    output_pin = config["output_pin"]
                    alert_msg = config["alert_msg"]
                    
                    print(alert_msg)
                    # 触发继电器瞬时动作
                    GPIO.output(output_pin, GPIO.LOW)
                    print(f"继电器GPIO{output_pin}触发")
                    time.sleep(1.0)
                    GPIO.output(output_pin, GPIO.HIGH)
                    time.sleep(0.5)
                    
                    # 发送告警邮件
                    send_alert_email("GPIO按键触发", alert_msg)
                    
                    # 更新最后触发时间
                    last_trigger_time[input_pin] = current_time
                    
            time.sleep(0.1)  # 降低循环频率,减少CPU占用
    except KeyboardInterrupt:
        print("程序终止,清理GPIO资源")
        GPIO.cleanup()

if __name__ == "__main__":
    main()

关键修改说明

  • 配置化管理GPIO映射:用GPIO_CONFIG字典统一管理输入引脚、对应输出引脚和告警信息,新增通道只需在字典中添加条目,无需修改核心逻辑。
  • 封装邮件发送函数:将邮件发送逻辑封装为send_alert_email,避免重复代码,同时优化邮件格式(使用MIMEText支持中文和主题)。
  • 按键防抖处理:通过记录每次触发的时间,设置DEBOUNCE_DELAY避免按键抖动导致的重复触发。
  • 结构化代码:将GPIO初始化、主循环、邮件发送拆分为独立函数,代码更易读和维护。
  • 异常处理:捕获KeyboardInterrupt(Ctrl+C),确保程序终止时正确清理GPIO资源。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 05:27:32