Medir distancia con precisión con Arduino y sensor láser VL53L0X y VL6180X

¿Qué es un VL53L0X?

El VL53L0X es un sensor de distancia infrarrojo láser de última generación, que podemos emplear junto con un procesador como Arduino para medir distancias de 5cm a 2m de forma precisa. Para rangos más cercanos, la variante VL6180X tiene un rango de 5mm a 200mm.

El VL53L0X es capaz de operar incluso con elevada luz ambiental infrarroja, e incorpora un sistema de compensación de la medición que le permite hacer funcionar incluso detrás de un cristal protector.

Es uno de los mejores sensores de distancia disponibles. Tiene una precisión superior que los sensores de ultrasonidos e infrarrojos, y no se ve alterado por las condiciones del ambiente como los ecos o la reflectancia de los objetos.

Por otro lado el ángulo de medición es relativamente estrecho. Esto es una ventaja en la mayoría de circunstancias, donde deseamos leer la distancia justo en frente del sensor. Aunque también puede ser una desventaja, por ejemplo, a la hora de detectar obstáculos.

VL53L0X-componente

¿Cómo funciona un VL53L0X?

El VL53L0X es un sensor ToF (Time of flight). Su funcionamiento consiste en enviar un pulso láser de luz infrarroja y medir el tiempo necesario en el haz en volver al sensor.

El ángulo de medición es de 25º. Esto se traduce en un área de medición de 0.44m de diámetro a una distancia de 1m.

El rango de medición depende de las condiciones del entorno (interior, o exterior), de las características del objetivo y del modo de funcionamiento. En general, tenemos dos modos. El estandard es de 50 a 1200mm, y un modo ampliado hasta 2000mm.

Esquema de montaje.

La conexión de los módulos que integran el VL53L0X es sencilla, ya que la comunicación se realiza a través de I2C. Por tanto, simplemente alimentamos el módulo desde Arduino mediante GND y 5V y conectamos el pin SDA y SCL de Arduino con los pines correspondientes del sensor.

arduino-sensor-distancia-laser-VL53L0X-esquema

laser

VL53L0X

Ejemplos de código.

Para realizar la lectura del sensor VL53L0X usaremos la librería desarrollada por Adafruit, disponible en este enlace.

La librería incorpora varios ejemplos de uso. El siguiente código toma lecturas de la distancia y muestra los resultados por puerto serie.

#include "Adafruit_VL53L0X.h"

Adafruit_VL53L0X lox = Adafruit_VL53L0X();

void setup() {
  Serial.begin(9600);

  // Iniciar sensor
  Serial.println("VL53L0X test");
  if (!lox.begin()) {
    Serial.println(F("Error al iniciar VL53L0X"));
    while(1);
  }
}

void loop() {
  VL53L0X_RangingMeasurementData_t measure;
    
  Serial.print("Leyendo sensor... ");
  // si se pasa true como parámetro, muestra por puerto serie datos de debug
  lox.rangingTest(&measure, false); 

  if (measure.RangeStatus != 4){
    Serial.print("Distancia (mm): ");
    Serial.println(measure.RangeMilliMeter);
  } 
  else{
    Serial.println("  Fuera de rango ");
  }
  delay(100);
}

Otra librería (Pololu)

A la hora de programar este láser con tu Arduino, también puedes elegir una librería de la sección de instalación de Librerías del IDE y mirar que tenemos. Bajo el nombre ‘VL53L0X’ se encuentran varias librerías interesantes.

La de Pololu o la de Adafruit por ejemplo. El funcionamiento es muy similar en todos los casos. Para utilizar esta librería (Pololu) lo primero es crear un objeto VL53L0X:

VL53L0X laser;

Luego habrá que inicializar este láser en el setup() de nuestro programa:

laser.init();

También habrá que añadir un timeout, un tiempo a partir del cuál el láser dé por perdida la medida que acaba de enviar ya que no ha rebotado con nada:

laser.setTimeout(500);

Sabemos cuando el sensor dará por perdida la recepción de la señal, ahora falta definir cada cuánto va a leer para detectar si la señal ha llegado. Para ir tomando medidas separadas en el tiempo tendremos que añadir esta línea en el setup():

laser.startContinous(tiempo);

Dónde el tiempo serán los milisegundos a esperar entre medidas. Si quisiésemos que las medidas se tomaran continuamente (Lo más rápido posible). Pondríamos esto en el setup():

laser.startContinous();

Como ves, simplemente he eliminado el tiempo. Ahora en el loop() tan solo debemos de encargarnos de dos cosas:

  • Recuperar el valor de medida:
    Asegurarme de que no ha habido un timeout y realmente la señal nunca ha sido recibida.
    Para ello utilizaremos esta función para recuperar el valor de la distancia en milímetros:

laser.readRangeContinuousMillimeters());

  • Por otra parte, debemos comprobar que no haya habido un error y el haz láser enviado no haya vuelto en el tiempo determinado:

laser.timeoutOccurred();

Esta función simplemente da un resultado booleano: true o false. true si ha habido un timeout y el láser enviado no se ha recepcionado o false si ha ido todo bien.