Skip to Content

Sensore di Distanza VL53L1X/TOF400C con Arduino

Sensore di Distanza VL53L1X/TOF400C con Arduino

In questo tutorial imparerai come utilizzare il sensore di distanza laser VL53L1X (chiamato anche TOF400C) con un Arduino o qualsiasi altro microcontrollore comune (ESP32/ESP8266) per misurare le distanze.

Il VL53L1X è un sensore di distanza Time-of-Flight (ToF) molto piccolo che utilizza luce laser a infrarossi per misurare la prossimità di un oggetto. Misurando il tempo impiegato dalla luce per riflettersi su un oggetto, può calcolare distanze con alta precisione.

Componenti necessari

Ti servirà un sensore di distanza VL53L1X. Per il microcontrollore, ho usato un Arduino Uno per questo progetto, ma qualsiasi altro Arduino o ESP32/ESP8266 andrà bene. Useremo anche un display OLED per mostrare le distanze misurate dal VL53L1X.

Sensore di distanza VL53L1X

Arduino

Arduino Uno

USB Data Sync cable Arduino

Cavo USB per Arduino UNO

Dupont wire set

Set di fili Dupont

Half_breadboard56a

Breadboard

OLED display

Display 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.

Caratteristiche del VL53L1X

Il VL53L1X è un chip minuscolo (4,4 x 2,5 x 1,56 mm) con due fori sulla parte superiore. Uno per l’emettitore del laser e uno per il rilevatore di luce. Il VL53L1X funziona emettendo un impulso laser dall’emettitore, ricevendo la luce riflessa da un oggetto nel rilevatore e, basandosi sul tempo impiegato (time-of-flight), calcola la distanza dall’oggetto. L’immagine sotto mostra i coni dell’emettitore e del rilevatore.

Principio di funzionamento del VL53L1X (source)

Ecco le principali specifiche del VL53L1X:

  • Emettitore VCSEL a 940 nm (luce IR, invisibile all’occhio)
  • Tempo di misura da 20 ms fino a 1000 ms
  • Dimensione programmabile della regione di interesse (ROI)
  • Posizione programmabile della ROI sull’array ricevente
  • Tre modalità di distanza: corta, media e lunga
  • Distanza tra 4 cm e 400 cm
  • Risoluzione: 1 mm
  • Tensione: da 2,6 a 3,5 V
  • Interfaccia di comunicazione I2C (fino a 400 kHz)

Le regioni programmabili di interesse (ROI) del VL53L1X permettono di ridurre o dividere il campo visivo in più zone. Puoi usarlo per implementare il riconoscimento di gesti, come lo swipe, per esempio. Per maggiori dettagli consulta il datasheet del sensore VL53L1X:

VL53L1X come parte di un sistema LiDAR

Ci sono molte applicazioni per i sensori laser di distanza, come l’avviso di prossimità per il parcheggio, il rilevamento di intrusi, l’evitamento di ostacoli nella robotica e altro. Soprattutto, i sensori laser di distanza sono comunemente usati in LiDAR sistemi, che sta per Luce Detection e Ranging e sono usati per creare mappe e modelli 3D altamente precisi.

Oltre al sensore laser di distanza, un sistema LiDAR tipicamente include un’unità GPS e un’unità di misura inerziale (IMU). Lo scanner è un meccanismo che muove il fascio laser su un’ampia area, permettendo al sistema di acquisire dati da angolazioni e posizioni diverse. L’unità GPS fornisce dati di posizione precisi. Infine, l’IMU traccia l’orientamento e il movimento del sistema LiDAR, fondamentale per mantenere la precisione durante la scansione.

Mentre gli impulsi laser vengono emessi e riflessi, il sistema registra continuamente le misure di distanza insieme agli angoli e alle posizioni corrispondenti. Questi dati vengono poi usati per creare una nuvola di punti, che rappresenta la distribuzione spaziale degli oggetti nell’area scansionata.

Puoi costruire un semplice LiDAR da solo montando il sensore laser su un servo e usando il servo per scansionare l’ambiente, mentre il sensore misura le distanze. Tuttavia, in questo tutorial useremo solo il sensore laser, senza un dispositivo di scansione.

Schema applicativo del VL53L1X

Lo schema applicativo seguente mostra il cablaggio esterno necessario per usare il chip VL53L1X. Puoi vedere le resistenze di pull-up per l’interfaccia I2C che collega il VL53L1X a un microcontrollore (host), e due condensatori che stabilizzano l’alimentazione.

Application Schematic of VL53L1X
Schema applicativo del VL53L1X (source)

SDA e SCL sono i pin per l’interfaccia I2C. XSHUT è il pin di spegnimento, che permette di spegnere il sensore se portato a massa. Questo è utile se vuoi collegare più sensori VL53L1X sulla stessa linea I2C. GPIO1 è un pin di interrupt che può segnalare al microcontrollore che i dati sono pronti.

Tuttavia, invece di usare direttamente il piccolo chip VL53L1X, è meglio procurarsi una breakout board che integra già l’elettronica sopra descritta ed è molto più facile da collegare.

Breakout board per VL53L1X

L’immagine seguente mostra il retro e il fronte di una tipica breakout board per il VL53L1X. Il sensore vero e proprio si trova dietro la copertura ovale protettiva. La copertura riduce l’impatto della luce ambientale sulla precisione del sensore.

Breakout board per VL53L1X (source)

Il pinout ha gli stessi pin discussi sopra. SDA, SCL per I2C, GPIO1 come segnale di interrupt, XSHUT per la selezione del chip, e VIN e GND per l’alimentazione.

Collegamento del VL53L1X

Grazie all’interfaccia I2C del VL53L1X, collegarlo a un Arduino è semplice. Prima collega i pin SCL e SDA della breakout board VL53L1X ai corrispondenti pin sull’Arduino come mostrato sotto. Poi collega il GND a massa e il 3.3V a VIN del VL53L1X.

Connecting VL53L1X with Arduino
Collegamento VL53L1X con Arduino

La breakout board VL53L1X funziona a 5V o 3.3V e puoi usare uno dei due per VIN. Qui uso 3.3V per VIN. Ora scriviamo un po’ di codice per testare il funzionamento del sensore VL53L1X.

Codice per misurare la distanza con VL53L1X

Prima di poter misurare distanze con il sensore VL53L1X, devi installare una libreria. Le più comuni sono la Adafruit VL53L1X Library e la VL53L1X Library by Pololu. Tuttavia, ho avuto problemi con le librerie Adafruit mentre scrivevo il tutorial per il VL53L0X Distance Sensor, quindi userò la VL53L1X Library by Pololu. Offre anche più opzioni di configurazione per il VL53L1X.

Installazione della libreria VL53L1X di Pololu

Per installare la VL53L1X Library by Pololu, apri il Library Manager, cerca VL53L1X, trova quella di Pololu e installa. L’immagine sotto mostra come appare una volta installata la libreria:

Installing VL53L1X Library by Pololu via Library Manager
Installazione della libreria VL53L1X di Pololu tramite Library Manager

Con la libreria installata, proviamo il sensore. Il codice seguente legge le distanze misurate dal VL53L1X e le stampa sul monitor seriale.

#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);
}

Analizziamo il codice nelle sue componenti per capirlo meglio.

Inclusione della libreria

Il codice inizia includendo la libreria necessaria per il sensore VL53L1X. Questa libreria fornisce le funzioni per comunicare con il sensore.

#include "VL53L1X.h"

Creazione di un oggetto sensore

Successivamente, creiamo un’istanza della classe VL53L1X, che ci permette di interagire con il sensore.

VL53L1X sensor;

Funzione di inizializzazione del sensore

La funzione sensor_init() si occupa di inizializzare il sensore. Prende due parametri: range_mode che specifica la modalità di misura della distanza, e high_speed che determina il budget temporale della misura.

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);
}

All’interno di questa funzione:

  • Wire.begin(); inizializza la comunicazione I2C.
  • sensor.setTimeout(500); imposta un timeout per le operazioni del sensore.
  • sensor.init(); inizializza il sensore.
  • sensor.setDistanceMode(range_mode); imposta la modalità di distanza in base al parametro di input.
  • Il budget temporale della misura è impostato in base alla richiesta di alta velocità.

Secondo il datasheet, il budget temporale del VL53L1X dovrebbe essere impostato come segue.

  • 20 ms è il budget temporale minimo e può essere usato solo in modalità distanza corta.
  • 33 ms è il budget temporale minimo che funziona per tutte le modalità di distanza.
  • 140 ms è il budget temporale che permette di raggiungere la distanza massima di 4 m (al buio su una superficie bianca) in modalità distanza lunga.

Nel codice uso 33 ms per la modalità veloce, poiché funziona con tutte le distanze, altrimenti 140 ms, che permette la distanza massima.

Per la modalità puoi usare le costanti predefinite VL53L1X::Short, VL53L1X::Medium o VL53L1X::Long. La distanza che il sensore può misurare dipende dalla modalità scelta e dalla luce ambientale. La tabella seguente dal datasheet del VL53L1X mostra queste dipendenze:

Maximum distance vs. distance mode under ambient light for VL53L1X
Distanza massima vs. modalità distanza sotto luce ambientale per VL53L1X

La modalità distanza lunga permette di raggiungere la distanza massima di 4 m – in condizioni ideali (al buio). In generale, la distanza di misura è influenzata dalla luce ambientale. La modalità distanza corta è più immune alla luce ambientale, ma la distanza massima è tipicamente limitata a 1,3 m.

Funzione Setup

Nella funzione setup(), avviamo la comunicazione seriale e inizializziamo il sensore con una modalità di distanza specifica.

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

Qui, Serial.begin(9600); imposta il monitor seriale a 9600 baud. La funzione sensor_init() è chiamata con VL53L1X::Medium come modalità di distanza e false per alta velocità, il che significa che il sensore opererà in modalità media distanza con un budget temporale più lungo.

Funzione Loop

Infine, nella funzione loop() leggiamo continuamente la distanza dal sensore e la stampiamo sul monitor seriale.

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

Se carichi ed esegui il codice, dovresti vedere le distanze misurate stampate sul monitor seriale.

Distances measured with VL53L1X printed on Serial Monitor
Distanze misurate con VL53L1X stampate sul monitor seriale

Nella sezione successiva aggiungeremo un OLED al nostro circuito e mostreremo le distanze su di esso, invece di stamparle sul monitor seriale.

Aggiungere un OLED per visualizzare i dati del VL53L1X

Poiché l’OLED è anch’esso un dispositivo I2C, collegarlo è semplice. Basta collegare SDA e SCL agli stessi pin a cui è collegato il sensore VL53L1X. E dato che l’OLED funziona a 3.3V, possiamo anche condividere le linee di alimentazione.

Connecting OLED and VL53L1X with Arduino
Collegamento OLED e VL53L1X con Arduino

Codice per visualizzare le distanze misurate dal VL53L1X sull’OLED

Il codice seguente legge le misure di distanza dal sensore VL53L1X e le visualizza sull’OLED. Dai un’occhiata veloce al codice completo, poi ne discuteremo i dettagli.

#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();
}

Analizziamo il codice nelle sue parti per capirlo meglio.

Inclusione delle librerie

All’inizio del codice includiamo le librerie necessarie per il progetto. La libreria Wire.h è usata per la comunicazione I2C, VL53L1X.h per interfacciarsi con il sensore di distanza VL53L1X, e Adafruit_SSD1306.h per controllare il display OLED.

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

Se non hai ancora installato la Adafruit_SSD1306 Library, dovrai farlo. Basta installarla tramite il Library Manager come al solito:

Adafruit_SSD1306 library installed in Library Manager
Libreria Adafruit_SSD1306 installata nel Library Manager

Nota che l’indirizzo I2C per il display OLED è impostato su 0x3C in oled.begin(). La maggior parte di questi piccoli OLED usa questo indirizzo (or 0x27) ma il tuo potrebbe essere diverso. Se non vedi nulla sull’OLED, probabilmente ha un indirizzo I2C differente e devi cambiarlo.

Se non conosci l’indirizzo I2C, dai un’occhiata al tutorial How to Interface the SSD1306 I2C OLED Graphic Display With Arduino per scoprirlo. Anche il tutorial Use SSD1306 I2C OLED Display With Arduino ti spiegherà come usare un OLED.

Inizializzazione degli oggetti

Successivamente, creiamo le istanze del display OLED e del sensore di distanza. Il display OLED è inizializzato con una larghezza di 128 pixel e un’altezza di 64 pixel. Il parametro &Wire indica che usiamo la libreria Wire per la comunicazione I2C, e -1 indica che non usiamo un pin di reset.

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

Funzione di inizializzazione del sensore

La funzione sensor_init() inizializza il sensore VL53L1X. Prende due parametri: range_mode per impostare la modalità di misura della distanza e high_speed per determinare il budget temporale della misura. All’interno della funzione, avviamo la comunicazione I2C, impostiamo un timeout per il sensore, lo inizializziamo e configuriamo la modalità di distanza. Il budget temporale è impostato in base all’abilitazione o meno dell’alta velocità.

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);
}

Funzione di inizializzazione OLED

La funzione oled_init() inizializza il display OLED. Inizia alimentando il display usando il parametro SSD1306_SWITCHCAPVCC e impostando l’indirizzo I2C a 0x3C. Impostiamo anche la dimensione del testo a 2 e il colore del testo a bianco.

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

Funzione di visualizzazione

La funzione display() si occupa di leggere la distanza dal sensore e mostrarla sullo schermo OLED. Prima dichiara un array statico di caratteri text per contenere la stringa della distanza. La distanza è letta in millimetri usando sensor.readRangeSingleMillimeters(), e il risultato è formattato nell’array text usando sprintf(). Il display OLED viene poi pulito, il cursore posizionato in un punto specifico, e la distanza stampata. Infine, il display viene aggiornato per mostrare il nuovo contenuto.

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();
}

Funzione Setup

Nella funzione setup() chiamiamo le funzioni di inizializzazione sia per il display OLED che per il sensore di distanza. Il sensore è inizializzato in modalità media distanza con alta velocità disabilitata.

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

Funzione Loop

Infine, la funzione loop() chiama continuamente la funzione display(), che aggiorna lo schermo OLED con l’ultima misura di distanza dal sensore. Questo ciclo gira indefinitamente, fornendo letture di distanza in tempo reale.

void loop() {
  display();
}

Conclusioni

In questo tutorial hai imparato come usare il sensore di distanza VL53L1X con un Arduino per misurare distanze e visualizzarle su un OLED.

Il sensore VL53L1X è un sensore molto piccolo, veloce e ad alta precisione che usa luce laser a infrarossi per misurare distanze. Il VL53L1X è quasi identico al VL53L0X ma ha un range maggiore. Il primo può misurare distanze fino a 400 cm, mentre il secondo è limitato a 200 cm. Se ti serve un sensore per distanze molto più grandi, dai un’occhiata al TF Luna che può misurare distanze fino a 8 metri.

Un altro sensore laser simile che usa il metodo Time-of-Flight è il sensore TOF10120. Tuttavia, il VL53L1X offre più opzioni di configurazione (distanza lunga, alta velocità) e ha un range maggiore (fino a 400 cm contro 180 cm).

Altri comuni sensori di distanza a infrarossi come il GP2Y0A710K0F o il GP2Y0A21YK0F usano la triangolazione per determinare la distanza basandosi sull’angolo della luce IR riflessa e hanno un range più corto e minore precisione.

Se hai domande, sentiti libero di lasciarle nella sezione commenti.

Buon divertimento con il tinkering ; )