繁体   English   中英

用超声波传感器和树莓派测量距离

[英]Measure distance with ultrasonic sensor and Raspberry

我正在尝试使用超声波传感器测量距离,一切看起来都很好,但是当我让程序工作几分钟(3-4 分钟)时,程序会停止距离测量。

我需要程序不要停止,因为我需要它发出安全警报。 该程序每隔一秒收集一次距离并将其显示在屏幕上。 但如果距离大于 10,程序会显示一条警告消息,直到距离小于 10 时才会显示。下面是代码:

import time
import RPi.GPIO as GPIO


# Usamos la referencia BOARD para los pines GPIO
GPIO.setmode(GPIO.BOARD)

# Definimos los pines que vamos a usar
GPIO_TRIGGER = 11
GPIO_ECHO = 13
GPIO_LED = 15

# Configuramos los pines como entradas y salidas
GPIO.setup(GPIO_TRIGGER,GPIO.OUT)  # Trigger
GPIO.setup(GPIO_ECHO,GPIO.IN)      # Echo
GPIO.setup(GPIO_LED ,GPIO.OUT) #Led


# -----------------------
# Definimos algunas funciones
# -----------------------

def medida():
  # Esta funcion mide una distancia
  GPIO.output(GPIO_TRIGGER, True)
  time.sleep(0.00001)
  GPIO.output(GPIO_TRIGGER, False)
  start = time.time()

  while GPIO.input(GPIO_ECHO)==0:
    start = time.time()

  while GPIO.input(GPIO_ECHO)==1:
    stop = time.time()

  elapsed = stop-start
  distancia = (elapsed * 34300)/2

  return distancia

def media_distancia():
  # Esta funcion recoge 3 medidas
  # y devuelve la media de las 3.
  distancia1=medida()
  time.sleep(0.1)
  distancia2=medida()
  time.sleep(0.1)
  distancia3=medida()
  distancia = distancia1 + distancia2 + distancia3
  distancia = distancia / 3
  return distancia


# -----------------------
# Programa principal
# -----------------------


print ("Medida con sensor de ultrasonidos")

# Ponemos el Trigger en falso (low)
GPIO.output(GPIO_TRIGGER, False)
# Ponemos el Led en falso (low)
GPIO.output(GPIO_LED, False)

# Metemos el bloque principal en un Try para asi poder
# comprobar si el usuario presiona Ctrl + C
# y poder ejecutar una limpieza del GPIO, esto tambien
# evita el usuario tener que ver muchos mensajes de error
try:
  while True: # Este bucle se repite siempre

# Lo primero que hago es medir la distancia
      distancia = media_distancia()
# Compruebo si la distancia es menor que 10
# Si es menor que 10 muestro la distancia por pantalla

      if distancia < 10:
        distancia = media_distancia() # Medidos la distancia 
        print ("Distancia: %.1f" % distancia, " - " , "Fecha:", time.strftime("%c")) # Mostramos la distancia por pantalla
        GPIO.output(GPIO_LED, False)
        time.sleep(1) # Esperamos 1 segundo
        distancia = media_distancia()
        a = 0 # Utilizo la variable a para poder para el proceso mas adelante

# Pregunto si la variable a es igual a 1
# Si lo es no hago nada y repito el if anterior
      if a == 1:
        pass
# Pero si no es 1 le asigno el valor 0
# Para poder seguir con el IF siguiente
      else: 
        a = 0
      if distancia > 10 and a == 0: # Si la distancia es mayor que 10cms
           print ("La distancia es mayor de 10 cms. Alarma activada!!", " - ", "Fecha:", time.strftime("%c")) # Se interrumpe el bucle y se muestra un aviso
           GPIO.output(GPIO_LED, True)  
           a = 1 # Pongo la variable en 1 para parar el proceso y que no se repita 
           distancia = media_distancia() # Seguimos midiento la distancia
           while distancia < 10: # Pero si la distancia vuelve a ser menor de 10
             break # Se termina este bucle y volvemos al principio nuevamente

except KeyboardInterrupt: # Si el usuario presiona crtl + C

  # Limpiamos los pines GPIO y salimos del programa

  print ("Apagando LED")
  time.sleep(1)
  GPIO.output(GPIO_LED, False)
  print ("Limpiando GPIO")
  GPIO.cleanup()
  print ("GPIO limpio")
  print ("Saliendo...")
  time.sleep(1)

为什么程序会在几分钟后停止?

在您的函数medida():中,您使用以下方法触发传感器:

GPIO.output(GPIO_TRIGGER, True)
time.sleep(0.00001)
GPIO.output(GPIO_TRIGGER, False)

然后等待ECHO设置为0开始计时最后等待ECHO设置为1停止计时

 while GPIO.input(GPIO_ECHO)==0:
    start = time.time()
 while GPIO.input(GPIO_ECHO)==1:
    stop = time.time()

现在假设这两个转换中的任何一个都没有发生:

  • 也许 ECHO 永远不会达到 1,因为根本没有返回 ECHO(没有物体,传感器的不当行为,错误连接......)
  • 或者,当您等待它变为 0 时,ECHO 可能已经为 1(您正在 TRIGGER 的上升沿之后执行 time.sleep(0.00001)。此时,在某些情况下,ECHO 可能已经变为 0 ...

如果发生这两件事中的任何一件,您的程序将永远等待,这可能就是正在发生的事情。 你应该在你的循环中包含一个超时,所以如果事情“挂起”你可以调用该函数再次触发传感器。

我最好的客人是您的代码某处有异常。 请尝试这个版本并添加输出示例:

import time
import RPi.GPIO as GPIO


# Usamos la referencia BOARD para los pines GPIO
GPIO.setmode(GPIO.BOARD)

# Definimos los pines que vamos a usar
GPIO_TRIGGER = 11
GPIO_ECHO = 13
GPIO_LED = 15

# Configuramos los pines como entradas y salidas
GPIO.setup(GPIO_TRIGGER,GPIO.OUT)  # Trigger
GPIO.setup(GPIO_ECHO,GPIO.IN)      # Echo
GPIO.setup(GPIO_LED ,GPIO.OUT) #Led


# -----------------------
# Definimos algunas funciones
# -----------------------

def medida():
  # Esta funcion mide una distancia
  GPIO.output(GPIO_TRIGGER, True)
  time.sleep(0.00001)
  GPIO.output(GPIO_TRIGGER, False)
  start = time.time()

  while GPIO.input(GPIO_ECHO)==0:
    start = time.time()

  while GPIO.input(GPIO_ECHO)==1:
    stop = time.time()

  elapsed = stop-start
  distancia = (elapsed * 34300)/2

  return distancia

def media_distancia():
  # Esta funcion recoge 3 medidas
  # y devuelve la media de las 3.
  distancia1=medida()
  time.sleep(0.1)
  distancia2=medida()
  time.sleep(0.1)
  distancia3=medida()
  distancia = distancia1 + distancia2 + distancia3
  distancia = distancia / 3
  return distancia


# -----------------------
# Programa principal
# -----------------------


print ("Medida con sensor de ultrasonidos")

# Ponemos el Trigger en falso (low)
GPIO.output(GPIO_TRIGGER, False)
# Ponemos el Led en falso (low)
GPIO.output(GPIO_LED, False)

# Metemos el bloque principal en un Try para asi poder
# comprobar si el usuario presiona Ctrl + C
# y poder ejecutar una limpieza del GPIO, esto tambien
# evita el usuario tener que ver muchos mensajes de error
continuar = True
while continuar: # Este bucle se repite siempre
  try:

  # Lo primero que hago es medir la distancia
        distancia = media_distancia()
  # Compruebo si la distancia es menor que 10
  # Si es menor que 10 muestro la distancia por pantalla

        if distancia < 10:
          distancia = media_distancia() # Medidos la distancia 
          print ("Distancia: %.1f" % distancia, " - " , "Fecha:", time.strftime("%c")) # Mostramos la distancia por pantalla
          GPIO.output(GPIO_LED, False)
          time.sleep(1) # Esperamos 1 segundo
          distancia = media_distancia()
          a = 0 # Utilizo la variable a para poder para el proceso mas adelante

  # Pregunto si la variable a es igual a 1
  # Si lo es no hago nada y repito el if anterior
        if a == 1:
          pass
  # Pero si no es 1 le asigno el valor 0
  # Para poder seguir con el IF siguiente
        else: 
          a = 0
        if distancia > 10 and a == 0: # Si la distancia es mayor que 10cms
             print ("La distancia es mayor de 10 cms. Alarma activada!!", " - ", "Fecha:", time.strftime("%c")) # Se interrumpe el bucle y se muestra un aviso
             GPIO.output(GPIO_LED, True)  
             a = 1 # Pongo la variable en 1 para parar el proceso y que no se repita 
             distancia = media_distancia() # Seguimos midiento la distancia
             while distancia < 10: # Pero si la distancia vuelve a ser menor de 10
               break # Se termina este bucle y volvemos al principio nuevamente

  except KeyboardInterrupt: # Si el usuario presiona crtl + C
    continuar = False

  except (Exception) as  error:
    print (str(error))

    # Limpiamos los pines GPIO y salimos del programa

  print ("Apagando LED")
  time.sleep(1)
  GPIO.output(GPIO_LED, False)
  print ("Limpiando GPIO")
  GPIO.cleanup()
  print ("GPIO limpio")
  print ("Saliendo...")
  time.sleep(1)

找到原因的正确方法很简单,使用记录器 没有黑匣子,你很难找到你的地方崩溃的原因!

python 有一个可以使用,查看文档

导入记录器模块:

import logging

配置它以创建一个文件...

logging.basicConfig(filename='example.log',level=logging.DEBUG)

并乞求登录你发现可疑的每个地方

logging.warning('Watch out!')  # will print a message to the console
logging.info('I told you so')  # will not print anything

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM