Micropython: Usando el sensor HC-SR04

El sensor ultrasónico HC-SR04 es un viejo conocido, ampliamente utilizado en un sinnúmero de aplicaciones donde sea necesario realizar una medición de distancias, como en robots que esquivan obstáculos, detectores de personas o para medir el nivel de un líquido. Es sencillo de usar y también barato. En este artículo veremos como utilizarlo en Micropython.

El HC-SR04 basa su funcionamiento en la propiedad de las ondas sonoras de rebotar contra las superficies y objetos. Consiste en un transmisor que emite un tren de señales ultrasónicas con una frecuencia de 40 KHz que de desplazan por el aire, rebotan contra el obstáculo que está al frente y son captadas por el receptor ubicado sobre el mismo sensor. A partir del tiempo que demora la señal en completar ese recorrido y conociendo la velocidad del sonido en el aire, se calcula la distancia a la que está el obstáculo.

Principio de funcionamiento

El módulo tiene 4 pines, dos de alimentación y dos de señales:

Vcc: Tensión de alimentación (5V)

Trig: Trigger. Entrada al módulo. Dispara la transmisión de ultrasonidos.

Echo: Salida que indica la recepción de la señal rebote.

GND: Tierra de alimentación

Como vemos, el HC-SR04 debe alimentarse con 5 voltios. En este ejemplo, donde uso una placa D1 mini, los voy a tomar del pin 5V que deriva esa tensión de la interfaz USB, a partir de los cuales se obtienen los 3,3V del ESP8266. Esto implica que la salida Echo del sensor también nos va a entregar 5V. Aunque no hay información oficial sobre el tema, la experiencia con el ESP8266 demuestra que es capaz de tolerar 5V en sus entradas (las pruebas que yo hice lo confirman). Si quieren estar 100% seguros y bajar ese valor antes del entrar al micro, pueden intercalar un divisor resistivo formado por una resistencia de 2K7 y 1K5 como se ve a continuación.

Divisor resistivo en la salida Echo
Esquemático del divisor

En la entrada Trig del HC-SR04 vamos a aplicar una señal de 3,3V, pero esto no es un inconveniente, porque el sensor lo reconoce como un valor ALTO válido.

El circuito completo (sin divisor resistivo en Echo) quedaría como sigue:

Conexiones al HC-SR04
Esquemático

Veamos ahora como utilizar el sensor desde Micropython.

Entre las librerías estandar de Micropython (las que están incluidas con el intérprete) no hay ninguna que nos permita usar el HC-SR04. Sin embargo, afortunadamente hay muchos desarrolladores en la comunidad que realizan sus aportes para ampliar las posibilidades de este lenguaje y escriben módulos para distintas placas o sensores. Este es el caso del HC-SR04, del cual podemos encontrar en la red mas de un módulo disponible. En este artículo usaremos el que se puede encontrar en este repositorio

Para descargar el módulo debemos acceder al repositorio, hacer click en el botón CODE y descargar el archivo ZIP.

Descarga del módulo del repositorio

Una vez descargado, hay que descomprimir el ZIP y subir el módulo hcsr04.py a nuestra placa para que la pueda usar el intérprete Python que ya está grabado allí. Debemos guardar este archivo dentro de una carpeta lib, que primero debemos crear. Para hacerlo, debemos activar la visualización de archivos en Thonny yendo al menú Visualización y tildando la opción Archivos, con lo que empezaremos a tener una ventana con los archivos locales de nuestra computadora y los que están almacenados en la placa con micropython. Luego, hacemos click con el botón derecho en la zona de los archivos de la placa y elegimos Nuevo Directorio y le damos como nombre lib

Puede que ustedes no tengan un archivo main, y sólo boot, eso no importa, el procedimiento es exactamente el mismo.

Ahora, hay que abrir el archivo hcsr04.py que descargamos y descomprimimos en Thonny y luego guardar con Fichero Guardar ComoMicropython Device y elegimos la carpeta lib que acabamos de crear. Debe quedar algo así:

Archivos en la placa

Una vez copiado el módulo en la carpeta lib ya estamos en condiciones de utilizarlo desde el programa. Como siempre, lo primero es importarlo. En esta ocasión vamos a importar la clase HCSR04:

from hcsr04 import HCSR04

Luego, creamos o instanciamos un objeto de esa clase, usando el constructor:

medidor = HCSR04 (trigger_pin=D2 , echo_pin=D1 )

El constructor tiene el siguiente formato general:

sensor = HCSR04 (trigger_pin, echo_pin, echo_timeout_us)

Los parámetros son los siguientes:

trigger_pin: pin que se conecta a la entrada Trig del sensor

echo_pin: pin que se conecta a la salida Echo del sensor

echo_timeout: Tiempo máximo de espera antes de producir un error

Por omisión el timeout está fijado en 30.000 us (30 ms) pero se puede modificar especificando otro valor en el constructor.

Un objeto de la clase HCSR04 tiene dos métodos disponibles:

distance_cm (): Devuelve la distancia medida en centímetros como un número de punto flotante (con coma)

distance_mm (): Devuelve la distancia medida en milímetros como un número entero.

El programa de pruebas puede verse a continuación. Luego de crear el objeto medidor, es un bucle sin fin donde se llama al método distance_cm en una estructura try-except (si no sabes como funciona, consulta la explicación aquí).

#Sensor de distancias HCS-R04
#Mapeo de GPIO de D1 Mini

D0 = 16
D1 = 5
D2 = 4
D3 = 0
D4 = 2
D5 = 14
D6 = 12
D7 = 13
D8 = 15

from hcsr04 import HCSR04
from time import sleep

medidor = HCSR04 (trigger_pin = D2 , echo_pin = D1)
while (True):
    try:
        distancia = medidor.distance_cm ()
        print ("Distancia = ", distancia)
        sleep (1)
    except:
        print ("Error!")

Al menos los sensores que pude probar nunca devolvieron el error de timeout. Cuando la distancia a medir supera los 4m, devuelven un valor cercano a 0 o negativo. Para filtrar estos errores y devolver un valor promediado que elimine pequeñas variaciones agregué una función que emplea sólo las lecturas de valores mayores que 0 para hacer un promedio de 16 medidas

#Sensor de distancias HCS-R04
#Mapeo de GPIO de D1 Mini

D0 = 16
D1 = 5
D2 = 4
D3 = 0
D4 = 2
D5 = 14
D6 = 12
D7 = 13
D8 = 15

from hcsr04 import HCSR04
from time import sleep

medidor = HCSR04 (trigger_pin = D2 , echo_pin = D1)

def midePromedio ():
     suma=0
     for i in range (0,16):
         distancia = medidor.distance_cm ()
         sleep (0.1)
         if (distancia > 0):
             suma+=distancia
     return suma/16

while (True):
     print ("Distancia = ", midePromedio ())

En el video puede verse el programa en funcionamiento:

Cualquier duda o sugerencia, pueden escribir en la sección de comentarios, así como sus experiencias con el timeout. Hasta la próxima!

Deja un comentario

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

A %d blogueros les gusta esto: