Skip to Content

Sensor de Distância VL53L1X/TOF400C com Arduino

Sensor de Distância VL53L1X/TOF400C com Arduino

Neste tutorial, vais aprender a usar o Sensor de Distância a Laser VL53L1X (também chamado TOF400C) com um Arduino ou qualquer outro microcontrolador comum (ESP32/ESP8266) para medir distâncias.

O VL53L1X é um sensor de distância Time-of-Flight (ToF) muito pequeno que usa luz laser infravermelha para medir a proximidade de um objeto. Ao medir o tempo que a luz demora a ser refletida por um objeto, consegue calcular distâncias com alta precisão.

Peças Necessárias

Vais precisar de um Sensor de Distância VL53L1X. Quanto ao microcontrolador, usei um Arduino Uno para este projeto, mas qualquer outro Arduino ou ESP32/ESP8266 também funciona. Também vamos usar um OLED para mostrar as distâncias medidas pelo VL53L1X num ecrã.

Sensor de Distância VL53L1X

Arduino

Arduino Uno

USB Data Sync cable Arduino

Cabo USB para Arduino UNO

Dupont wire set

Conjunto de Fios Dupont

Half_breadboard56a

Breadboard

OLED display

Ecrã OLED

Makerguides is a participant in affiliate advertising programs designed to provide a means for sites to earn advertising fees by linking to Amazon, AliExpress, Elecrow, and other sites. As an Affiliate we may earn from qualifying purchases.

Características do VL53L1X

O VL53L1X é um chip minúsculo (4,4 x 2,5 x 1,56 mm) com dois orifícios no topo. Um para o emissor de luz laser e outro para o detector de luz. O VL53L1X funciona emitindo um pulso de luz laser pelo emissor, recebendo a luz refletida de um objeto no detector e, com base no tempo que demorou (time-of-flight), calcula a distância ao objeto. A imagem abaixo mostra os cones do emissor e do detector.

Princípio de Funcionamento do VL53L1X (source)

Aqui estão as principais especificações do VL53L1X:

  • Emissor VCSEL de 940 nm (luz IR, invisível ao olho)
  • Tempo de medição de 20 ms até 1000 ms
  • Tamanho programável da região de interesse (ROI)
  • Posição programável da ROI na matriz receptora
  • Três modos de distância: curto, médio e longo
  • Distância entre 4 cm e 400 cm
  • Resolução: 1 mm
  • Tensão: 2,6 a 3,5 V
  • Interface de comunicação I2C (até 400 kHz)

As regiões programáveis de interesse (ROI) do VL53L1X permitem reduzir ou dividir o campo de visão total em múltiplas zonas. Podes usar isto para implementar reconhecimento de gestos, como deslizar, por exemplo. Para mais detalhes, consulta o datasheet do sensor VL53L1X:

VL53L1X como parte de um sistema LiDAR

Existem muitas aplicações para sensores de distância a laser, como aviso de proximidade em estacionamento, deteção de intrusos, evasão de obstáculos em robótica e mais. O mais importante é que sensores de distância a laser são frequentemente usados em LiDAR sistemas, que significa Luz Deteção e Rangeamento e são usados para criar mapas e modelos 3D altamente precisos.

Além do sensor de distância a laser, um sistema LiDAR normalmente inclui uma unidade GPS e uma unidade de medição inercial (IMU). O scanner é um mecanismo que move o feixe laser por uma área ampla, permitindo ao sistema capturar dados de diferentes ângulos e posições. A unidade GPS fornece dados de localização precisos. Finalmente, a IMU acompanha a orientação e o movimento do sistema LiDAR, o que é crucial para manter a precisão durante a digitalização.

À medida que os pulsos laser são emitidos e refletidos, o sistema regista continuamente as medições de distância juntamente com os seus ângulos e posições correspondentes. Estes dados são então usados para criar uma nuvem de pontos, que representa a distribuição espacial dos objetos na área digitalizada.

Podes construir um LiDAR simples tu mesmo, fixando o sensor de distância a laser num servo e usar o servo para escanear o ambiente, enquanto o sensor mede as distâncias. No entanto, neste tutorial vamos usar apenas o sensor de distância a laser, sem dispositivo de varrimento.

Esquema de Aplicação do VL53L1X

O esquema de aplicação seguinte mostra a ligação externa necessária para usar o chip VL53L1X. Podes ver os resistores pull-up para a interface I2C que liga o VL53L1X a um microcontrolador (host), e dois condensadores que estabilizam a alimentação.

Application Schematic of VL53L1X
Esquema de Aplicação do VL53L1X (source)

SDA e SCL são os pinos para a interface I2C. XSHUT é o pino de desligar, que permite desligar o sensor quando puxado para baixo. Isto é útil se quiseres ligar vários sensores VL53L1X à mesma linha I2C. GPIO1 é um pino de interrupção que pode sinalizar ao microcontrolador que os dados estão prontos.

No entanto, em vez de usar diretamente o pequeno chip VL53L1X, é melhor obter uma placa breakout que já tenha a eletrónica acima integrada e seja muito mais fácil de ligar.

Placa breakout para VL53L1X

A imagem seguinte mostra a parte de trás e a frente de uma placa breakout típica para o VL53L1X. O chip sensor real está localizado atrás da cobertura oval protetora. A cobertura reduz o impacto da luz ambiente na precisão do sensor.

Placa breakout para VL53L1X (source)

O pinout tem os mesmos pinos discutidos acima. SDA, SCL para I2C, GPIO1 como sinal de interrupção, XSHUT para seleção do chip, e VIN e GND para alimentação.

Ligação do VL53L1X

Graças à interface I2C do VL53L1X, ligá-lo a um Arduino é fácil. Primeiro, liga os pinos SCL e SDA da placa breakout VL53L1X aos pinos correspondentes no Arduino, como mostrado abaixo. Depois, liga o terra ao GND e 3,3V ao VIN do VL53L1X.

Connecting VL53L1X with Arduino
Ligação do VL53L1X com Arduino

A placa breakout VL53L1X funciona com 5V ou 3,3V e podes usar qualquer um para o VIN. Aqui, estou a usar 3,3V para o VIN. A seguir, vamos escrever algum código para testar a função do sensor VL53L1X.

Código para medir distância com VL53L1X

Antes de poderes medir distâncias com o sensor VL53L1X, terás de instalar uma biblioteca. As mais comuns são a Adafruit VL53L1X Library e a VL53L1X Library by Pololu. No entanto, tive problemas com as bibliotecas da Adafruit ao escrever o tutorial para o VL53L0X Distance Sensor, por isso vou usar a VL53L1X Library by Pololu. Ela também oferece mais opções de configuração para o VL53L1X.

Instalar a Biblioteca VL53L1X da Pololu

Para instalar a VL53L1X Library by Pololu, abre o Library Manager, procura por VL53L1X, encontra a da Pololu e instala. A imagem abaixo mostra como fica depois de instalada a biblioteca:

Installing VL53L1X Library by Pololu via Library Manager
Instalar a Biblioteca VL53L1X da Pololu via Library Manager

Com a biblioteca instalada, vamos testar o sensor. O código seguinte lê as distâncias medidas pelo VL53L1X e imprime-as no monitor Serial.

#include "VL53L1X.h"

VL53L1X sensor;

void sensor_init(VL53L1X::DistanceMode range_mode, bool high_speed) {
  Wire.begin();
  sensor.setTimeout(500);
  sensor.init();
  sensor.setDistanceMode(range_mode);  
  int budget = high_speed ? 33000 : 140000;
  sensor.setMeasurementTimingBudget(budget);
}

void setup() {
  Serial.begin(9600);
  // range_mode: VL53L1X::Short, VL53L1X::Medium, or VL53L1X::Long
  sensor_init(VL53L1X::Medium, false);   
}

void loop() {
  int dist = sensor.readRangeSingleMillimeters();
  Serial.println(dist);
  delay(1000);
}

Vamos decompor o código nas suas partes para melhor compreensão.

Inclusão da Biblioteca

O código começa por incluir a biblioteca necessária para o sensor VL53L1X. Esta biblioteca fornece as funções necessárias para comunicar com o sensor.

#include "VL53L1X.h"

Criação de um Objeto Sensor

De seguida, criamos uma instância da classe VL53L1X, que nos permite interagir com o sensor.

VL53L1X sensor;

Função de Inicialização do Sensor

A função sensor_init() é responsável por inicializar o sensor. Recebe dois parâmetros: range_mode que especifica o modo de medição de distância, e high_speed que determina o orçamento de tempo de medição.

void sensor_init(VL53L1X::DistanceMode range_mode, bool high_speed) {
  Wire.begin();
  sensor.setTimeout(500);
  sensor.init();
  sensor.setDistanceMode(range_mode);  
  int budget = high_speed ? 33000 : 140000;
  sensor.setMeasurementTimingBudget(budget);
}

Dentro desta função:

  • Wire.begin(); inicializa a comunicação I2C.
  • sensor.setTimeout(500); define um tempo limite para as operações do sensor.
  • sensor.init(); inicializa o sensor.
  • sensor.setDistanceMode(range_mode); define o modo de distância com base no parâmetro de entrada.
  • O orçamento de tempo de medição é definido com base na velocidade alta solicitada.

De acordo com o datasheet, o orçamento de tempo do VL53L1X deve ser definido da seguinte forma.

  • 20 ms é o orçamento mínimo e só pode ser usado no modo de distância curta.
  • 33 ms é o orçamento mínimo que funciona para todos os modos de distância.
  • 140 ms é o orçamento que permite alcançar a distância máxima de 4 m (no escuro, num gráfico branco) com o modo de distância longa.

No código, uso 33 ms para o modo rápido, pois funciona para todas as distâncias, e 140 ms caso contrário, pois permite a distância máxima.

Para o alcance, podes usar as constantes pré-definidas VL53L1X::Short, VL53L1X::Medium, ou VL53L1X::Long. O alcance que o sensor pode medir depende do modo escolhido e da luz ambiente. A tabela seguinte do datasheet do VL53L1X mostra essas dependências:

Maximum distance vs. distance mode under ambient light for VL53L1X
Distância máxima vs. modo de distância sob luz ambiente para VL53L1X

O modo de distância longa permite alcançar a maior distância possível de até 4 m – em condições ideais (escuro). Geralmente, a distância medida é afetada pela luz ambiente. O modo de distância curta é mais imune à luz ambiente, mas a sua distância máxima é tipicamente limitada a 1,3 m.

Função Setup

Na função setup(), iniciamos a comunicação Serial e inicializamos o sensor com um modo de distância específico.

void setup() {
  Serial.begin(9600);
  // range_mode: VL53L1X::Short, VL53L1X::Medium, or VL53L1X::Long
  sensor_init(VL53L1X::Medium, false);   
}

Aqui, Serial.begin(9600); configura o Monitor Serial a 9600 baud. A função sensor_init() é chamada com VL53L1X::Medium como modo de alcance e false para alta velocidade, o que significa que o sensor vai operar em alcance médio com um orçamento de tempo maior.

Função Loop

Finalmente, na função loop(), lemos continuamente a distância do sensor e imprimimos no Monitor Serial.

void loop() {
  int dist = sensor.readRangeSingleMillimeters();
  Serial.println(dist);
  delay(1000);
}

Se carregares e executares o código, deverás ver as distâncias medidas impressas no Monitor Serial.

Distances measured with VL53L1X printed on Serial Monitor
Distâncias medidas com VL53L1X impressas no Monitor Serial

Na próxima secção, vamos adicionar um OLED ao nosso circuito e mostrar as distâncias nele, em vez de imprimir no Monitor Serial.

Adicionar um OLED para mostrar dados do VL53L1X

Como o OLED também é um dispositivo I2C, ligá-lo é simples. Basta ligar SDA e SCL aos mesmos pinos onde o sensor VL53L1X está ligado. E como o OLED funciona a 3,3V, podemos também partilhar as linhas de alimentação.

Connecting OLED and VL53L1X with Arduino
Ligação do OLED e VL53L1X com Arduino

Código para mostrar distâncias medidas pelo VL53L1X no OLED

O código seguinte lê as medições de distância do sensor VL53L1X e mostra-as no OLED. Dá uma vista rápida ao código completo primeiro, depois discutiremos os detalhes.

#include "Wire.h"
#include "VL53L1X.h"
#include "Adafruit_SSD1306.h"

Adafruit_SSD1306 oled(128, 64, &Wire, -1);
VL53L1X sensor;

void sensor_init(VL53L1X::DistanceMode range_mode, bool high_speed) {
  Wire.begin();
  sensor.setTimeout(500);
  sensor.init();
  sensor.setDistanceMode(range_mode); 
  int budget = high_speed ? 33000 : 140000;
  sensor.setMeasurementTimingBudget(budget);
}

void oled_init() {
  oled.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  oled.setTextSize(2);
  oled.setTextColor(WHITE);
}

void display() {
  static char text[30];
  int dist = sensor.readRangeSingleMillimeters();
  sprintf(text, "%4d mm", dist);

  oled.clearDisplay();
  oled.setCursor(20, 25);
  oled.print(text);

  oled.display();
}

void setup() {
  oled_init();
  sensor_init(VL53L1X::Medium, false); 
}

void loop() {
  display();
}

Vamos decompor o código nas suas partes para melhor compreensão.

Inclusão de Bibliotecas

No início do código, incluímos as bibliotecas necessárias para o nosso projeto. A biblioteca Wire.h é usada para comunicação I2C, VL53L1X.h para interface com o sensor de distância VL53L1X, e Adafruit_SSD1306.h para controlar o ecrã OLED.

#include "Wire.h"
#include "VL53L1X.h"
#include "Adafruit_SSD1306.h"

Se ainda não instalaste a Adafruit_SSD1306 Library, terás de o fazer. Basta instalar via Library Manager como de costume:

Adafruit_SSD1306 library installed in Library Manager
Biblioteca Adafruit_SSD1306 instalada no Library Manager

Note que o endereço I2C para o ecrã OLED está definido para 0x3C em oled.begin(). A maioria destes pequenos OLEDs usa este endereço (or 0x27), mas o teu pode ser diferente. Se não vês nada no OLED, provavelmente tem um endereço I2C diferente e terás de alterar o endereço.

Se não souberes o endereço I2C, consulta o tutorial How to Interface the SSD1306 I2C OLED Graphic Display With Arduino para o encontrar. Também o tutorial Use SSD1306 I2C OLED Display With Arduino te vai ensinar mais sobre como usar um OLED.

Inicialização de Objetos

De seguida, criamos instâncias do ecrã OLED e do sensor de distância. O ecrã OLED é inicializado com uma largura de 128 pixels e altura de 64 pixels. O parâmetro &Wire indica que estamos a usar a biblioteca Wire para comunicação I2C, e -1 indica que não estamos a usar um pino de reset.

Adafruit_SSD1306 oled(128, 64, &Wire, -1);
VL53L1X sensor;

Função de Inicialização do Sensor

A função sensor_init() inicializa o sensor VL53L1X. Recebe dois parâmetros: range_mode para definir o modo de medição de distância e high_speed para determinar o orçamento de tempo de medição. Dentro da função, iniciamos a comunicação I2C, definimos um tempo limite para o sensor, inicializamos o sensor e configuramos o modo de distância. O orçamento de tempo de medição é definido com base na ativação ou não da alta velocidade.

void sensor_init(VL53L1X::DistanceMode range_mode, bool high_speed) {
  Wire.begin();
  sensor.setTimeout(500);
  sensor.init();
  sensor.setDistanceMode(range_mode); 
  int budget = high_speed ? 33000 : 140000;
  sensor.setMeasurementTimingBudget(budget);
}

Função de Inicialização do OLED

A função oled_init() inicializa o ecrã OLED. Começa por ligar o ecrã usando o parâmetro SSD1306_SWITCHCAPVCC e definir o endereço I2C para 0x3C. Também definimos o tamanho do texto para 2 e a cor do texto para branco.

void oled_init() {
  oled.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  oled.setTextSize(2);
  oled.setTextColor(WHITE);
}

Função de Exibição

A função display() é responsável por ler a distância do sensor e mostrar no ecrã OLED. Primeiro declara um array de caracteres estático text para guardar a string da distância. A distância é lida em milímetros usando sensor.readRangeSingleMillimeters(), e o resultado é formatado no array text usando sprintf(). O ecrã OLED é então limpo, o cursor é colocado numa posição específica, e a distância é impressa. Finalmente, o ecrã é atualizado para mostrar o novo conteúdo.

void display() {
  static char text[30];
  int dist = sensor.readRangeSingleMillimeters();
  sprintf(text, "%4d mm", dist);

  oled.clearDisplay();
  oled.setCursor(20, 25);
  oled.print(text);

  oled.display();
}

Função Setup

Na função setup(), chamamos as funções de inicialização tanto do ecrã OLED como do sensor de distância. O sensor é inicializado com modo de alcance médio e alta velocidade desativada.

void setup() {
  oled_init();
  sensor_init(VL53L1X::Medium, false); 
}

Função Loop

Finalmente, a função loop() chama continuamente a função display(), que atualiza o ecrã OLED com a última medição de distância do sensor. Este ciclo corre indefinidamente, fornecendo leituras de distância em tempo real.

void loop() {
  display();
}

Conclusões

Neste tutorial aprendeste a usar o Sensor de Distância VL53L1X com um Arduino para medir distâncias e mostrá-las num OLED.

O Sensor VL53L1X é um sensor muito pequeno, rápido e de alta precisão que usa luz laser infravermelha para medir distâncias. O VL53L1X é quase idêntico ao VL53L0X mas tem um alcance maior. O primeiro pode medir distâncias até 400 cm, enquanto o segundo está limitado a 200 cm. Se precisares de um sensor para um alcance muito maior, vê o TF Luna que pode medir distâncias até 8 metros.

Outro sensor de distância a laser semelhante que usa o método Time-of-Flight é o sensor TOF10120. No entanto, o VL53L1X tem mais opções de configuração (longo alcance, alta velocidade) e um alcance maior (até 400 cm vs 180 cm).

Outros sensores comuns de distância infravermelha, como o GP2Y0A710K0F ou o GP2Y0A21YK0F, usam triangulação para determinar a distância com base no ângulo da luz IR refletida e têm alcance mais curto e menor precisão.

Se tiveres alguma dúvida, não hesites em deixar nos comentários.

Boas experiências ; )