Comment utiliser un capteur a ultrasons HCSR04 avec Arduino.

Aujourd'hui j'ai reçu un lot de capteurs à ultrasons HCSR04 pour mon prochain projet de voiture commandée par Wifi. Ces capteurs sont trés pratiques car ils offrent une détection relativement précise pour un coût faible. De plus ils sont trés faciles à prendre en main.

Pour le montage suivant vous aurez besoin:

  • D'un capteur HC-SR04 (3 euros)
  • D'une carte arduino (testé sur Uno, Léonardo et Mega mais devrais fonctionner partout)
  • Quelques fils de breadboard mâle/femelle

arduinohcsr04overview

Fonctionnement de base

Ces capteurs sont équipés de deux modules: un module d'émission et un module de réception. Ces modules sont reliés respectivement aux pins Trigger et Echo. Le module dispose aussi de deux pins d'alimentation (+5V et GND).

En fonctionnement, le module envoie une onde devant lui via le module d'émission lorsqu'il reçoit une commande sur son pin Trigger. L'onde va alors se déplacer dans l'air jusqu'à rebondir sur un obstacle. C'est le retour de cette onde qui est ensuite captée par le module de réception et va déclencher un signal sur le pin echo.

La différence de temps entre l'envoi de l'onde, et sa réception nous donne la distance parcourue par celle-ci. Il suffit de diviser cette distance par deux pour avoir la distance jusqu'a l'obstacle (car l'onde à parcouru deux fois cette distance: aller puis retour).

Pour rentrer un peu plus dans les détails techniques, une impulsion haute sur le pin Trigger pendant 10us fait passer le Pin Echo en état HAUT. Ce pin restera dans cet état jusqu'à ce que l'onde soit captée. Si aucune onde n'est reçue aprés un certain temps, le pin redeviens flottant.

Voici quelques formules pour calculer la distance:

Le temps est en uS
Vitesse du son en M/S (340M/2)

Formules utiles:
Distance en m = temps × vitesse du son / 2
Ditance en cm = temps x 58
Distance en in = temps x 148

Branchements

Ce capteur dispose de 4 pins:

5V
Trig
Echo
GND

Les noms des pins sont inscrits sur la carte donc il n'y a normalement pas de confusion à avoir.

Pour un module, on peux le connecter directement à l'arduino car il ne consomme pas beaucoup (15mA en émission). Par contre si vous voulez en connecter plusieurs, une alimentation supplémentaire est à considérer.

Pour le programme suivant, j'ai connecté le 5V et le GND au 5V et au GND de l'arduino. Le pin Echo est connecté au pin 7 et le pin Trig au pin 8. Il est possible de connecter les pins Trigger et Echo au même pin de l'arduino (pour n'en utiliser qu'un au lieu de deux) mais j'essaye de rester le plus simple possible. Il existe des variantes du capteur qui n'ont que trois pins au lieu de quatre.

arduinohcsr04

Vue du montage final du capteur sur une carte arduino Mega.

Programme de test

Le programme suivant effectue une mesure en boucle via le capteur et inscrit son résultat sur la liaison série.

//Define the echo pin (receive the echo from the ultrasound)
#define SENSOR_ECHO_PIN 7
//Define the trig pin (trigger the ultrasonic emitter)
#define SENSOR_TRIG_PIN 8
//On some sort of sensors, echo and trig can be on the same pin

//Precalculate some values
const float SpeedOfSound = 343.2; // ~speed of sound (m/s) in air, at 20°C         
const float MicrosecondsPerMillimetre = 1000.0 / SpeedOfSound; // microseconds per millimetre
const float MicrosecondsToMillimetres = (1.0 / MicrosecondsPerMillimetre); //distance by time elapsed
const float MicrosecondsToMillimetresDistance = MicrosecondsToMillimetres / 2.0; //because the ping make twice distance to object

void setup() {
	// initialize serial communication to debug
	Serial.begin(9600);
	
	//Set pin modes
	pinMode(SENSOR_ECHO_PIN, INPUT);
	pinMode(SENSOR_TRIG_PIN, OUTPUT);
	
	//Enable internal pull down for echo (to force it to zero when not in HIGH)
	digitalWrite(SENSOR_ECHO_PIN, LOW);
}

void loop() {
	//Send a high pulse on the trigger for a given amount of time
	digitalWrite(SENSOR_TRIG_PIN, HIGH);
	delayMicroseconds(10); // Some sensor need more than 10 us
	digitalWrite(SENSOR_TRIG_PIN, LOW);
	
	//Sound wave is in transit, wait for it to come back (ECHO pin goes to LOW)
	long microseconds = pulseIn(SENSOR_ECHO_PIN, HIGH)

	long millimetres = MicrosecondsToMillimetresDistance * microseconds;
	
	//Print result
	char buff[32];
	sprintf(buff, "Distance: %d cm", millimetres);
	Serial.println(buff);
	
	//Add a delay to avoid flooding Serial, and avoiding soundwave collisions
	delay(1000);
}

Points pièges

Pour l'instant la mesure effectuée par le capteur est bloquante, c'est à dire que tant que le ping n'est pas parti puis revenu, l'arduino ne fera rien d'autre. Pour un ou deux capteurs ce n'est pas un problème, mais si on venait à en avoir 10 ou 15 cela risque de créer des soucis.

Il existe des librairies pour gérer les capteurs de maniére non bloquante. La meilleure actuellement s'apelle NewPing. Cette librairie utilise les interruptions pour gérer la mesure en paralléle du reste du code.

Autre détail à prendre en compte, les capteurs peuvent se mélanger entre eux si on effectue une mesure simultanée. Il ne faut pas oublier les cas ou on reçoit plusieurs echos pour un seul envoi. En effet, si plusieurs surfaces réfléchissent l'onde à des distances différentes, on ne détecte que la premiére. Mais le second echo risque d'étre détécté si on effectue une autre mesure juste à la suite.

Par exemple sur mon prochain robot, je me limite à 8 mesures par seconde. Cela laisse 125ms à l'onde pour se propager (soit 42 métres, bien au dessus de la portée du capteur). C'est suffisant pour écarter les faux positifs et les reflets entre les différents capteurs. Ce chiffre est à adapter à votre cas (nombre de capteurs, précision voulue).