Aller au contenu

Module VL53L0X : caractéristiques de ce Capteur de Distance Infrarouge I2C, branchement sur Arduino + exemples de code

Tutorial VL53L0X arduino avec explication fonctionnement capteur infrarouge, raccordement à l'Arduino Uno, pilotage d'un module IR ou plusieurs en I2C

Récemment, nous avons vu ensemble le capteur à ultrasons HC-SR04, ainsi que ses forces et ses faiblesses. Aujourd’hui, je vous propose de découvrir quelque chose de complémentaire/alternatif aux ultrasons : le capteur à infrarouges VL53L0X i2c (aussi appelé « capteur IR »).

Dans cet article, nous verrons comment fonctionne la mesure de distance par infrarouges (mesures IR), quelles sont les caractéristiques du module VL53L0X (mini plaquette PCB, prête à l’emploi), et des exemples de code Arduino avec un ou plusieurs capteurs de ces capteurs infrarouges ! Ça vous dit ? Alors en avant !

Ce contenu vous plaît ? Alors abonnez-vous à la Newsletter pour ne rien louper !

Remarque : bien que j’utilise un Arduino Uno dans ce tuto, le capteur infrarouge VL53L0X peut aussi bien fonctionner avec un ESP32, STM32, RP2040 (Raspberry Pi Pico), ou même ATtiny (du moment où il y a suffisamment de mémoire). Aussi, faites bien attention au terme « VL53L0X », qui désigne ici aussi bien la puce VL53L0X de chez STMicroelectronics en elle-même, que la mini carte PCB prête à l’emploi (aussi appelé « module VL53L0X » ou « breakout board »). Comme ça vous ne serez pas surpris dans cet article, si j’emploi ce terme indifféremment, pour désigner l’un ou l’autre 😉

Module Description Lien
Mini capteur IR VL53L0X en version module prêt à souder, pour tuto passionelectronique.fr, pour débutants en électronique ou passionnés amateur d'électronique ! Capteur infrarouge VL53LOX
(pour mesures de distances)

Comment fonctionne la mesure de distances par infrarouges ?

La mesure de distances par infrarouges peut se faire de différentes manières. Ici, je vais vous expliquer comment fonctionne l’une d’elles (celle du capteur VL53L0X que je vous présente dans ce tuto), qui repose sur un principe similaire à l’écho sonore :

  • on envoie un signal (infrarouge, ici)
  • on mesure le temps que met ce signal pour revenir, ou plus exactement le temps qu’il aura mis pour faire l’aller/retour (c’est ce qu’on appelle son « temps de vol »). Si le faisceau a rencontré un obstacle, alors une partie sera réfléchie, telle un écho sonore sur une paroi)
  • et on en déduit une distance (du fait qu’on connait la vitesse de la lumière, environ égale à 3×108 m/s)

C’est pour ça que les capteurs infrarouges (IR) de mesure de distances à « temps de vol », comme le VL53L0X, sont constitués de 3 parties :

  • un émetteur, qui émet des signaux infrarouges (invisibles à l’œil nu)
  • un récepteur photosensible, qui est chargé de détecter les rayons lumineux réfléchis
  • et une partie électronique permettant de piloter l’émetteur, de traiter les infos captées par le récepteur, et de les mettre à disposition pour l’utilisateur

Voici une représentation de capteur IR (infrarouge), avec :
– la partie émission lumineuse/infrarouge en bas (qui ne part pas en ligne droite, mais se diffuse sous forme de cône, d’environ 35° d’ouverture)
– et la partie réception en haut (avec son « cône de réception » d’environ 25° d’ouverture, qui représente la zone à partir de laquelle le récepteur peut collecter de la lumière)

En cas d’obstacle, une partie des rayons infrarouges est réfléchie, et revient au récepteur qui les détecte, comme visible sur l’image ci-dessous :

Principe de mesure de distance par infrarouges, illustré par émetteur récepteur IR type VL53L0X, avec rayons émis sur surface réfléchissante et réflexion comme écho retour

Comme vous l’aurez certainement deviné, à partir de cette image, pour qu’une mesure soit possible, l’obstacle doit se trouver dans la zone couverte par l’émetteur IR, et réfléchir suffisamment de lumière vers le récepteur IR. Car oui, la qualité de la mesure de distance par infrarouges dépend de certains facteurs. En effet, la mesure sera optimale avec :

  • une surface claire, plutôt que noire
  • une surface mate, plutôt que brillante
  • une surface opaque, plutôt que transparente
  • et une surface « de face », plutôt qu’en biais 😉

Bien sûr, ne considérez pas ces règles comme absolues, mais de manière générale, les surfaces claires sont souvent plus favorables que les surfaces sombres à la réflexion des rayons infrarouges !

Caractéristiques et brochage du module infrarouge VL53L0X

Basiquement, le VL53L0X est une toute petite puce électronique, intégrant un laser infrarouge, et permettant de faire des mesures de distances. Il est fabriqué par STMicroelectronics (datasheet du VL53L0X ici).

Pour nous autres, bricoleurs/passionnés d’électronique, le VL53L0X s’utilise généralement sous la forme d’un module prêt à l’emploi (breakout board). Ainsi, il est très facile de le raccorder à un Arduino, un ESP32, ou autre, avec des fils dupont.

Cela étant dit, voyons à présent les caractéristiques principales du capteur infrarouge VL53L0X que je vais utiliser dans ce tuto, et son brochage.

Caractéristiques de la carte VL53L0X (émetteur/récepteur IR)

Voici les principales caractéristiques du module VL53L0X (mini carte PCB, prête à l’emploi) :

CaractéristiqueDescription
Tension d’alimentation2,6 à 5,5 V (module)

Nota : la puce VL53L0X en elle-même est alimentée en 2,8V, via un régulateur interne, embarqué sur la mini plaquette PCB
Technologie de mesureTemps de vol infrarouge (« Time of Flight » en anglais, ou simplement « ToF »)
CommunicationI²C (jusqu’à 400 kHz)
Adresse I2C0x29, par défaut (modifiable ensuite, logiciellement, mais ça restera éphémère)
Plage de mesure (par défaut)De 30 mm à 1200 mm (1,2 mètres, donc)
Plage de mesure étendueDe 30 mm à 2000 mm (en mode « Long Range »)
Unité de mesure (retour i2c)Millimètre (directement, sans besoin de conversion)
Format de la mesureValeur numérique sur 16 bits (donc 2 octets, transmis via le bus I2C)
Adaptation des niveaux logiquesIntégrée sur les lignes SDA et SCL (le module est donc compatible 3,3V ou 5V sans problème, par exemple !)
Précision de mesure±3 % à 1,2 m
Justesse de mesureTrès relative, car le fait de souder ce composant CMS (refusion) peut altérer le calibrage d’usine. Ainsi, on peut par exemple avoir des écarts (offset) de mesure allant de 20 à 40 mm, par rapport à la « réalité ». Je vous en toucherai un mot, à la fin de cet article/tuto.
Champ de visionCône de 25°, côté récepteur (et 35° côté émetteur, pour info)
Durée de mesureDe 20 ms (haute vitesse) à 200 ms (haute précision)
Longueur d’onde (rayons IR)940 nm (invisible à l’œil nu)
Consommation au repos5 µA
Consommation moyenne20 mA environ (typiquement, en fonctionnement)
Pics de consommation40 mA (courant max ponctuel, en fonctionnement)
Broches (module)VIN (ou VCC), GND, SDA, SCL, GPIO1, et XSHUT

Cela étant vu, passons à la partie brochage du module VL53L0X, à proprement parler !

Brochage d’une carte VL53L0X (pinout de la breakout board)

Voici le brochage (pinout) typique d’un module VL53L0X (breakout board) :

VL53L0X pinout avec alimentation VIN/GND de 2,6 à 5,5V et broches I²C horloge SCL et données SDA, plus sortie d'interruption GPIO1 et entrée XSHUT pour activer ou non la puce

Comme vous pouvez le constater, on retrouve ici :

  • une alim à fournir entre VIN et GND (entre 2.6V et 5.5V, comme vu précédemment)
  • le bus I2C à raccorder sur les broches SDA et SCL
  • une sortie optionnelle d’interruption programmable (GPIO1)
  • et une entrée optionnelle d’activation/désactivation du module (XSHUT), qu’il faut :
    • mettre à la masse lorsqu’on souhaite désactiver un module (XSHUT à 0, donc)
    • laisser déconnectée lorsqu’on souhaite (ré)activer le module (nota : une résistance pull-up, reliée en interne au +2,8V, permet alors de ramener cette ligne XSHUT à l’état haut)

Cela étant vu, découvrez maintenant comment câbler cette carte VL53L0X à une carte Arduino 🙂

Module Description Lien
Mini capteur IR VL53L0X en version module prêt à souder, pour tuto passionelectronique.fr, pour débutants en électronique ou passionnés amateur d'électronique ! Capteur infrarouge VL53LOX
(pour mesures de distances)

Comment raccorder un capteur VL53L0X à un Arduino Uno ?

Pour connecter un capteur à infrarouges VL53L0X à un Arduino Uno, rien de plus simple ! Car il suffit simplement de brancher une alim et le bus I2C, et le tour est joué ! La preuve, en image :

Wiring Arduino Uno VL53L0X breakout board, avec connexion des fils d'alimentation 5V et GND, ainsi que liaison série i2c via lignes SDA et SCL sur pins A4 et A5

Pour rappel, sur une carte Arduino Uno, les broches I²C se retrouvent sur :

  • pin A4 = SDA (lignes de données i2c)
  • pin A5 = SCL (ligne d’horloge i2c)

Et comme les résistances pull-up sur SDA et sur SCL sont déjà intégrées dans la breakout board (module/pcb) VL53L0X, nous n’avons donc pas besoin d’en prévoir/rajouter !

Nota : les pull-up i2c, côté module VL53L0X, sont reliées au rail d’alimentation Vin. Donc si vous alimentez le module en +5V ou +3,3V au niveau de Vin, les pull-up tireront les lignes I2C vers 5 volts ou 3,3 volts. Et bien sûr, ceci est ensuite adapté pour que la puce VL53L0X, elle, reçoive/émette des signaux en +2.8V, à son niveau !

Maintenant que nous avons vu la partie matérielle, passons à la partie logicielle !

Quelle librairie utiliser pour interagir avec ce capteur de distance ? (Pololu)

Pour ce tuto, j’ai choisi de partir sur la librairie « VL53L0X développée par Pololu », car elle est simple à utiliser, et compatible avec un « grand nombre » de microcontrôleurs. Donc si vous débutez, je vous la recommande vraiment. Ensuite, libre à vous d’en changer si le cœur vous en dit, car il en existe plein d’autres !

Pour l’installer dans Arduino IDE, il faut tout d’abord cliquer dans le menu Outils > Gérer de bibliothèques, taper « VL53L0X » dans le champ de recherche et valider. Ainsi, face à vous se retrouvera alors tout un tas de librairies arduino ayant le mot clef « vl53l0x » dedans, et il va falloir descendre dans la liste pour trouver celle de Pololu, comme visible ci-dessous :

Aperçu librairie VL53L0X dans gestionnaire de bibliothèque de l'IDE Arduino, affichage de celle de Pololu pour une grande compatibilité Arduino ESP32 etc

Il ne reste plus qu’à cliquer sur cette ligne, et cliquer sur « Installer », pour lancer l’installation de cette librairie dans l’IDE Arduino. Une fois fait, la mention « Installé » doit apparaître à l’écran (si jamais la liste « remonte en haut », il faudra « redescendre » pour retrouver cette librairie pololu !) :

Bibliothèque Arduino VL53L0X by Pololu installée dans l'IDE arduino, pour pouvoir faire des mesures de distances par rayons infrarouges émis et captés en retour

Important : attention à ne pas choisir une autre bibliothèque, portant un nom similaire ou approchant ! Sinon les explications et exemples de codes qui suivent risquent de ne pas fonctionner !

Maintenant que cette librairie est installée, vous pourrez l’inclure dans n’importe lequel de vos sketchs arduino, en ajoutant la ligne « #include <VL53L0X.h> » au début de vos programmes.

Au passage, voici les principales fonctions de cette librairie VL53L0X de chez Pololu :

  • init() : initialise le capteur, et indique si l’initialisation a réussi
  • setTimeout() : définit un délai maximal d’attente, pour les mesures (sans quoi le timeout est désactivé, par défaut)
  • setMeasurementTimingBudget() : ajuste le temps consacré à chaque mesure, afin de privilégier la rapidité ou la précision (valeur = 33000 µs, par défaut, et ça convient aux mesures « classiques »)
  • startContinuous() : démarre les mesures en continu (si aucune valeur n’est précisée entre parenthèses, alors les lectures se feront « à la vitesse max » ! Mais vous pouvez préciser une période en millisecondes, pour réduire la consommation électrique, par exemple.
  • readRangeContinuousMillimeters() : récupère une mesure lorsque le mode continu est activé
  • timeoutOccurred() : indique si ce délai a été dépassé (1 si timeout atteint, sinon 0)
  • setAddress() : attribue une nouvelle adresse I²C au capteur, logiciellement, qui sera réinitialisée après coupure d’alimentation (nous verrons ça dans l’exemple de code #2)
  • readRangeSingleMillimeters() : effectue une mesure unique (cas où le mode « continu » n’est pas activé/souhaité)

À cela s’ajoute bon nombre d’autres fonctions secondaires, mais aussi plus spécifiques, comme readReg (que vous verrez dans l’exemple de code #1), setSignalRateLimit, setVcselPulsePeriod, … mais pour ne pas vous noyer dans ce tuto introductif au VL53L0X, je ne vais pas plus entrer dans les détails ici !

Module Description Lien
Mini capteur IR VL53L0X en version module prêt à souder, pour tuto passionelectronique.fr, pour débutants en électronique ou passionnés amateur d'électronique ! Capteur infrarouge VL53LOX
(pour mesures de distances)

Exemple de code #1 : mesure de distance avec 1 capteur VL53L0X (librairie Pololu)

Pour commencer, voyons un premier exemple de code arduino, permettant de faire des mesures de distances toutes les secondes, avec un capteur VL53L0X. Ou plutôt : voyons comment câbler les choses pour commencer, et le code détaillé ensuite 😉

D’un point de vue matériel, il faudra reprendre le câblage que je vous avais présenté au point « 3) Comment raccorder un capteur VL53L0X à un Arduino Uno ? », à savoir :

  • le +5V de la carte Arduino Uno sur l’entrée VIN du VL53L0X
  • le GND arduino sur le GND du VL53L0X
  • la pin A5 arduino sur la broche SCL du VL53L0X
  • et la pin A4 arduino sur le broche SDA du VL53L0X

Voici à quoi le raccordement Arduino Uno ↔ Capteur IR VL53L0X ressemble de mon côté, sur breadboard :

Cela étant vu, passons au programme arduino à présent. Le voici :

// ===================================================================================================
//   ______               _                  _///_ _           _                   _
//  /   _  \             (_)                |  ___| |         | |                 (_)
//  |  [_|  |__  ___  ___ _  ___  _ __      | |__ | | ___  ___| |_ _ __ ___  _ __  _  ___  _   _  ___
//  |   ___/ _ \| __|| __| |/ _ \| '_ \_____|  __|| |/ _ \/  _|  _| '__/   \| '_ \| |/   \| | | |/ _ \
//  |  |  | ( ) |__ ||__ | | ( ) | | | |____| |__ | |  __/| (_| |_| | | (_) | | | | | (_) | |_| |  __/
//  \__|   \__,_|___||___|_|\___/|_| [_|    \____/|_|\___|\____\__\_|  \___/|_| |_|_|\__  |\__,_|\___|
//                                                                                      | |
//                                                                                      \_|
// ===================================================================================================
//
//  Fichier     :       prg1-Test-avec-un-seul-VL53L0X.ino
//
//  Descriptif  :       Programme de test pour capteur infrarouge VL53L0X (breakout board GY-530 / CJVL53L0XV2),
//                      affichant des mesures de distances toutes les secondes, sur le moniteur série
//
//  Créé le     :       15.08.2026
//  Auteur      :       Jérôme TOMSKI
//  Site        :       https://passionelectronique.fr/
//  GitHub      :       https://github.com/PassionElectronique/Programmes-tests-capteur-VL53L0X
//  Licence     :       https://creativecommons.org/licenses/by-nc-nd/4.0/deed.fr (BY-NC-ND 4.0 CC)
//
// ==============================================================================================================
//
//  Prérequis   :       Avoir installé la librairie "VL53L0X" de "Pololu"
//
//  Câblage     :       |------------|--------------|
//                      |  VL53L0X   | Arduino Uno  |
//                      |------------|--------------|
//                      | VCC ou VIN |      5V      |
//                      |    GND     |     GND      |
//                      |    SCL     |   A5 / SCL   |
//                      |    SDA     |   A4 / SDA   |
//                      |   GPIO1    | Non connecté |
//                      |   XSHUT    | Non connecté |
//                      |------------|--------------|
//
// ==============================================================================================================


// Inclusion des librairies dont nous aurons besoin ici
#include <Wire.h>
#include <VL53L0X.h>

// Création d'une objet "capteurIR", à partir de la bibliothèque VL53L0X
VL53L0X capteurIR;


// ========================
// Initialisation programme
// ========================
void setup() {

  // -------------------------
  // Initialisation port série
  // -------------------------
  Serial.begin(9600);
  delay(500);
  Serial.println();
  Serial.println(F("-----------------------"));
  Serial.println(F("Test du capteur VL53L0X"));
  Serial.println(F("-----------------------"));

  // ----------------------
  // Initialisation bus I2C
  // ----------------------
  Wire.begin();
  Wire.setClock(100000);              // I2C "standard", à 100 kHz

  // ---------------------------
  // Préconfiguration capteur IR
  // ---------------------------
  capteurIR.setTimeout(500);          // Durée maximale d'attente d'une mesure, en ms (millisecondes)

  // -------------------------
  // Initialisation capteur IR
  // -------------------------
  Serial.println(F("Initialisation du capteur infrarouge VL53L0X..."));
  if (!capteurIR.init()) {
    Serial.println(F("[ERREUR] Capteur VL53L0X non détecté !"));
    while (1) {}  // Boucle sans fin
  }
  Serial.println(F("VL53L0X initialisé avec succès !"));
  Serial.println();

  // ----------------------------------------------
  // Affichage du "Model ID" et de la "Revision ID" 
  // ----------------------------------------------
  uint8_t modelId = capteurIR.readReg(0xC0);
  uint8_t revisionId = capteurIR.readReg(0xC2);

  Serial.print(F("Model ID    : 0x"));
  Serial.println(modelId, HEX);

  Serial.print(F("Revision ID : 0x"));
  Serial.println(revisionId, HEX);

  // ------------------------
  // Configuration capteur IR
  // ------------------------
  capteurIR.setMeasurementTimingBudget(33000);    // Paramètre "budget temporel", en microsecondes (basiquement 33 ms, soit 33000 µs)
  capteurIR.startContinuous();                    // Démarrage des mesures continues (nota : sans argument, les mesures sont réalisées les unes à la suite des autres)

  // ------------------------
  // Fin de la partie "setup"
  // ------------------------
  Serial.println(F("Mesures continues démarrées."));
  Serial.println();

}


// =================
// Boucle principale
// =================
void loop() {

  // ---------------------------------------
  // Lecture d'une distance (en millimètres)
  // ---------------------------------------
  uint16_t distance_mesuree_en_mm = capteurIR.readRangeContinuousMillimeters();

  // ---------
  // Affichage
  // ---------
  if (capteurIR.timeoutOccurred()) {
    // En cas de timeout (pas de mesure reçue dans le temps imparti, fixé à 500ms un peu plus haut), on affiche un message d'erreur
    Serial.println(F("ERREUR : mesure non reçue à temps (timeout)"));
  } else {
    // Et si pas d'erreur, on affiche la distance mesurée
    Serial.print(F("Distance = "));
    Serial.print(distance_mesuree_en_mm);
    Serial.println(F(" mm"));
  }

  // ---------------------------------------------------------
  // Pause d'une seconde, avant rebouclage de la fonction loop
  // ---------------------------------------------------------
  delay(1000);

}

Comme vous pouvez le constater, je vous ai mis un maximum de commentaires dans ce code arduino VL53L0X, afin de faciliter la compréhension de celui-ci ! Sinon, dans les grandes lignes, voici ce que fait ce programme :

  • en partie « setup » (au démarrage de l’arduino uniquement, donc) :
    • on fixe le timeout du capteur IR (durée au-delà de laquelle on considère qu’on n’a pas reçu de réponse de sa part)
    • on initialise le capteur, et on affiche le résultat de cette initialisation (et on stoppe le programme, en cas d’échec)
    • on lit 2 de ses registres (optionnel, uniquement pour vous en faire la démo)
    • on fixe un budget temps (optionnel, juste pour vous montrer comment changer cette valeur, fixée à 33 ms par défaut)
    • on lance les mesures perpétuelles (comme ça le VL53L0X va faire des mesures en permanence, et on aura juste qu’à récupérer la dernière mesure effectuée par le capteur)
  • en partie « loop » (boucle sans fin) :
    • on demande au capteur de nous retourner la dernière mesure qu’il a fait (valeur 16 bits, donnant une distance exprimée en millimètres)
    • on affiche cette valeur sur le port série
    • et on fait une pause d’une seconde, avant de reboucler à l’infini !

Pour visualiser tout ce process, il suffit d’uploader ce programme dans l’Arduino Uno, d’ouvrir le moniteur série de l’IDE Arduino, et d’observer ce qui est retourné. Pour ma part, voici ce que j’ai obtenu, de mon côté (en ayant mis un obstacle à 1,2m environ, et puis en l’ayant rapproché jusqu’à 2cm du capteur environ) :

Moniteur série Arduino montrant des mesures I2C d'un capteur VL53L0X effectuées toutes les secondes, affichage en millimètre des distances mesurées par arduino

À noter qu’en cas d’erreur d’initialisation I2C, on obtient le message suivant (chose que j’ai simulé de mon côté, en débranchant la liaison I2C) :

Exemple échec initialisation i2c visible sur moniteur série, lors d'une tentative de démarrage arduino avec un capteur IR modèle VL53L0X branché sur le bus I²C en A4/A5

À présent, compliquons un peu les choses, et voyons comment brancher plusieurs capteurs IR VL53L0X sur un seul et même bus I2C !

Module Description Lien
Mini capteur IR VL53L0X en version module prêt à souder, pour tuto passionelectronique.fr, pour débutants en électronique ou passionnés amateur d'électronique ! Capteur infrarouge VL53LOX
(pour mesures de distances)

Exemple de code #2 : mesure de distance avec plusieurs capteurs VL53L0X

Dans cette partie, nous allons voir comment brancher 2 capteurs VL53L0X sur le même bus I2C (et la logique sera la même pour 3, 4, ou encore plus de capteurs IR sur un unique bus I²C).

La difficulté, comme vous l’aurez peut-être deviné, concerne l’adresse i2c de ces capteurs. Car :

  • on ne peut pas avoir 2 périphériques I²C avec la même adresse, sur un seul et même bus I2C
  • et il n’y a pas de broche physique sur un module VL53L0X, pour changer d’adresse I2C au niveau de chaque capteur

Mais rassurez-vous, car il y a une façon toute simple pour résoudre ce soucis ! En effet, le fabricant sur VL53L0X, STMicroelectronics, nous offre la possibilité de changer « logiciellement » l’adresse I2C d’un capteur. Pour réaliser cette opération, il va falloir activer tous les modules séparément, l’un après l’autre, afin de re-paramétrer chaque adresse I2C, au besoin.

Pour ce faire, on va utiliser la broche XSHUT de chaque module, qui permet, lorsqu’elle est mise à la masse, de désactiver un module. Il suffira donc d’activer qu’un seul VL53L0X à la fois en laissant sa broche XSHUT à l’état haut (tout les autres modules devront avoir leur broche XSHUT à l’état bas), de changer son adresse, puis de passer au suivant, en répétant cette opération jusqu’au dernier.

Ici, pour que ça reste simple, je vous ai fait un montage-exemple à 2 capteurs VL53L0X uniquement. En sachant que le principe restera le même, que vous ayez 2, 3, 4, … ou plus de capteurs branchés en parallèle sur le bus I2C (à ceci près qu’il faudra tout de même faire attention à ne pas en mettre trop sur un seul et même bus I²C, sinon on va tirer trop de courant avec toutes les pull-up en doublon, présentes sur les breakout board, au niveau des lignes SDA et SCL, à moins d’en dessouder quelques unes).

Voici le câblage à réaliser pour ce 2ème exemple avec le VL53L0X et Arduino Uno :

Raccordement multiple VL53L0X sur Arduino, câblage des lignes XSHUT sur la carte arduino et mise en commun de l'alimentation et des lignes I²C nommées SCL et SDA

Et voici ce que donne, une fois câblé sur breadboard, de mon côté :

Remarque : ici, comme les 2 capteurs pointent dans la même direction, nous n’allons pas utiliser le mode de lectures continues (fonctions « startContinuous » et « readRangeContinuousMillimeters » de la librairie Pololu), mais plutôt utiliser le mode de lecture à la demande, nommé « single » (fonction « readRangeSingleMillimeters »). Sans quoi les signaux lumineux réfléchis d’un capteur reviendraient sur l’autre, et vice-versa, et entraîneraient des potentielles erreurs de mesure. Une alternative aurait été de mettre ces capteurs en biais ou de les éloigner suffisamment, afin que leur faisceaux lumineux ne se croisent pas.

Maintenant que la partie matérielle est faite, passons à la partie logicielle, et jetons un coup d’œil à ce 2ème programme arduino, permettant d’effectuer des mesures de distances avec 2 capteurs VL53L0X :

// ===================================================================================================
//   ______               _                  _///_ _           _                   _
//  /   _  \             (_)                |  ___| |         | |                 (_)
//  |  [_|  |__  ___  ___ _  ___  _ __      | |__ | | ___  ___| |_ _ __ ___  _ __  _  ___  _   _  ___
//  |   ___/ _ \| __|| __| |/ _ \| '_ \_____|  __|| |/ _ \/  _|  _| '__/   \| '_ \| |/   \| | | |/ _ \
//  |  |  | ( ) |__ ||__ | | ( ) | | | |____| |__ | |  __/| (_| |_| | | (_) | | | | | (_) | |_| |  __/
//  \__|   \__,_|___||___|_|\___/|_| [_|    \____/|_|\___|\____\__\_|  \___/|_| |_|_|\__  |\__,_|\___|
//                                                                                      | |
//                                                                                      \_|
// ===================================================================================================
//
//  Fichier     :       prg2-Test-avec-deux-VL53L0X.ino
//
//  Descriptif  :       Programme de test pour 2 capteurs infrarouges VL53L0X (breakout board GY-530 / CJVL53L0XV2),
//                      avec reprogrammation de leur adresse I²C (base = 0x29), puis affichage de leurs mesures
//                      de distances toutes les secondes, sur le moniteur série
//
//  Créé le     :       16.08.2026
//  Auteur      :       Jérôme TOMSKI
//  Site        :       https://passionelectronique.fr/
//  GitHub      :       https://github.com/PassionElectronique/Programmes-tests-capteur-VL53L0X
//  Licence     :       https://creativecommons.org/licenses/by-nc-nd/4.0/deed.fr (BY-NC-ND 4.0 CC)
//
// ==============================================================================================================
//
//  Prérequis   :       Avoir installé la librairie "VL53L0X" de "Pololu"
//
//  Câblage     :       /-----------|-----------|--------------\
//                      | Capteur 1 | Capteur 2 | Arduino Uno  |
//                      |-----------|-----------|--------------|
//                      |    VIN    |    VIN    |      5V      |
//                      |    GND    |    GND    |     GND      |
//                      |    SDA    |    SDA    |   A4 (SDA)   |
//                      |    SCL    |    SCL    |   A5 (SCL)   |
//                      |   XSHUT   |    ---    |      D2      |
//                      |    ---    |   XSHUT   |      D3      |
//                      |   GPIO1   |   GPIO1   | Non connecté |
//                      \-----------|-----------|--------------/
//
//  Remarque    :       On arrête un VL53L0X en forçant sa broche XSHUT au niveau bas ; à l'inverse, il faut
//                      se déconnecter de cette broche pour qu'elle puisse revenir au niveau haut toute seule,
//                      via sa pull-up embarquée, pour réactiver le capteur
//
// ==============================================================================================================


// Inclusion des librairies dont nous aurons besoin ici
#include <Wire.h>
#include <VL53L0X.h>

// Création de deux objets "capteurIR_xxx", à partir de la bibliothèque VL53L0X
VL53L0X capteurIR_1;
VL53L0X capteurIR_2;

// Adresses I2C qu'on souhaite attribuer à ces capteurs (de base 0x29). Nota : bien qu'on puisse théoriquement mettre ici n'importe quelle
// valeur entre 0 et 127, mieux vaut se limiter aux adresses allant de 0x08 à 0x77 incluses, pour éviter les adresses "réservées".
constexpr uint8_t ADRESSE_CAPTEUR_1 = 0x30;     // Une fois configurée, la nouvelle adresse i2c du capteur #1 sera 0x30
constexpr uint8_t ADRESSE_CAPTEUR_2 = 0x31;     // Une fois configurée, la nouvelle adresse i2c du capteur #2 sera 0x31

// Affectation de leurs broches XSHUT sur l'Arduino Uno
constexpr uint8_t XSHUT_CAPTEUR_1 = 2;          // Le XSHUT du capteur #1 sera branché sur la pin D2 de l'Arduino Uno
constexpr uint8_t XSHUT_CAPTEUR_2 = 3;          // Le XSHUT du capteur #2 sera branché sur la pin D3 de l'Arduino Uno


// ========================
// Initialisation programme
// ========================
void setup() {

  // -------------------------
  // Initialisation port série
  // -------------------------
  Serial.begin(9600);
  delay(500);
  Serial.println();
  Serial.println(F("--------------------------"));
  Serial.println(F("Test de 2 capteurs VL53L0X"));
  Serial.println(F("--------------------------"));

  // -----------------------
  // Préparation capteurs IR
  // -----------------------
  desactiveCapteur(XSHUT_CAPTEUR_1);    // Il faut impérativement commencer par arrêter ces 2 capteurs, car tous deux
  desactiveCapteur(XSHUT_CAPTEUR_2);    // possèdent l'adresse I2C 0x29, à la mise sous tension !
  delay(100);

  // ----------------------
  // Initialisation bus I2C
  // ----------------------
  Wire.begin();
  Wire.setClock(100000);              // I2C "standard", à 100 kHz

  // ---------------------------
  // Configuration du capteur #1
  // ---------------------------
  Serial.println(F("Activation du capteur #1..."));
  activeCapteur(XSHUT_CAPTEUR_1);
  delay(100);
  
  capteurIR_1.setTimeout(500);
  if (!capteurIR_1.init()) stoppeProgramme(F("[ERREUR] Capteur #1 non détecté, à son adresse de base '0x29' !"));

  capteurIR_1.setAddress(ADRESSE_CAPTEUR_1);
  Serial.print(F("[RÉUSSI] Capteur #1 configuré à l'adresse 0x"));
  Serial.print(ADRESSE_CAPTEUR_1, HEX); Serial.print(F(" !"));
  
  if (!capteurIR_1.setMeasurementTimingBudget(33000)) stoppeProgramme(F("[ERREUR] Impossible de fixer le budget temporel pour le capteur #1"));
  Serial.println();

  // ---------------------------
  // Configuration du capteur #2
  // ---------------------------
  Serial.println(F("Activation du capteur #2..."));
  activeCapteur(XSHUT_CAPTEUR_2);
  delay(100);
  
  capteurIR_2.setTimeout(500);
  if (!capteurIR_2.init()) stoppeProgramme(F("[ERREUR] Capteur #2 non détecté, à son adresse de base '0x29' !"));

  capteurIR_2.setAddress(ADRESSE_CAPTEUR_2);
  Serial.print(F("[RÉUSSI] Capteur #2 configuré à l'adresse 0x"));
  Serial.print(ADRESSE_CAPTEUR_2, HEX); Serial.print(F(" !"));
  
  if (!capteurIR_2.setMeasurementTimingBudget(33000)) stoppeProgramme(F("[ERREUR] Impossible de fixer le budget temporel pour le capteur #2"));
  Serial.println();

  // ------------------------
  // Fin de la partie "setup"
  // ------------------------
  Serial.println(F("Les deux capteurs sont opérationnels !"));
  Serial.println();
  Serial.println(F("Capteur 1 | Capteur 2"));
}


// =================
// Boucle principale
// =================
void loop() {

  // --------------------------------
  // Lecture de distances (capteur 1)
  // --------------------------------
  uint16_t distance_en_mm_mesuree_capteur_1 = capteurIR_1.readRangeSingleMillimeters();
  bool timeout_capteur_1 = capteurIR_1.timeoutOccurred();

  // --------------------------------
  // Lecture de distances (capteur 2)
  // --------------------------------
  uint16_t distance_en_mm_mesuree_capteur_2 = capteurIR_2.readRangeSingleMillimeters();
  bool timeout_capteur_2 = capteurIR_2.timeoutOccurred();

  // ---------
  // Affichage
  // ---------

  // Affichage de la mesure du 1er capteur
  Serial.print(F(" "));
  if (timeout_capteur_1) {
    Serial.print(F("TIMEOUT"));
  } else if (distance_en_mm_mesuree_capteur_1 <= 2000) {
    Serial.print(distance_en_mm_mesuree_capteur_1);   // Obstacle détecté (distance max = 2000 mm)
    Serial.print(F(" mm"));
  } else {
    Serial.print("  OUT  ");   // Obstacle hors de portée
  }

  // Séparateur
  Serial.print(F("  | "));

  // Affichage de la mesure du 2nd capteur
  Serial.print(F(" "));
  if (timeout_capteur_2) {
    Serial.println(F("TIMEOUT"));
  } else if (distance_en_mm_mesuree_capteur_2 <= 2000) {
    Serial.print(distance_en_mm_mesuree_capteur_2); // Mesure valide
    Serial.println(F(" mm"));
  } else {
    Serial.println("  OUT  ");   // Obstacle hors de portée
  }

  // ---------------------------------------------------------
  // Pause d'une seconde, avant rebouclage de la fonction loop
  // ---------------------------------------------------------
  delay(1000);

}


// ========================================================================
// Fonction : desactiveCapteur
// Rôle     : désactive le VL53L0X ciblé, en forçant son XSHUT à l'état bas
// ========================================================================
void desactiveCapteur(uint8_t pin) {
  digitalWrite(pin, LOW);     // On fixe la pin arduino à l'état bas
  pinMode(pin, OUTPUT);       // puis on la configure en sortie
}

// ===============================================================
// Fonction : activeCapteur
// Rôle     : active le VL53L0X ciblé, en libérant sa broche XSHUT
// ===============================================================
void activeCapteur(uint8_t pin) {
  pinMode(pin, INPUT);        // On configure la pin arduino en entrée ("haute impédance")

  // Remarque : ici, pour "physiquement" déconnecter l'Arduino Uno du module VL53L0X ciblé,
  //            on "ruse" en transformant la sortie arduino en entrée, ce qui a pour effet
  //            d'imposer ni niveau haut, ni niveau bas ; et côté VL53L0X, une pull-up
  //            permet de ramener XSHUT au niveau haut. Si on fait ainsi, c'est simplement
  //            pour une question de niveau de tension : un Arduino Uno travaille en 5V,
  //            tandis que la puce VL53L0X travaille à 2,8 volts !
}

// ===============================================================
// Fonction : activeCapteur
// Rôle     : active le VL53L0X ciblé, en libérant sa broche XSHUT
// ===============================================================
void stoppeProgramme(const __FlashStringHelper *message) {
  // Nota : "__FlashStringHelper" permet de récupérer un texte stocké en mémoire flash,
  //        issu de F(...texte...), toujours dans l'idée de ne pas surcharger la RAM
  
  Serial.println();
  Serial.println(message);
  Serial.println(F("Programme arrêté !"));
  while (1) {}  // Boucle sans fin
}

Dans cet exemple, j’ai changé l’adresse I2C de base :

  • du 1er capteur VL53L0X de 0x29 à 0x30
  • du 2ème capteur VL53L0X de 0x29 à 0x31

Nota : pour rappel, ces changements d’adresses I2C ne sont valables que jusqu’à la coupure d’alimentation. En effet, si on coupait et rallumait l’alimentation, alors les puces VL53L0X seraient réinitialisées, et leurs adresses i2c automatiquement remises à la valeur par défaut, à savoir 0x29 (d’où la nécessité de systématiquement reconfigurer les adresses I²C de chacun des modules, au démarrage du programme !).

Petite subtilité au sujet de la ligne XSHUT des capteurs VL53L0X : celle-ci doit être soit mise à la masse pour désactiver la puce, soit mise à +2,8V (tension d’alimentation de la puce) pour l’activer. Comme on utilise ici un Arduino Uno fonctionnant en 5V :

  • concernant la mise à la masse, rien de plus simple à faire avec une pin arduino, car il suffit de configurer la pin Arduino en sortie, et la mettre à l’état bas (0V)
  • concernant la mise au niveau haut (+2,8V), il ne faut évidemment pas environ les +5V issus de l’arduino, sans quoi la puce VL53L0X va griller. En fait, il suffit simplement de se déconnecter de cette ligne, pour la laisser revenir à 2,8 volts toute seule ; car une résistance pull-up, interne à la carte VL53L0X et branchée sur le +2,8V, permet de faire cela automatiquement !

C’est pourquoi, dans le programme :

  • lorsqu’on souhaite mettre XSHUT à l’état bas (désactivation du VL53L0X), on configure la ligne arduino correspondante en SORTIE, et on l’a met à la masse
  • lorsqu’on souhaite mettre XSHUT à l’état haut (activation du VL53L0X), on configure la ligne arduino correspondante en ENTRÉE, pour laisser la pull-up côté capteur emmener le niveau de cette ligne à +2,8V

Du reste, si tout va bien, une fois ce programme uploadé, vous devriez obtenir quelque chose de ce genre (là j’ai mis un obstacle à 30 cm environ, et l’ai rapproché jusqu’à ~ 2 cm) :

Moniteur série arduino affichant les mesures de plusieurs capteurs VL53L0X ayant des adresses I2C reconfigurées, différentes de 0x29, pour démo avec Arduino

Ne faites pas trop attention aux décalages de mesures, car je ne tenais pas mon obstacle (bloc de feuilles papier mat !) très droit, au moment des essais 😉

Module Description Lien
Mini capteur IR VL53L0X en version module prêt à souder, pour tuto passionelectronique.fr, pour débutants en électronique ou passionnés amateur d'électronique ! Capteur infrarouge VL53LOX
(pour mesures de distances)

[IMPORTANT] Décalages constatés en pratique (offset / écarts de mesure)

J’ai testé une bonne dizaine de module VL53L0X et ai constaté des écarts de mesures assez importants, allant de 20mm à 40mm en trop !

Ce décalage, aussi appelé offset en anglais, était constant, quelle que soit la mesure. Par exemple, si l’écart (offset) était de +25 mm, alors :

  • un obstacle situé à 50 mm donnait une mesure de distance à 75 mm (écart = +25)
  • un obstacle situé à 200 mm donnait une mesure de distance à 225 mm (écart = +25)
  • un obstacle situé à 1100 mm donnait une mesure de distance à 1125 mm (écart = +25)

Première chose qu’on peut dire : il est très facile de corriger cet écart logiciellement, dans un programme arduino, en ajoutant l’offset correspondant au capteur. Sauf que ce décalage est plus ou moins aléatoire d’un module VL53L0X à l’autre, et qu’il faut noter pour chacun de ces capteurs son décalage correspondant. Clairement, tout ça devient vite long et pénible !

Pour info, au début, j’avais pensé à un problème de qualité (puisque j’avais commandé mes premiers capteurs IR sur Aliexpress). Mais au bout d’un moment, je me suis aperçu que la qualité de ces modules VL53L0X laissait vraiment à désirer, et ce, quelque soit le vendeur. Du coup, je me suis mis à faire des recherches plus approfondies, au sujet de ce capteur IR.

Et à force de creuser, j’ai découvert une chose assez particulière : ce décalage est assez fréquent, et est consécutif au soudage (refusion) du capteur sur son PCB. En clair : lorsque vous soudez une puce VL53L0X, cela peut altérer son calibrage d’usine (chose reconnue par le fabricant, si je puis dire). D’où ces écarts de mesures, d’un capteur VL53L0X à un autre, et ce, quelque soit le fournisseur !

Et en creusant encore un peu plus, il s’avère que la plupart des modèles monozones comme le VL53L0X ont tous (plus ou moins) des soucis d’altération du calibrage fait en usine, au moment de la soudure sur PCB ! Bien sûr, j’imagine que ce problème sera résolu dans le temps, d’une manière ou d’une autre. Mais pour l’heure, c’est quelque chose qu’il faut bien avoir en tête, et ne pas être surpris par des mesures faussées (qu’on peut compenser logiciellement, sauf capteur endommagé, bien évidemment !).

À présent, faut il jeter ces capteurs VL53L0X à la « poubelle » ? Perso, je dirais non ! Car ils sont vraiment pas chers (comparé aux autres modèles IR, j’entends), et que par conséquent, il suffit d’évaluer leur erreur/écart de mesure, et de l’intégrer dans le code arduino.

Sinon, il existe des modèles multizones, comme le VL53L5CX (que je n’ai pas encore testé), où là, d’après ce que j’ai pu lire, la calibration reste valable même après refusion. Mais bon, c’est quelque chose d’un peu plus complexe à mettre en oeuvre, qui demande beaucoup plus de mémoire programme, et qui coûte bien plus cher à l’achat ! C’est pourquoi je préfère rester sur ces petits capteurs IR pas cher (VL53L0X), pour bricoler 😉

Liens et téléchargements

Pour ceux que ça intéresse, vous trouverez ici les liens vers :

Tuto VL53L0X : Conclusion !

Vous voici au terme de ce tuto introductif au capteur à infrarouges VL53L0X, et son branchement/pilotage avec Arduino ! J’espère que tout ceci vous aura plu, et pourra vous servir dans vos prochains montages !

Sur ce, je vous dit à bientôt, avec un tout nouveau projet expérimental, vous verrez 😉
Jérôme.

Module Description Lien
Mini capteur IR VL53L0X en version module prêt à souder, pour tuto passionelectronique.fr, pour débutants en électronique ou passionnés amateur d'électronique ! Capteur infrarouge VL53LOX
(pour mesures de distances)

À découvrir aussi : le capteur à ultrasons HC-SR04 (en version « P », compatible 3,3/5V)

Ce contenu vous plaît ? Alors abonnez-vous à la Newsletter pour ne rien louper !

(*) Mis à jour le 03/10/2026

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Symbole danger point d'exclamation site PSE, triangle jaune avec contour noir, texte noir alerte au milieuAfin de filtrer au maximum les messages de type "spam" ou "inappropriés", chaque commentaire est soumis à modération, et validé manuellement. Du coup, il se peut que certains commentaires ne soient pas publiés, ou sinon, avec un peu de retard. Par ailleurs, j'ai malheureusement plus de messages à traiter que de temps pour y répondre ; c'est pourquoi je ne pourrais pas répondre à tout le monde. Désolé …

Soutenir le site

×

Soutenez le site Passion Électronique, en faisant un don via Paypal ou Stripe, afin que celui-ci reste le plus longtemps possible 100% gratuit et sans pub !
→ Logo PayPal
Faire un don via : PayPal
→ Logo Stripe
Faire un don via : Stripe
Merci à vous ❤️