Tuto pas-à-pas C++ : utiliser un capteur ultrason HC-SR04 sur la Gamebuino Meta

Voici un tutoriel étape par étape qui vous permettra de réaliser un programme simple afin d’utiliser un capteur US (ultrason) avec votre console.

Le tuto est destiné à être réalisé avec le matériel fourni dans le pack d’accessoires Gamebuino. Toutefois vous pouvez bien entendu utiliser un autre capteur tant que celui-ci est compatible Arduino.

00002

Pour ce tutoriel, il vous faut :

  • une console Gamebuino META
  • Un capteur US compatible Arduino
  • un ordinateur avec l’environnement de développement l’IDE Aduino installé

Si ce n’est pas encore fait, reportez vous à la fiche
Premiers pas (C++ 1/5) : Installation rapide du logiciel - Gamebuino pour installer l’IDE Arduino.

Si vous avez déjà les bases en programmation (ou la flemme de lire tout le tuto qui suit) vous pouvez trouver le code complet du programme réalisé ici dans le Mini-code : ultrason

Les branchements

En parallèle de notre code il faut brancher le capteur à la console, si possible avec le backpack.
On branche l’ alimentation (VCC) sur un pin 3V3, la masse (GND) sur une masse. Les pins “echo” et “trig” sont à brancher sur des pins digitals, ici echo sera branché sur D3 et trig sur D4.

Capteur Backpack Couleur Description
TRIG 4 VERT Sortie de signal
ECHO 3 JAUNE Entrée de signal
VCC 3V3 ROUGE Alimentation
GND GND BRUN Masse



Etape 1 : Bien commencer

Cette étape est identique sur la plupart des tutos car elle constitue la base indispensable de n’ilmporte quel programme pour Gamebuino.

Pour commencer, ouvrez l’éditeur Arduino préconfiguré pour la Gamebuino

-Vous devriez avoir ceci sur votre écran :

void setup() {
  // put your setup code here, to run once:
}

void loop() {
  // put your main code here, to run repeatedly:
}

Pour l’instant, le code est un peu vide, mais on va le compléter.

  • En premier lieu on a besoin d’ajouter au tout début du fichier la ligne suivante :
#include <Gamebuino-Meta.h>

C’est ce qu’on appelle une “librairie”, elle va nous permettre d’utiliser tout un tas de fonctions sans avoir à les programmer à la main. Cette librairie contient toutes les fonctions de la Gamebuino et est très utile pour la suite.
On va ajouter deux fonctions pour que notre programme puisse fonctionner :

  • Dans la fonction setup() on ajoute un appel à la fonction gb.begin() comme suit :
void setup() {
  // put your setup code here, to run once:
  gb.begin();
}

La fonction gb.begin() permet d’initialiser la console : sans cela rien ne fonctionnera !

  • Ensuite, on ajoute la fonction waitForUpdate() dans la fonction loop :
void loop() {
  // put your main code here, to run repeatedly:
  gb.waitForUpdate();
}

La fonction waitForUpdate() permet de rafraichir le contenu de l’écran (c’est à dire dessiner dessus), gère la lecture des sons, les appuis sur les touches, bref tout ce qui donne vie à votre Gamebuino.

On a à présent une structure de programme fonctionnelle, même si elle ne fait encore rien de concret.

Etape 2 : Lire les données du capteur

Avant d’obtenir une mesure de distance plus ou moins précise avec notre capteur il faut commencer par récupérer les données brutes, et pour cela il faut de petits réglages pour permettre à la console de communiquer avec le capteur.

  • En premier on doit configurer les entrées/sorties de notre capteur dans le programme comme suit :
#include <Gamebuino-Meta.h> 

#define US_PIN_INPUT_ECHO   3   // Attache le pin D3 au pin Echo du capteur US
#define US_PIN_OUTPUT_TRIG  4   // Attache le pin D4 au pin Trig du capteur US

Ici on utlise les define pour assigner des “noms” à nos pins D3 et D4 afin de les différencier et d’y faire référence plus facilement dans la suite de notre programme.

  • Ensuite on doit configurer le mode d’interaction de ces pins dans notre fonction setup() :
void setup() {
  gb.begin();
  
  pinMode( US_PIN_OUTPUT_TRIG, OUTPUT);   // Définit le pin TRIG comme sortie (OUTPUT)
  pinMode( US_PIN_INPUT_ECHO, INPUT);     // Définit le pin ECHO comme entrée (INPUT)
  digitalWrite(US_PIN_OUTPUT_TRIG, LOW);  // Démarrage du pin TRIG en mode sortie faible
}

C’est une étape cruciale car si l’on ne définit pas ces modes correctement il est impossible de communiquer avec notre capteur.

Maintenant nous allons pouvoir effectuer la mesure proprement dite.

Pour cela on commence par déclarer une fonction ultrasonic_measure() avec un retour en float.

  • La déclaration se fait donc ainsi :
float ultrasonic_measure() {

}

Jusque-là tout va bien.

  • On ajoute ensuite l’activation de l’émetteur ultrason TRIG sur 10ms :
float ultrasonic_measure() {

 digitalWrite(US_PIN_OUTPUT_TRIG, HIGH); 
 delayMicroseconds(10);             // Active le pin TRIG en mode HIGH pendant 10ms
 digitalWrite(US_PIN_OUTPUT_TRIG, LOW);
}

Cela nous permet d’émettre une vague d’ultrason dont on va pouvoir mesurer le temps de retour avec notre pin ECHO

  • Cette mesure là est effectuée ainsi :
float ultrasonic_measure() {

  digitalWrite(US_PIN_OUTPUT_TRIG, HIGH); 
  delayMicroseconds(10);                  // Active le pin TRIG en mode HIGH pendant 10ms
  digitalWrite(US_PIN_OUTPUT_TRIG, LOW);
  
  long duration = pulseIn(US_PIN_INPUT_ECHO, HIGH, 20000);   // Lecture du pin ECHO, retourne la temps de trajet de l'ultrason en microsecondes
  duration = duration * 144 / 100;  // On doit ajuster la mesure en ajoutent 44% à la valeur renvoyée par pulseIn()
  
  // Calcul de la distance
  long distance = duration * 0.034 / 2; // Vitesse du son divisée par 2 (car aller et retour)

  f32_distance = f32_distance*.9 + 0.1 * distance;
  return f32_distance;
}

On mesure l’écart de temps entre l’activation du pin TRIG et la détection de l’onde retour par le pin ECHO. On ajuste de 44% la valeur obtenue et on obtient la durée en microsecondes. Cet ajustement tient au capteur lui-même. Ensuite on peut simplement diviser ce temps par 1/2 de la vitesse du son pour obtenir une distance en vertu de la formule D = T * V (1/2 car l’onde fait un aller et retour et parcourt donc deux fois la distance).
En fin de fonction on retourne notre valeur distance.

Enfin on va ajouter un appel à notre fonction ultrasonic_measure() dans notre loop()

  • On en profite pour ajuster notre valeur tel que :
void loop() {
  gb.waitForUpdate();
  
  float d = ultrasonic_measure();
  if ( d > 50 ) d = 50;
  if ( d < 5 ) d = 5;
}

Ainsi on ne mesure “que” la plage entre 5 et 50 cm. Vous pouvez bien entendu ajuster ces valeurs si vous le souhaitez, le capteur est précis jusqu’à 3-4 mètres environ.

Etape 3 : Ajouter un visuel

Dans cette partie nous allons afficher les valeurs obtenues pendant notre mesure puis les transformer en une jauge dynamique pour représenter une distance.

  • On commence par déclarer une fonction display_bar(float) que l’on appelle bien entendu dans notre loop() :
void  display_bar(float distance) {

  gb.display.clear();
}
void loop() {
  gb.waitForUpdate();
  
  float d = ultrasonic_measure();
  if ( d > 50 ) d = 50;
  if ( d < 5 ) d = 5;
  
  display_bar(d);
}

Ici on a juste une fonction prenant un float en paramètre qui efface l’écran à chaque cycle.

  • On y ajoute donc l’affichage de nos valeurs de temps et de distance :
void  display_bar(float distance) {

  gb.display.clear();

  gb.display.print( "Duration : ");
  gb.display.println(duration);

  gb.display.print( "Distance : ");
  gb.display.println(f32_distance);
}

00001
Rien de bien compliqué, on utilise simplement des fonctions d’affichage standard pour afficher du texte et des valeurs numériques.

On peut maintenant commencer à créer notre jauge de distance.

  • Tout d’abord on affiche un rectangle vide avec la fonction drawRect() :
void  display_bar(float distance) {

  gb.display.clear();

  // Affichage des valeurs

  //Affichage de la jauge
  gb.display.drawRect(5, gb.display.height() - 15, gb.display.width() - 10, 10);
}

00004

  • Ensuite on remplit cette jauge avec la fonction fillRect() ET on ajuste la couleur de remplissage en fonction de la distance :
void  display_bar(float distance) {

  gb.display.clear();

  // Affichage des valeurs

  //Affichage de la jauge
  gb.display.drawRect(5, gb.display.height() - 15, gb.display.width() - 10, 10);

  //Remplissage de la jauge
  int32_t i32_bar_len = (((distance + 0.5) * 100) / 50) * (gb.display.width()- 12) / 100;
  gb.display.setColor(GREEN);
  if(distance < 35){
    gb.display.setColor(ORANGE);
  }
  if(distance < 15){
    gb.display.setColor(RED);
  }
  gb.display.fillRect(6, gb.display.height() - 14, i32_bar_len, 8);
}

00002 00003 00005
On remplit par défaut en vert, si la distance est inférieure à 35cm on passe en orange et en rouge si elle est en dessous de 15cm. Vous pouvez bien entendu changer ces valeurs si vous le souhaitez. Pensez à modifier le “padding” de notre valeur distance dans la fonction loop() si c’est le cas.

Et voilà, vous avez survécu à un nouveau tutoriel Gamebuino. Félicitations !

1 Like

Petite précision : les 44% ne proviennent pas du capteur, mais de la librairie de mesure de temps du SAM21.

Cette mesure de temps est effectuée par une boucle mal calibrée.

Le temps mesuré en microsecondes est sous estimé, ce qui nécessite de multiplier le résultat par 1.44 pour obtenir la valeur correcte.

1 Like

Ha ! Merci pour cette précision !.. Je ne comprenais pas du tout d’où venait cette bizarrerie ! :joy:

2 Likes