Télémètres infrarouge VL53L0X

Ce tutoriel explique comment mettre en œuvre le télémètre infrarouge VL53L0X de STMicroelectronics en MicroPython. Celui-ci utilise le protocole de communication I2C.

Le télémètre infrarouge VL53L0X Grove :


Grove - VL53L0X


Crédit image : Seeed Studio

Attention le capteur de distance est situé au verso du module Grove, sur la face opposée à celle du connecteur !

Le VL53L0X mesure la distance selon le même principe qu’un sonar ou un radar actif. Il émet une onde qui se propage devant lui jusqu’à ce qu’elle rencontre un obstacle qui la réfléchit partiellement. Lorsque l’onde réfléchie atteint le capteur, celui-ci la détecte et mesure le temps de son aller-retour. Connaissant la vitesse de propagation de l’onde, le VL53L0X calcule la distance à l’obstacle qui l’a renvoyée vers lui, c’est pourquoi on dit qu’il s’agit d’un capteur de temps de vol (ou time of flight en anglais, ce qui donne l’acronyme ToF).
Dans le cas d’un sonar l’onde utilisée est une onde sonore (des vibrations de l’air). Dans le cas du VL53L0X qui nous intéresse ici, c’est une onde électromagnétique cohérente (de la lumière laser) de fréquence (couleur) infrarouge.
La mesure de la distance est plus rapide et plus précise qu’avec un sonar. La portée maximum du VL53L0X est de deux mètres. Dans l’archive téléchargeable de cet exemple se trouve également le pilote du capteur VL53L1X, une version plus récente du VL53L0X ayant une portée de quatre mètres.

Matériel requis

  1. Une carte d’extension de base Grove
  2. La carte NUCLEO-WB55
  3. Un module télémètre infrarouge VL53L0X Grove (Time of Flight distance sensor)
  4. Un module buzzer Grove

Connectez le module VL53L0X à l’une des prises I2C de la carte d’extension de base Grove et le buzzer à la prise D6.

Le code MicroPython

Ce code a été adapté à partir de ce site.

Vous pouvez télécharger les scripts MicroPython de ce tutoriel (entre autres) en cliquant ici.

Il faut récupérer le fichier VL53L0X.py et le copier dans le répertoire du périphérique PYBFLASH.

Le programme réalise les fonctions suivantes :

  • Mise en œuvre de l’interruption périodique d’un timer pour générer des bips à une fréquence pilotable.
  • Ajustement dynamique de la fréquence du timer au moyen d’un capteur de distance VL53L0x.

La fréquence des bips du buzzer varie en fonction de la distance mesurée par le capteur (plus la distance est courte, plus les bips sont rapprochés). Il s’agit d’un mini radar de recul.

Editez maintenant le script main.py :

# Objet du Script : 
# Réalisation d'un télémètre avec une sortie sonore (type "radar de recul").
# Le buzzer émet des bips de fréquence variable, inversement proportionnelle 
# à la distance mesurée par le VL53L0x (plus la distance est courte, plus les bips 
# sont rapprochés).
# La distance mesurée par le VL53L0x est convertie en valeur de fréquence, 
# qui est ensuite attribuée à l'interruption de dépassement périodique d'un  
# timer, laquelle contrôle le buzzer.
# Matériel (en plus de la carte NUCLEO-WB55) :
# - un Grove Base Shield
# - un module buzzer Grove connecté sur D6 du Grove Base Shield.
# - un capteur Time of Flight Grove connecté sur une prise I2C du Grove Base Shield.
# Source : https://github.com/uceeatz/VL53L0X

from time import sleep_ms # Pour temporiser
import gc # Ramasse miettes, pour éviter de saturer la mémoire

# Fréquence du timer, en hertz
MIN_FREQUENCY_HZ = 0.25
MAX_FREQUENCY_HZ = 10.

# Bornage de l'intervalle de mesures du capteur, valeurs en mm
MIN_DIST_MM = const(1)
MAX_DIST_MM = const(1700)

frequency = MIN_FREQUENCY_HZ # Fréquence initiale du timer
distance = MAX_DIST_MM # distance initiale d'un supposé obstacle

# Initialisation de la broche du buzzer
buzzer_pin = pyb.Pin('D6', pyb.Pin.OUT_PP) 

timer_id = 1 # Timer sur D6

# Routine de service de l'interruption (ISR) de dépassement de compteur du timer 1.
# Génère un bip de 5 millisecondes
@micropython.native # Produit un bytecode optimisé pour STM32
def tick(timer):

	global distance
	
	if distance < MAX_DIST_MM:
		buzzer_pin.value(1)
		sleep_ms(55)
		buzzer_pin.value(0)
	else:
		buzzer_pin.value(0)
		
# Démarre le timer 1 à la fréquence de frequency Hz.
# Assigne la fonction "tick" à l'interruption de dépassement de compteur du timer 1.
tim1 = pyb.Timer(timer_id, freq=frequency, callback=tick)

from machine import I2C # Bibliothèque pour le bus I2C
import VL53L0X # Bibliothèque pour le VL53L0X

#Initialisation du bus I2C numéro 1 du STM32WB55 
i2c = I2C(1)

# Pause d'une seconde pour laisser à l'I2C le temps de s'initialiser
sleep_ms(1000)

tof = VL53L0X.VL53L0X(i2c) # Instance du capteur de distance

# Fonction pour remapper un intervalle de valeurs dans un autre
@micropython.native # Produit un bytecode optimisé pour STM32
def map (value, from_min, from_max, to_min, to_max):
	return (value-from_min) * (to_max-to_min) / (from_max-from_min) + to_min

# Fonction principale
@micropython.native  # Produit un bytecode optimisé pour STM32
def main():

	global distance
		
	sleep_ms(500) # Temporisation "de sécurité"
	tof.start() # démarrage du capteur
	tof.read() # Première mesure "à blanc"
	sleep_ms(500) # Temporisation "de sécurité"

	try: # Gestion d'erreurs
		
		while True:

			# Mesure de la distance et correction des valeurs aberrantes
			distance = min(max(tof.read(), MIN_DIST_MM), MAX_DIST_MM)
			
			# Remappe la distance dans l'intervalle de fréquence souhaité
			frequency = map(distance, MIN_DIST_MM, MAX_DIST_MM, MIN_FREQUENCY_HZ, MAX_FREQUENCY_HZ)
			
			# Prend le complément de la fréquence (pour qu'elle augmente lorsqu'on s'approche d'un obstacle).
			frequency = round(max(MAX_FREQUENCY_HZ - frequency, MIN_FREQUENCY_HZ),3)

			# Ajuste la fréquence du timer
			tim1.freq(frequency)
			
			# Appel du ramasse-miettes, indispensable pour que le programme ne se bloque pas
			# très rapidement en fragmentant complètement la RAM.
			gc.collect()
			
			sleep_ms(50) # Temporisation de 50 millisecondes

	# En cas d'interruption clavier avec *[CTRL]-[C]*
	except KeyboardInterrupt:
		tim1.deinit() # Arrêt du timer
		buzzer_pin.value(0) # Arrêt du buzzer
		tof.stop() # Arrêt du capteur

# Appel de la fonction principale
main()

Pour aller plus loin : Utiliser le VL53L1X

Vous trouverez également dans l’archive téléchargeable MODULES.ZIP un exemple avec une version plus récente du VL53L0X, le VL53L1X, ayant une portée de quatre mètres (merci à Julien NGUYEN).

Pour aller encore plus loin : Afficher les distances avec ST BLE Sensor et utiliser le VL53L1X

Vous trouverez dans l’archive téléchargeable MODULES.ZIP un autre ensemble de scripts qui démontre comment afficher les valeurs de distances renvoyées par le VL53L0X avec l’application smartphone, ST BLE Sensor via une connexion sans fil avec la radio BLE du STM32WB55.