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

树莓派Model B+超声波测距模块控制继电器故障排查求助

树莓派超声波检测传送带状态控制继电器的代码问题排查与修复

我帮你梳理下代码里的核心问题,再给你对应的修复方案和完整代码:

一、代码里的明显错误

  • GPIO引脚冲突:你把超声波的TRIG和继电器的RelayPin都设成了11号引脚!这会导致两个模块同时占用同一个GPIO,硬件直接冲突,肯定没法正常工作,必须给其中一个换个空闲引脚。
  • 语法与变量名错误:
    • 循环里你定义了dis12 = distance(),但判断的时候写成了if dis = dis2——首先变量名写错了(dis12 vs dis2),其次Python里判断相等要用==,单等号是赋值,这行代码会直接抛出语法错误。
  • 逻辑不符合需求:你的需求是“距离保持不变持续5秒”才关闭继电器,但当前代码只是间隔5秒测两次距离就判断相等,这太粗糙了——比如传送带只是短暂停顿一下,5秒后又动了,也会触发,而且两次测量相等也不代表中间的5秒距离都没变。
  • 超声波测距函数的计时问题:原distance函数里的time1和time2是在while循环内部赋值,每次循环都会覆盖,这样计算出的时间差是错的,应该在ECHO引脚状态变化的瞬间记录时间。

二、修正后的完整代码

#!/usr/bin/env python
import RPi.GPIO as GPIO
import time

# 修正引脚冲突,给继电器换个空闲引脚
TRIG = 11
ECHO = 12
RelayPin = 13  # 换成空闲的13号引脚,避免和TRIG冲突

def setup():
    GPIO.setmode(GPIO.BOARD)
    GPIO.setup(TRIG, GPIO.OUT)
    GPIO.setup(ECHO, GPIO.IN)
    GPIO.setup(RelayPin, GPIO.OUT)
    GPIO.output(RelayPin, GPIO.HIGH)  # 初始继电器保持工作状态(默认HIGH为吸合)

def distance():
    GPIO.output(TRIG, 0)
    time.sleep(0.000002)
    GPIO.output(TRIG, 1)
    time.sleep(0.00001)
    GPIO.output(TRIG, 0)
    
    # 修正计时逻辑:等待ECHO变高时开始计时
    while GPIO.input(ECHO) == 0:
        pass  # 等待ECHO触发信号
    time1 = time.time()
    
    # 等待ECHO变低时结束计时
    while GPIO.input(ECHO) == 1:
        pass
    time2 = time.time()
    
    during = time2 - time1
    return during * 340 / 2 * 100  # 转换为厘米单位

def loop():
    stable_start_time = None  # 记录距离开始稳定的时间点
    last_distance = None  # 记录上一次的测量距离
    tolerance = 1  # 允许的距离误差(厘米),避免超声波微小波动误判
    
    while True:
        current_dis = distance()
        print("%.2f cm" % current_dis)  # Python2格式,Python3可改成f"{current_dis:.2f} cm"
        
        # 判断当前距离是否和上次测量值在误差范围内
        if last_distance is not None and abs(current_dis - last_distance) <= tolerance:
            # 距离稳定,开始计时或持续计时
            if stable_start_time is None:
                stable_start_time = time.time()
            else:
                # 检查稳定时长是否达到5秒
                if time.time() - stable_start_time >= 5:
                    print("传送带已停止,关闭继电器")
                    GPIO.output(RelayPin, GPIO.LOW)
        else:
            # 距离发生变化,重置计时并恢复继电器工作
            stable_start_time = None
            GPIO.output(RelayPin, GPIO.HIGH)
        
        last_distance = current_dis
        time.sleep(0.1)  # 缩短采样间隔,提升监测精准度

def destroy():
    GPIO.output(RelayPin, GPIO.HIGH)
    GPIO.cleanup()  # 释放GPIO资源

if __name__ == '__main__':
    setup()
    try:
        loop()
    except KeyboardInterrupt:
        destroy()

三、关键修改说明

  1. 引脚冲突修复:把继电器引脚换成了13号,你可以根据自己GPIO扩展板的空闲引脚调整,只要不和TRIG/ECHO重复就行。
  2. 超声波计时逻辑修正:现在会在ECHO引脚刚变高时记录开始时间,刚变低时记录结束时间,计算出的距离更准确。
  3. 符合需求的稳定检测逻辑:
    • 增加了误差容忍度,避免超声波的微小波动导致误判。
    • 用stable_start_time持续记录距离稳定的时长,只有当稳定状态持续满5秒时,才关闭继电器。
    • 如果距离重新开始变化,会立即重置计时并恢复继电器的工作状态。
  4. 语法与细节优化:修正了判断相等的语法错误、变量名错误,同时优化了采样间隔和打印格式。

内容的提问来源于stack exchange,提问作者ryan tea

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 09:05:45