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 !
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 |
|---|---|---|
|
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 :

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éristique | Description |
|---|---|
| Tension d’alimentation | 2,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 mesure | Temps de vol infrarouge (« Time of Flight » en anglais, ou simplement « ToF ») |
| Communication | I²C (jusqu’à 400 kHz) |
| Adresse I2C | 0x29, 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 étendue | De 30 mm à 2000 mm (en mode « Long Range ») |
| Unité de mesure (retour i2c) | Millimètre (directement, sans besoin de conversion) |
| Format de la mesure | Valeur numérique sur 16 bits (donc 2 octets, transmis via le bus I2C) |
| Adaptation des niveaux logiques | Inté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 mesure | Trè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 vision | Cône de 25°, côté récepteur (et 35° côté émetteur, pour info) |
| Durée de mesure | De 20 ms (haute vitesse) à 200 ms (haute précision) |
| Longueur d’onde (rayons IR) | 940 nm (invisible à l’œil nu) |
| Consommation au repos | 5 µA |
| Consommation moyenne | 20 mA environ (typiquement, en fonctionnement) |
| Pics de consommation | 40 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) :

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 |
|---|---|---|
|
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 :

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 :

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 !) :

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 |
|---|---|---|
|
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) :

À 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) :

À 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 |
|---|---|---|
|
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 :

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) :

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 |
|---|---|---|
|
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 :
- le premier code arduino, avec 1 capteur VL53L0X (GitHub)
- le second code arduino, utilisant 2 capteurs VL53L0X (GitHub)
- le datasheet de la puce VL53L0X (source : st.com / STMicroelectronics)
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 |
|---|---|---|
|
Capteur infrarouge VL53LOX (pour mesures de distances) |
À découvrir aussi : le capteur à ultrasons HC-SR04 (en version « P », compatible 3,3/5V)
(*) Mis à jour le 03/10/2026

Afin 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é …