Réaliser un Télémètre à Ultrasons
avec une platine Arduino
Aujourd'hui, une communauté active existe autour des cartes Arduino, laquelle met à disposition des exemples de codes, de nombreuses librairies permettant de programmer facilement sans se soucier de coder des pilotes pour les différents composants utilisés, le tout en "open-source".
Qui plus est, l'IDE (Environnement de Développement), est fourni gratuitement!
On reproche à ces platines leur prix qui peut être assez élevé si on achète les versions "officielles", mais ces platines étant "open-hardware", on peut trouver des copies "made in china" sur Ebay pour pas très cher.
Vous disposez d'une carte Arduino Mega, d'un écran LCD+Keypad Sainsmart (s'enquille directement sur la carte Arduino Mega), d'un E/R Ultrasons SR04 et d'une résistance de 4,7 k, vous pouvez construire un Télémètre!
Principe:
C'est un peu le principe du radar mais avec des ultrasons!
Un transducteur émet une onde sonore à une fréquence de 40KHz, cette onde se réfléchit s'il y a un obstacle et un autre transducteur est chargé de recevoir l'onde réfléchie en l'amplifiant un peu, car le signal reçu est assez faible.
En général, la portée d'un tel dispositif n'est que de 4 à 5 mètres maximum.
La récupération de l'information "distance" se fait assez simplement:
Amélioration de la précision de la mesure:
La vitesse de propagation du son dans l'air peut varier suivant sa densité, donc sa température.
Sur Wikipedia, un tableau montre que la vitesse de propagation peut varier de 325.4 m/s à -10°C à 349.2 m/s à +30C.
En fait, la variation est linéaire et l'équation donnant la variation de vitesse de propagation en fonction de la température est la suivante: V = 0.6 x T + 331.5. (voir site)
On utilisera un capteur DHT22, lequel est précis à +/- 0.5°C sur une plage de température allant de -40 à +80°C.
Composants nécessaires:
Ensemble Câblé:
Commentaires:
La carte LCD s'enquille directement sur la platine Arduino Mega (pas de câbles superflus)
Partie Programmation:
Organigramme du système:

Bibliothèques utilisées:
1 2 3 4 |
// Bibliothèque gérant l'affichage LCD #include <LiquidCrystal.h> // Bibliothèque dédiée capteur DHT22 (humidité / Température) #include <DHT.h> |
N.B.: si elles ne sont pas installées, il suffit de cliquer sur "Croquis -> Inclure une Bibliothèque -> Gérer les Bibliothèques" et taper le nom de la bibliothèque pour vérifier si cette dernière est installée.
Si elle ne l'est pas, cliquer sur "installer".
Initialisation du Module LCD: (voir site)
Le Module utilisé est prévu pour fonctionner sur une carte "compatible Arduino".
Il est composé d'un module LCD 16x2 et de 5 boutons reliés à un réseau de résistances formant un pont diviseur, dont la valeur lue dépend de la touche sur laquelle on appuie.
La valeur est lue sur l'entrée A0 de la platine Arduino.
Le réglage de luminosité est réglable en appliquant un signal PWM sur la sortie "Digital 10" de la platine Arduino. (pas utilisé ici)
Allocation des Pins:
Pin | Function |
---|---|
Analog 0 | Button (select, up, right, down and left) |
Digital 4 | DB4 |
Digital 5 | DB5 |
Digital 6 | DB6 |
Digital 7 | DB7 |
Digital 8 | RS (Data or Signal Display Selection) |
Digital 9 | Enable |
Digital 10 | Backlit Control |
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
// select the pins used on the LCD panel LiquidCrystal lcd(8, 9, 4, 5, 6, 7); // respecter l'ordre des Pins // define some values used by the panel and buttons int adc_key_in = 0; #define btnRIGHT 0 #define btnUP 1 #define btnDOWN 2 #define btnLEFT 3 #define btnSELECT 4 #define btnNONE 5 // Fonction "Lire les Boutons" int read_LCD_buttons() { adc_key_in = analogRead(0); // read the value from the sensor // my buttons when read are centered at these valies: 0, 144, 329, 504, 741 // we add approx 50 to those values and check to see if we are close if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result // For V1.1 us this threshold if (adc_key_in < 850) return btnSELECT; if (adc_key_in < 50) return btnRIGHT; if (adc_key_in < 250) return btnUP; if (adc_key_in < 450) return btnDOWN; if (adc_key_in < 650) return btnLEFT; return btnNONE; // when all others fail, return this... } void setup() { // LCD lcd.begin(16, 2); // Démarrage du LCD lcd.setCursor(0,0); // Curseur positionné ligne "0" 1er caractère //lcd.print("Push the buttons"); // print a simple message } |
Initialisation du DHT22:
1 2 3 4 5 6 7 8 9 |
// DHT22 #define DHTPIN 40 // Pin Arduino sur laquelle la pin 2 du DHT22 est connectée #define DHTTYPE DHT22 // DHT 22 (AM2302) DHT dht(DHTPIN, DHTTYPE); // On "instancie" le DHT void setup() { // DHT22 dht.begin(); } |
Initialisation du Télémètre SR-04:
1 2 3 4 5 6 7 8 9 10 |
// SR04 const int USTrig = 30; // Déclencheur Impulsion sur la broche 30 const int USEcho = 31; // Réception Echo sur la broche 31 float VITESSE = 340; //vitesse par défaut du son 340 m/s void setup() { // SR04 pinMode(USTrig, OUTPUT); pinMode(USEcho, INPUT); } |
Code définitif (enfin tout est perfectible!):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
/* Programme permettant de mesurer une distance * Capteurs: SR-04: télémètre à ultrasons * DHT22: Humidité et température * Entrées: Bouton "Select" pour lire Température pendant 5s * Sorties: Affichage Distance - Température - Humidité sur LCD * Bugs: Adafruit_Sensor.h: No such file or directory * Solution: installer la bibliothèque "Adafruit Unified Sensor" */ // Bibliothèque gérant l'affichage LCD #include <LiquidCrystal.h> // Bibliothèque dédiée capteur DHT22 (humidité / Température) #include <DHT.h> // select the pins used on the LCD panel LiquidCrystal lcd(8, 9, 4, 5, 6, 7); // define some values used by the panel and buttons int lcd_key = 0; int adc_key_in = 0; float temp = 15; // on initialise la température à 15°C float hum = 20; // on initialise le taux d'humidité à 20% (pas important) float dist = 0; #define btnRIGHT 0 #define btnUP 1 #define btnDOWN 2 #define btnLEFT 3 #define btnSELECT 4 #define btnNONE 5 // DHT22 #define DHTPIN 40 // Pin Arduino sur laquelle la pin 2 du DHT22 est connectée #define DHTTYPE DHT22 // DHT 22 (AM2302) DHT dht(DHTPIN, DHTTYPE); // On "instancie" le DHT // SR04 const int USTrig = 30; // Déclencheur Impulsion sur la broche 30 const int USEcho = 31; // Réception Echo sur la broche 31 float VITESSE = 340; //vitesse par défaut du son 340 m/s // Fonction "Lire les Boutons" int read_LCD_buttons() { adc_key_in = analogRead(0); // read the value from the sensor // my buttons when read are centered at these valies: 0, 144, 329, 504, 741 // we add approx 50 to those values and check to see if we are close if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result // For V1.1 us this threshold if (adc_key_in < 850) return btnSELECT; if (adc_key_in < 50) return btnRIGHT; if (adc_key_in < 250) return btnUP; if (adc_key_in < 450) return btnDOWN; if (adc_key_in < 650) return btnLEFT; return btnNONE; // when all others fail, return this... } void setup() { // SR04 pinMode(USTrig, OUTPUT); pinMode(USEcho, INPUT); // LCD lcd.begin(16, 2); // Démarrage du LCD lcd.setCursor(0,0); // Curseur positionné ligne "0" 1er caractère //lcd.print("Push the buttons"); // print a simple message // DHT22 dht.begin(); } void loop() { // Test si Appui sur le Bouton "SELECT" if (read_LCD_buttons() == btnSELECT){ temp = dht.readTemperature(); hum = dht.readHumidity(); lcd.setCursor(0,0); // curseur positionné à la 1ère ligne et 1er caractère lcd.print ("temp: "); // Affichage de la chaine de caractères "temp: " lcd.setCursor(8,0); // positionnement du curseur à la 1ère ligne et 8ème caractère lcd.print (temp); // Affichage de la température (en °C) lcd.setCursor(0,1); // positionnement du curseur à la 2ème ligne et 1er caractère lcd.print ("hum: "); // Affichage de la chaine de caractères "hum: " lcd.setCursor(7,1); // positionnement du curseur à la 2ème ligne et 7ème caractère lcd.print (hum); // Affichage du taux d'humidité (en %) // Recalcul de la vitesse du son VITESSE = 0.595*temp + 331.5; delay(5000); // On maintient l'affichage pendant 5 secondes lcd.clear(); // On efface l'affichage } // 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.setCursor(0,0); lcd.print ("Err.: Dist > 4m"); delay(500); lcd.clear(); } 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 dist = temps*VITESSE + 0.065; //on multiplie par la vitesse, d=t*v et on ajoute la largeur du boitier (qui compte pour la mesure) // 6. On affiche la distance lcd.setCursor(0,0); lcd.print ("Dist: "); lcd.setCursor(8,0); lcd.print (dist); } // petite pause delay(250); } |
Commentaires:
Dans la partie "recalcul", j'ai ajouté la lecture de l'information "Hygrométrie", çà ne mange pas de pain...
Dans la formule de calcul de la distance, il y a un décalage de "+0.065 m", pourquoi?
Explication:
On pourrait augmenter la portée du SR04 en augmentant le gain de l'amplificateur de réception (nécessite un petit rétro-engineering de la carte) => risque d'erreur de mesure dû à l'amplification de signaux parasites...
Conclusion:
Le code n'est qu'un exemple, il peut être modifié à volonté!
Pour une mesure précise, l'idéal est de pointer le télémètre vers une surface plane sans armoire ou autre obstacle susceptible de perturber la mesure.
On peut aussi ajouter une fonction de calcul de d'aire ou de volume d'une pièce, çà existe sur d'autres appareils.
Il est possible de concevoir et d'imprimer un boîtier en plastique pour protéger le montage et lui donner un aspect "fini" 😉