Réaliser un télémètre à ultrasons

Apprenons à réaliser un télémètre à ultrasons grâce à une Arduino et un petit module complémentaire

Lorsque l’on veut mesurer des distances, on utilise en général une règle ou un ruban mètre. Mais comment faire pour avoir une distance numerique en temps réel ?

Une réponse : utiliser la technologie des ultrasons pour réaliser un télémètre.

Bien que peu précis à l’échelle des centimètres, ces derniers sont relativement fiables à l’échelle de la dizaine de centimètres. Les ultrasons étant des ondes sonores se propageant sous la forme d’un cône (ils sont peu directifs), ils font de très bons détecteurs d’obstacles.

Nous allons donc nous lancer dans la réalisation d’un petit télémètre à ultrasons via une Arduino et avec un affichage intégré sur un écran LCD (parce que la voie série, c’est un peu pénible pour se promener :D ). Voici les prérequis pour suivre ce tutoriel :

  • savoir se servir d’une Arduino ;
  • savoir utiliser un écran LCD alphanumérique avec l’Arduino.

À la fin de ce tutoriel, vous serez en mesure de :

  • utiliser un capteur HC-SR04 ;
  • comprendre et utiliser une information de type "temps de vol" ;
  • utiliser la fonction pulseIn() pour mesurer une durée d’état sur une broche.

Rappel sur les ultrasons

Faisons un peu de sciences et rappelons ce que sont des ultrasons.

Un ultrason est une onde sonore à haute fréquence. Par haute fréquence j’entends toutes les fréquences sonores inaudibles pour l’oreille humaine, soit celles au-delà de 20 kHz. Elles sont l’opposé des infrasons qui sont les ondes sonores dont la fréquence est inférieure à la plus faible audible pour l’Homme et qui est de 20 Hz.

Bon, c’est bien beau mais cette histoire de fréquence ça ne nous en dit pas beaucoup plus !

Une onde sonore c’est quoi ?

Une onde sonore est un phénomène physique de compression et décompression. Lorsqu’une vibration est produite (par n’importe quel objet qui vibre), l’air subit alors une onde de choc qui se traduit en mouvement des atomes. Il y a alors ce phénomène de compression et décompression (des "trous" dans l’air) que des récepteurs dans nos oreilles convertissent en bruit.

Plus les compressions sont proches et plus la fréquence est élevée. On parle alors de son aigu. Au contraire, plus les compressions sont éloignées et plus la fréquence est faible, on parle d’un son grave. Une fréquence s’exprime en Hertz et traduit la répétition d’un motif d’un phénomène durant une seconde. Par exemple si je cligne des yeux trois fois par seconde, on peut dire que je cligne des yeux à 3 Hz.

Dans le cas des ultrasons, les compressions/décompressions sont très courtes. En effet, le motif se répète plus de 20 000 fois par seconde, donc à plus de 20 kHz. En général, en électronique on utilise un transducteur piézo pour générer cela. C’est une sorte de petit buzzer capable de vibrer très vite. Très souvent, les télémètres à ultrasons vibrent à une fréquence de 40 kHz.

Une dernière caractéristique des ondes sonores est leur capacité à être réfléchie par les obstacles. En effet, les ondes sonores ont tendance à "rebondir" sur les obstacles. On entend alors l’onde de départ et un peu plus tard la même avec un retard et une plus faible intensité. C’est exactement le même phénomène qu’un écho dans une pièce vide ou en montagne. L’onde sonore se déplace, rebondit sur les murs lisses et revient à votre oreille avec un retard entre le moment où vous avez parlé et celui où vous l’entendez (et une puissance sonore plus faible). En général, dans le domaine de l’acoustique et de la musique, on cherche à supprimer cette caractéristique en recouvrant les murs de matériaux spéciaux. Cependant, dans le cas d’une mesure de distance, on va exploiter cet effet.

Principe de la mesure

Comme dit précédemment, on va tirer parti du fait que l’onde sonore rebondit sur les obstacles et revient souvent vers l’expéditeur. On va aussi exploiter une autre chose connue, sa vitesse !

En effet, la vitesse de déplacement d’une onde sonore dans l’air est connue depuis longtemps. Elle est d’environ 340 mètres par seconde à 25 degrés Celsius (plutôt lent comparé à la lumière et ses 300 000 km/s :D ). À partir de là, si on sait quand l’onde est partie et quand on la reçoit de nouveau (après le rebond), on est en mesure de calculer un temps de vol de l’onde. On a alors une durée, une vitesse, et on peut en déduire une distance !

Comme l’onde fait un aller-retour (le voyage depuis l’émission de l’onde, le rebond, puis le retour sur le récepteur), il faudra diviser le temps de vol par deux pour ne considérer qu’un trajet (l’aller ou le retour). Le calcul sera alors simple. Une vitesse s’exprime par une distance divisée par un temps v=d/tv = d/t donc la distance sera la vitesse multipliée par le temps d=v×td = v \times t.

Passons un peu à la pratique pour mieux comprendre !

Un capteur à ultrasons
Un capteur à ultrasons

Mise en œuvre du télémètre

Le télémètre que nous allons utiliser est assez simple. Son nom est HC-SR04 et existe en différentes variations. Découvrons-le et voyons comment le faire fonctionner avec notre Arduino.

Le HC-SR04

Présentation du composant

Le HC-SR04 est ce que l’on appelle communément un "Télémètre à ultrasons". Il est trouvable relativement facilement sur de nombreux sites de fournisseurs de composants électroniques. Les sites livrant depuis la Chine proposent des prix inférieurs à 5 euros en général.

Ce composant possède plusieurs petites choses. Tout d’abord, sur la face avant on peut voir l’émetteur US et son récepteur. Ce sont des petites cellules piézo-électriques qui vont soit vibrer lorsqu’une tension est appliquée (émetteur), soit au contraire produire une tension lorsque une vibration est reçue (récepteur).

Sur la face arrière on trouve plusieurs petits circuits permettant la génération du signal et le traitement de ce dernier. Ainsi, un composant va générer une onde de 40 kHz lors d’un "top départ" et la partie restante s’occupera de la mise en forme de la réception (amplification et filtrage) et de mettre en forme cela proprement sur une broche de sortie. Parlons d’ailleurs des broches. On en trouve 4.

Les premières sont comme toujours VCC et GND qui vont accueillir l’alimentation (respectivement 5V et masse). On trouve ensuite la broche "echo" sur laquelle sera présent le signal de sortie. Enfin, une broche nommée "Trig". Cela signifie "Trigger" soit "déclencheur" ou "gâchette". En mettant cette broche à l’état haut pendant 10µs vous allez déclencher le ping pour la mesure. Un "ping" représente le lancement d’une onde ultrason. Pour reprendre l’exemple de l’écho dans la pièce vide, le ping correspondrait au moment où vous émettez un son en parlant.

Le signal de sortie est assez simple à exploiter. Il est initialement à 0, puis passe à 1 lorsque le ping est envoyé. Il repasse ensuite à 0 quand l’écho est revenu au récepteur OU s’il n’y a pas de retour durant les 30ms après l’envoi (l’onde est alors considérée perdue).

Branchement

Les branchements sont eux-même assez simples. Il suffira de relier 5V et GND à leurs broches respectives sur Arduino et mettre "Trig" et "Echo" sur des I/O numériques (8 et 9 par exemple). Pas la peine d’un schéma pour cela !

Exploitons le capteur avec Arduino

Passons maintenant à la pratique avec Arduino. Le but ici sera d’être capable de faire une mesure de distance puis de l’afficher en millimètres dans la console de la voie série.

Setup

On va comme toujours commencer par le setup. Pour une fois, pas de bibliothèque externe à rajouter, tout sera fait "à la main". Comme vu plus tôt, nous allons utiliser deux broches que je vais très justement nommer "USTrig" et "USEcho", pour le déclencheur (une sortie numérique) et le retour d’informations (une entrée numérique). Je vais ensuite préparer la voie série pour afficher les mesures.

const int USTrig = 8; // Déclencheur sur la broche 8
const int USEcho = 9; // Réception sur la broche 9

void setup() {
    pinMode(USTrig, OUTPUT);
    pinMode(USEcho, INPUT);

    digitalWrite(USTrig, LOW);

    Serial.begin(9600);
}

Et c’est tout pour le setup !

Loop

Les choses faciles sont réglées, passons aux choses amusantes et faisons des mesures !

Comme je le disais dans la présentation du composant, il y a une suite d’actions à faire pour mesurer la distance. Schématiquement cela se traduirait par la liste suivante :

  1. Un état haut de 10 microsecondes est mis sur la broche "Trig"
  2. On remet à l’état bas la broche Trig
  3. On lit la durée d’état haut sur la broche "Echo"
  4. On divise cette durée par deux pour n’avoir qu’un trajet
  5. On calcule la distance avec la formule d=v×td = v \times t
  6. On affiche la distance

Toutes ces étapes sont en fait assez simples, à part peut-être la mesure de la durée. Heureusement, une fonction nommée pulseIn() est la pour ça :) . Cette dernière, qui est bloquante, se chargera de mesurer combien de temps une broche reste dans un état (HIGH or LOW). Elle prend en paramètre le numéro de la broche et l’état à observer.

Voici alors un exemple de programme que l’on obtient :

#define VITESSE 340 //vitesse du son 340 m/s

// setup()

void loop()
{
   // 1. Un état haut de 10 microsecondes est mis sur la broche "Trig"
   digitalWrite(USTrig, HIGH);
   delayMicroseconds(10); //on attend 10 µs
   // 2. On remet à l’état bas la broche Trig
   digitalWrite(USTrig, LOW);

   // 3. On lit la durée d’état haut sur la broche "Echo"
   unsigned long duree = pulseIn(USEcho, HIGH);

   if(duree > 30000)
   {
      // si la durée est supérieure à 30ms, l'onde est perdue
      Serial.println("Onde perdue, mesure échouée !");
   }
   else
   {
      // 4. On divise cette durée par deux pour n'avoir qu'un trajet
      duree = duree/2;

      // 5. On calcule la distance avec la formule d=v*t
      float temps = duree/1000000.0; //on met en secondes
      float distance = temps*VITESSE; //on multiplie par la vitesse, d=t*v

      // 6. On affiche la distance
      Serial.print("Duree = ");
      Serial.println(temps); //affiche le temps de vol d'un trajet en secondes
      Serial.print("Distance = ");
      Serial.println(distance); //affiche la distance mesurée (en mètres)
   }

   // petite pause
   delay(250);
}

Si vous voulez obtenir la distance en millimètres, il suffira de multiplier par 1000. Mais soyons malins, nous pouvons aussi optimiser en évitant une opération. Pour cela c’est simple, la ligne calculant le temps en seconde passe de :

float temps = duree/1000000.0;

à

float temps = duree/1000.0;

puisque multiplier la distance par 1000 dans notre situation revient exactement à avoir un temps divisé par le même facteur (pour avoir l’information en centimètres, il aurait fallu utiliser un facteur 100 plutôt que 1000). Je vous laisse poser les maths si vous voulez me croire sur parole ;) .

Si les mesures ne sont pas ultra-précises, essayez de modifier la constante de vitesse. Les ondes sont sensibles à la température ce qui influe sur leur vitesse. Nous verrons cela plus tard ;) .

Ajout de l’écran et montage final

Tout va bien ? Les échos reviennent ? Alors place à la portabilité ! Dans cette dernière étape nous allons rajouter l’écran à notre nouvel outil.

Pour rajouter l’écran, commençons par vérifier le câblage nécessaire. L’écran nécessite 4 (ou 8 selon vos choix) fils de données (+ 2 de contrôle) et une alimentation. Cette dernière sera prise sur les broches 5V et GND de l’Arduino et les fils de données seront sur les broches 2 à 5. Les fils de contrôle EN et R/W seront sur les broches 6 et 7.

Faire fonctionner l’écran seul

En science, lorsque l’on veut tester quelque chose on l’isole du reste. Ici c’est pareil ! Nous avons pu constater que notre télémètre fonctionne bien en le faisant marcher seul, nous allons faire de même en utilisant l’écran seul. Pour cela, nous allons simplement afficher une ligne de caractères.

On commence logiquement par le setup et ce qui va avec, notamment la bibliothèque LiquidCrystal et un objet du même nom.

#include "LiquidCrystal.h"

// VÉRIFIEZ AVEC VOS PROPRES BROCHES
LiquidCrystal lcd(6,7,2,3,4,5); //liaison 4 bits de données

void setup() {
    lcd.begin(2, 16); // Initialisation de l’écran (2 lignes 16 caractères pour ma part)
}

Une fois cela fait, on va afficher une simple ligne dans notre programme principal :

void loop() {
    lcd.clear();
    lcd.home(); // Replace le curseur en haut à gauche
    lcd.print("-+ Eskimetre +-");
    delay(10000); //pause de 10 secondes inutile, juste pour éviter de rafraîchir sans arrêt
}

Si le message s’affiche correctement, alors tout va bien et vous pouvez continuer !

L’écran avec le télémètre

Nous y voilà ! Le moment tant attendu où nous allons afficher les mesures sur l’écran ! Pour cela, commencez par rajouter sur votre montage le télémètre (broche 8 et 9) et fusionner les setup pour n’en faire qu’un sans la voie série. Vous devriez obtenir quelque chose comme ça :

#include "LiquidCrystal.h"
#define VITESSE 340

// VÉRIFIEZ AVEC VOS PROPRES BROCHES
LiquidCrystal lcd(6,7,2,3,4,5); //liaison 4 bits de données
const int USTrig = 8; // Déclencheur sur la broche 8
const int USEcho = 9; // Réception sur la broche 9

void setup() {
    lcd.begin(2, 16); // Initialisation de l’écran (2 lignes 16 caractères pour ma part)

    pinMode(USTrig, OUTPUT);
    pinMode(USEcho, INPUT);

    lcd.print("-+ Eskimetre +-");
}

Il faut ensuite fusionner le tout pour faire un affichage sur le LCD. Je vous propose d’exploiter les deux lignes pour afficher :

  • En haut : la distance en millimètres (int)
  • En bas : le temps en millisecondes (int)
void loop() {
    // 1. Un état haut de 10 microsecondes est mis sur la broche "Trig"
   digitalWrite(USTrig, HIGH);
   delayMicroseconds(10); //on attend 10 µs
   // 2. On remet à l'état bas la broche Trig
   digitalWrite(USTrig, LOW);

   // 3. On lit la durée d'état haut sur la broche "Echo"
   unsigned long duree = pulseIn(USEcho, HIGH);

   if(duree > 30000)
   {
      //si la durée est supérieure à 30ms, l'onde est perdue
      lcd.clear();
      lcd.home(); // Replace le curseur en haut à gauche
      lcd.print("Onde perdue :(");
      lcd.setCursor(0,1);
      lcd.print("Mesure echouee !");
   }
   else
   {
      // 4. On divise cette durée par deux pour n'avoir qu'un trajet
      duree = duree/2;

      // 5. On calcul la distance avec la formule d=v*t
      unsigned int distance = duree*(VITESSE/1000.0); //on multiplie par la vitesse, d=t*v
      
      // 6. On affiche !
      lcd.clear();
      lcd.home(); // Replace le curseur en haut à gauche
      char message[16] = "";
      sprintf(message, " Dist : %4d mm", distance);
      lcd.print(message);
      sprintf(message, "Temps : %4d us", duree);
      lcd.setCursor(0,1);
      lcd.print(message);
   }
   delay(250); // Petite pause
}

Il est pas beau ce télémètre :D ? Voici ce que ça donne chez moi :

Mon télémètre

Et voici une version sur simulateur https://www.tinkercad.com/embed/3NbcDdiiH1v

!(https://www.tinkercad.com/embed/3NbcDdiiH1v)

Aller plus loin

Comme je l’ai brièvement mentionné plus tôt, la température a un impact sur la vitesse des ondes (ainsi que la pression et d’autres choses). Une amélioration de notre télémètre serait donc d’avoir une correction de la vitesse via une mesure de la température !

Pour débuter, prenons connaissance des données. Wikipédia nous dit que la vitesse de propagation du son dans l’air suit à peu près le tableau suivant :

Vitesse du son en fonction de la température
Vitesse du son en fonction de la température

Si l’on fait un graphique avec ce tableau, on peut déduire les valeurs de la relation V=f(t)V = f(t) (vitesse en fonction de la température) qui est presque linéaire et donc peut être modélisée par une fonction affine. En faisant le calcul de la variation via les deux points les plus extrêmes du bout de droite, on obtient un coefficient de 0.6 m/s par degrés Celsius (325.4349.21030\frac{325.4-349.2}{-10-30}). On observe aussi une ordonnée à l’origine (soit à 0 degré) de 331.5 mètres par seconde.
Tout cela nous donne la relation : V=at+bV = at+b (avec VV la vitesse en mètres par seconde et tt la température en degrés Celsius). aa vaudra ainsi 0.6 et bb vaudra 331.5.

Je ne donnerai pas le détail du montage ni le code ici cependant. Je vous le laisse en tant qu’évolution/exercice si vous le souhaitez, en rajoutant un capteur de température au montage (un LM35 par exemple). Voici cependant la logique de code qu’il faudrait suivre pour implémenter cela :

void loop() {
    // On fait la mesure de température

    // On stocke la température en degrés Celsius dans "degres".
    float degres;

    // puis on ajuste la vitesse en fonction de la température
    float vitesse = 0.6*degres + 331.5;

    // et enfin, on fait tout le reste comme avant (mesure + affichage)
    // La seule différence sera que l'on utilisera la variable "vitesse" ...
    // ... au lieu de la constante VITESSE
}

Vous avez maintenant un outil de mesure complètement fonctionnel. Il suffit de fabriquer un boîtier et de rajouter une batterie ou quelques piles pour avoir un module totalement autonome ! On pourrait aussi pousser le vice en utilisant une Arduino mini ou micro pour réduire encore un peu plus la taille du produit final !

39 commentaires

Merci. ^^

Autre question : sur Amazon, le capteur est désigné par "4-Pin Module à ultrasons HC-SR04 Capteur de mesure de distance pour Arduino" et je ne l'ai vu employé qu'avec Arduino sur le Net : ce capteur est-il dédié à cette carte ou peut-on l'utiliser avec n'importe quoi ?

+0 -0

Merci. :)

Encore une question ? :P

J'ai lu que le capteur avait un angle de mesure de 15°. Du coup, il ne cible pas vraiment un point en particulier. Comment se comporte-t-il si l'onde rencontre plusieurs objets ?

+0 -0

Bonjour, Excelent tuto,j'ai acheté 1 capteur ultra son qui perd toute mesure quand il voit trop loin,alors j'en ai acheté 3 autres ailleurs,ceux là fonctionnent mais sont peu fiables et surtout ne dépasse pas les 250 cm. Dommage je voulais fabriquer un appareil qui aurait donné le volume d'eau restant dans une cuve cylindrique couchée de 6 metres de diametre. Encore félicitations pour le tuto.

Bonjour, félicitation pour ce tuto assez explicatif J'ai un projet de télémètre a ultrason mais sur des distances pouvant atteindre maximum 6 mètre j'ai ainsi choisi le modèle Srf08. Cependant je cherche à récupérer la hauteur de différent type de fluide sans flotteur ni sonde interne. J'ai donc pensé à réguler la fréquence de l'émetteur mais il y a un pb , je n'arrive pas a modifier cette fréquence d'émission et malheureusement l'onde traverse le premier fluide. NEED SOME HELP PLEASE

Merci beaucoup, j’ai vu que les gens utilise ce capteur pour faire un chemin automatique(voiture qui suit un chemin) on trouve des tutos dans le net (branchement…) mais pas d’explication, pouvez vous expliquer comment on peut suivre un chemin(chemin comme cercle, ou demi cercle…)

Merci

Bonjour Eskimon,

Tout d’abord, je tiens à te féliciter quant à la qualité de ton tutoriel. Très bien fait. J’ai une question concernant la réception de donnés. Est-il possible selon toi de transmettre les informations sur une tablette tactile et si oui, par quel moyen ?

Bien cordialement,

Excellent ce tutoriel et merci pour tous tes apports. Plus qu’à gérer le bon timing entre mesure de température, calcul de vitesse puis mesure de distance. Une petite remarque au sujet de la célérite du son par rapport à ton interpolation : cette dernière (en supposant que l’air est un gaz parfait ce qui est assez vrai) peut directement être calculée et de façon précise à l’aide de l’expression :

celerite=sqrt(1.4x287x(273+temperature))

où 1.4 et 287 sont des constantes liées au gaz et 273 la conversion de la tempéraure de °C à Kelvin. Bon, je replonge dans mon code ;)

+1 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte