Detalle de las conexiones del sensor. Cable rojo: Vcc (5 V). Cable amarillo: Trig. Cable verde: Echo. Cable negro: Gnd (0 V)

Controla un sensor de proximidad desde tu Raspberry Pi

En este artículo vamos a jugar con un componente muy sencillo: el sensor de proximidad HC-SR04. Es este componente de aquí:

Sensor HC-SR04 de proximidad por ultrasonidos
Sensor HC-SR04 de proximidad por ultrasonidos

Seguro que, si os interesa el mundillo del cacharreo y el prototipado, os suena porque parecen unos ojos. En cierto modo lo son, ya que gracias a él nuestra Raspberry Pi puede detectar objetos en su proximidad, y ofrecer a nuestros programas la distancia a la que se encuentra el componente detectado.

Su principio de funcionamiento es el del SONAR, y es el que usan los murciélagos para detectar obstáculos y presas. Por uno de los “ojos”, el que está marcado como T de transmisor, nuestro sensor emitirá ultrasonidos cuyo eco, fruto del rebote con un obstáculo, captará con el que aparece rotulado con una R, de receptor. Al recibir ese eco, nuestro sensor emitirá una señal eléctrica a través del pin etiquetado como Echo que, correctamente interpretada, nos ofrecerá la distancia al obstáculo.

En este artículo vamos a configurarlo para imprimir por pantalla las distancias al objeto más cercano, a través de un programa en Python.

Acerca del HC-SR04

Este sensor se encuentra disponible a un precio muy asequible en Amazon España (enlace de afiliado), aunque como en todo lo de Amazon los precios fluctúan según la demanda. Su funcionamiento está basado en ultrasonidos y funciona con una corriente de 15 mA y unos niveles de tensión de alimentación y referencia de 5 V, en contraposición a la tensión de referencia que utiliza la Raspberry Pi, es de 3,3 V. A priori, esto es un problema que se puede resolver usando sabiamente nuestros conocimientos de circuitos eléctricos y resistores, como veremos.

Tiene 4 terminales, a saber:

  • Vcc, que es el terminal de alimentación al que deberemos conectar un voltaje continuo de 5 V.
  • Trig, de trigger (gatillo, o disparador), que es una señal de control que nosotros enviaremos desde la Raspberry Pi para pedirle al sensor que mida la distancia al objeto que tenga enfrente. Desde el punto de vista del sensor es un PIN de entrada, que deberemos conectar a un GPIO configurado como salida. Funciona por tensión y si le aplicamos un voltaje de 3,3 V de forma directa funcionará correctamente.
  • Echo es un PIN a través del cual el sensor nos contestará una vez le pidamos una medida, haciendo variar su salida entre 0 y 5 V.
  • Gnd es un terminal al que deberemos aplicar el voltaje de referencia de 0 V desde nuestra placa de prototipos.

El sensor tiene un alcance de 4 metros y la distancia más corta que es capaz de detectar es de 2 centímetros, todo ello con una precisión de 3 milímetros.

Funcionamiento

El funcionamiento del sensor responde a este mecanismo:

  • Para hacer una medida nos tenemos que asegurar de que, previamente, el PIN Trig esté a nivel bajo (0 V, 0, GPIO.LOW) durante al menos 2 μs (microsegundos).
  • Posteriormente, debemos enviar un nivel alto (3,3 V, 1, GPIO.HIGH) al PIN Trig durante 10 μs, intervalo tras el cual lo volveremos a poner a nivel bajo.

Esto hace que el sensor emita 8 pulsos de ultrasonidos a una frecuencia de 40 kHz. El oído humano es capaz de oir frecuencias de hasta 22 kHz en general (habrá alguien que pueda superarlo, pero por poco), por eso es inaudible y se llama ultrasonido porque está por encima (ultra) de la máxima frecuencia perceptible.

  • Tras ello, al detectar un objeto en el rango de medición (menor a 4 metros), el PIN Echo se pondrá a un nivel alto de 5 V.
  • Se mantendrá con ese voltaje durante un tiempo que representa el tiempo T que ha tardado el sonido en viajar al obstáculo desde el transmisor, rebotar, y ser detectado en el receptor.
Funcionamiento del sensor. El pulso en Echo tendrá una duración T igual al instante de recepción, tR, menos el instante de emisión, tI.
Funcionamiento del sensor. El pulso en Echo tendrá una duración T igual al instante de recepción, tR, menos el instante de emisión, tI.

 

  • Lo que tendremos que hacer con esa medida de tiempo, en segundos, será dividirla entre 2 (sólo queremos contar un camino) y multiplicarla por la velocidad del sonido, que a 20 ºC es de 343 metros por segundo. Así:

D (m) = (T/2) · 343 m/s

Y el resultado, como es lógico según la fórmula, vendrá dado en metros.

Montaje del prototipo

Para montar el prototipo voy a estrenar mi placa de prototipado larga que viene con el kit de Sunfounder que os enseñaba hace unas semanas, junto con la placa de expansión de GPIO que trae; la otra que tengo del kit de Vilros no encaja. Como veréis en la foto tengo que cablear la alimentación sacándola de los terminales GPIO de 5V0 (5 V) y de GND (0 V).

Prototipo con HC-SR04
Prototipo con HC-SR04
Detalle de las conexiones del sensor. Cable rojo: Vcc (5 V). Cable amarillo: Trig. Cable verde: Echo. Cable negro: Gnd (0 V)
Detalle de las conexiones del sensor. Cable rojo: Vcc (5 V). Cable amarillo: Trig. Cable verde: Echo. Cable negro: Gnd (0 V)

Diagrama de conexiones:

Prototipo con el esquema básico de conexiones - haz click para ampliarlo
Prototipo con el esquema básico de conexiones – haz click para ampliarlo
  1. Conectaremos un PIN 5V0 (5 V) desde las filas conectadas a la placa de expansión a una de las columnas laterales rotuladas con un signo + rojo. Usad un cable rojo, por convenio (negro es masa y rojo es tensión de alimentación).
  2. Conectaremos un PIN rotulado como GND, 0 V, masa o tierra, desde su fila a la columna lateral marcada con un signo – azul. Usad un cable negro, por convenio (negro es masa y rojo es tensión de alimentación).
  3. El sensor hay que conectarlo ocupando 4 filas de la placa de prototipado: como recordaréis del artículo y el vídeo en el que os enseñaba este tipo de placas con un ejemplo más pequeño, las columnas de una misma fila están conectadas entre sí. En mi caso he ocupado las 4 últimas: de la 60 a la 63, incluidas.
  4. Una vez hecho eso, alimentamos el sensor:
    1. Tiramos un cable rojo desde la fila de tensión roja, de 5 V (a la que hemos conectado el cable en el punto 1), directamente a la fila que se conecta con el terminal Vcc del sensor.
    2. Tiramos un cable negro desde la fila azul, de 0 V, a la que hemos conectado un cable desde un PIN GND (punto 2), directamente a la fila que se conecta con el terminal Gnd del sensor.
  5. Sacamos un cable amarillo de la fila que se conecta al terminal Trig del sensor y lo conectamos directamente a la fila que se conecta al PIN GPIO 12. Este GPIO 12 estará configurado como salida, y la corriente que extraerá el sensor será su corriente de trabajo (15 mA), dentro de los niveles seguros para la Raspberry.
    1. Recordad que la Raspberry Pi soporta a través de GPIO “un máximo de 16 mA por cada PIN, no superando entre todos 50 mA“: os lo contaba en el artículo sobre análisis de circuitos eléctricos.
    2. Esto quiere decir que en este prototipo no necesitamos limitar la corriente con un resistor, pero si usásemos más terminales GPIO como salida en otro montaje más complejo, sí deberíamos hacerlo para no superar el máximo de 50 mA entre todos ellos.
  6. Sacaremos un cable verde del terminal Echo del sensor, que conectaremos a un divisor de tensión formado por tres resistores de 330 Ω como podéis ver en el esquema y, con otro cable verde, lo llevaremos hasta el PIN GPIO 6. El divisor de tensión merece una sección aparte.
  7. El divisor de tensión debe ir conectado a tierra como en el esquema, por lo que si lo estáis conectando en la sección inferior de la placa de prototipado, como yo, deberéis conectarlo a la fila azul rotulada con un -, y ésta a un puerto GPIO rotulado como GND mediante un cable negro.

Pasar de 5 V a 3,3 V: el divisor de tensión

Un divisor de tensión es un sistema de resistores que sirve para fijar la tensión a un nivel intermedio entre el nivel de alimentación del conjunto (por ejemplo, 5 V) y el nivel de tierra. Normalmente se configura con 2 resistencias como en la siguiente imagen:

Divisor de tensión
Divisor de tensión

Si suponemos que Vd no se conecta a nada y por lo tanto por esa derivación no sale ninguna corriente, este montaje funciona como sigue:

Vd = I · R2

Echo = I · R1 + I · R2

Dividiendo una expresión por otra, se tiene que:

Vd / Echo = I · R2 / (I · R1 + I · R2)

Simplificando y despejando Vd, se llega a que:

Vd = Echo · R2 / (R1 + R2)

En el circuito que estamos montando, Echo es 5 V y queremos conseguir en Vd haya un valor de 3,3 V, puesto que la Raspberry Pi trabajo con ese nivel de referencia. Por lo tanto:

3,3V = 5V * R2/ (R1 + R2) ⇒

3,3V · R1 + 3,3V · R2 = 5V * R2 ⇒

R2 ≅ 2 · R1

Es decir: si configuramos un divisor de tensión con una resistencia R2 conectada a tierra que valga el doble que otra resistencia R1, conectada a la tensión de referencia de 5 V, en medio de ambas resistencias tendremos aproximadamente 3,3 V. Nos vale cualquier par de resistencias, pero en función de su valor la corriente que las recorrerá será, lógicamente, diferente.

En el caso que nos ocupa este sencillo análisis es válido, ya que Vd irá directamente conectado a un PIN GPIO configurado como entrada: los GPIO de entrada se comportan como un circuito abierto (o una resistencia infinita), y por lo tanto no drenan corriente del circuito. Pero ojo: si Vd lo conectásemos a un circuito que presentase una resistencia global menor que infinito, habría que hacer un análisis más completo. Te propongo que completes el circuito poniendo una resistencia R3 entre Vd y tierra, y que apliques las leyes de Kirchoff y de Ohm para comprobarlo. En este caso, además, como la corriente que aceptaría el resto del circuito no sería nula, tendríamos que considerar dos resistencias que fijasen no sólo la tensión, sino también la corriente, de forma que el resto del circuito no se dañase o funcionase como se pretende.

Como se da la mala suerte de que no tengo ninguna resistencia en mis kits que valga exactamente el doble que otra, lo que haré será colocar 2 resistencias de 330 Ω en serie en lugar de una de 660 Ω para hacer las veces de R2:

Divisor de tensión final
Divisor de tensión final

Las resistencias en serie son equivalentes a una única resistencia cuyo valor es la suma de sus valores individuales, como podrás comprobar si repites el análisis.

Si ahora vuelves a consultar el diagrama podrás reconocer un divisor de tensión en la configuración de resistencias, el PIN Echo del sensor y el GPIO 6 de entrada a la Raspberry Pi: los elementos recorridos por los cables verdes.

El divisor de tensión dentro del prototipo
El divisor de tensión dentro del prototipo

Programa de pruebas

El programa de pruebas, de acuerdo a lo explicado en el apartado Funcionamiento, es el siguiente:

#!/usr/bin/python3

import time
import RPi.GPIO as GPIO
<br># Configurar el GPIO con convenio de numerado BCM
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
# trig (cable amarillo en el prototipo)
GPIO.setup(12, GPIO.OUT)
# echo (cable verde en el prototipo)
GPIO.setup(6, GPIO.IN)

try:
    while True:
        start = 0
        end = 0
        # Configura el sensor
        GPIO.output(12, False)
        time.sleep(2) # 2 segundos para hacer el programa usable
        # Empezamos a medir
        GPIO.output(12, True)
        time.sleep(10*10**-6) #10 microsegundos
        GPIO.output(12, False)

        # Flanco de 0 a 1 = inicio 
        while GPIO.input(6) == GPIO.LOW:
            start = time.time()
        # Flanco de 1 a 0 = fin
        while GPIO.input(6) == GPIO.HIGH:
            end = time.time()

        # el tiempo que devuelve time() está en segundos
        distancia = (end-start) * 343 / 2
        print ("Distancia al objeto =", str(distancia))
        
except KeyboardInterrupt:
    print("\nFin del programa")
    GPIO.output(12, False)
    GPIO.cleanup()

En este listado, lo único que tenéis que tener en cuenta es que para hacer el programa usable y que os dé tiempo a ver en pantalla los resultados he puesto una pausa de 2 segundos, que no microsegundos, entre cada medida. Ese intervalo es igualmente válido para configurar el sensor (forzando un nivel bajo en el terminal Trig, conectado al GPIO 12).

Para medir el ancho del pulso que el sensor estoy usando dos bucles de espera activa, técnica de la que no me siento orgulloso y que por lo tanto, en su debido momento, será objeto de estudio para entenderla, ver sus defectos y hablar sobre cómo los podemos solventar:

        # Flanco de 0 a 1 = inicio 
        while GPIO.input(6) == GPIO.LOW:
            start = time.time()
        # Flanco de 1 a 0 = fin
        while GPIO.input(6) == GPIO.HIGH:
            end = time.time()

Fijando esos dos instantes de tiempo con ayuda de esos bucles, ya tendremos la medida, en segundos, del tiempo que tarda el (ultra)sonido en ir hasta el obstáculo y volver al sensor. Dicha medida la podremos multiplicar por la velocidad del sonido para obtener la distancia, en metros.

El resultado lo podéis ver en la siguiente imagen:

Resultado del ejercicio
Resultado del ejercicio

No olvidéis dar permisos de ejecución al programa con chmod +x ultrasonidos.py  (si lo habéis llamado así).

Y esto es todo: espero que haya resultado interesante. Puedes dejarme cualquier comentario en esta misma entrada, enviándome cualquier comentario a través del formulario de contacto, o bien a través de la dirección de correo que allí encontrarás.

4 comentarios en “Controla un sensor de proximidad desde tu Raspberry Pi

  1. Buenas.

    Entonces si yo quisiera montar 10 sensores de estos…podria?. Tendria que poner resistencias mas grandes?. Porque segun leo con 300 ohmios solo podria poner 3 sensores con su resistencia cada uno…cierto?

    1. A falta de hacer las cuentas, no podrías hacerlo porque la corriente que drenarías del SoC sería demasiado alta.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *