Construire un télémètre Arduino et un niveau à bulle numérique – Guide pas à pas
Dans ce tutoriel, nous allons apprendre à réaliser un télémètre Arduino et un niveau à bulle numérique. Vous pouvez regarder la vidéo suivante ou lire le tutoriel écrit ci-dessous. L'appareil comprend un capteur à ultrasons pour mesurer la distance à l'objet le plus proche, un accéléromètre pour mesurer l'angle par rapport au sol, un écran LCD pour afficher les résultats, et un PCB personnalisé sur lequel tous les composants sont connectés. On utilise l'appareil avec un seul bouton. Une fois alimenté, il faut sélectionner l'unité de mesure. En appuyant sur le bouton, on fait défiler les unités, et en le maintenant enfoncé un moment, on accède au premier programme. Ici, on peut mesurer la distance et stocker les deux dernières mesures. Pour accéder au second programme, on maintient à nouveau le bouton enfoncé. Ce programme permet de mesurer une surface carrée en prenant deux mesures de distance perpendiculaires. Le programme suivant est le niveau à bulle numérique, où l'on mesure l'angle par rapport au sol. Avec le bouton, on peut basculer entre les deux axes pour mesurer soit le Tangage (Pitch), soit le Roulis (Roll). Voici le schéma électrique de ce projet Arduino. Notez que j'ai déjà des tutoriels détaillés sur le fonctionnement de chacun de ces modules : Tutoriel capteur à ultrasons, Tutoriel LCD, Tutoriel accéléromètre MEMS. Vous pouvez vous procurer les composants nécessaires via les liens ci-dessous : Selon le schéma, nous devons concevoir le PCB personnalisé, ce que j'ai fait avec le logiciel gratuit EasyEDA. Une fois la conception terminée, on exporte simplement le fichier Gerber pour la fabrication. Vous pouvez consulter les fichiers de projet EasyEDA de ce projet ici. Ensuite, on commande le PCB chez JLCPCB, sponsor de ce projet. On glisse-dépose le fichier Gerber, on vérifie dans le visualiseur, on choisit les options, et on commande à prix raisonnable. Pour une première commande, jusqu'à 10 PCB pour 2$. Après quelques jours, les PCB sont arrivés. La qualité est excellente et tout correspond exactement à la conception. Maintenant, nous pouvons commencer l'assemblage électronique. J'ai commencé par souder des connecteurs à broches sur le PCB pour faciliter la connexion/déconnexion des composants. J'ai ensuite inséré et soudé les trois résistances. Deux servent de diviseur de tension pour le contraste du LCD (1kΩ à R1, 220Ω à R2). La troisième est une résistance de pull-up pour le bouton. Ensuite, j'ai fabriqué le boîtier. J'ai choisi de l'acrylique transparent pour laisser visible l'électronique. J'avais de l'acrylique de 5mm d'un ancien projet, découpé à la scie circulaire. J'ai dû faire une ouverture pour le LCD sur le dessus du boîtier (4mm d'épaisseur pour mieux s'adapter au LCD). J'ai d'abord percé deux trous, puis inséré une scie à métaux pour faire l'ouverture grossièrement, et affiné à la râpe pour que le LCD s'ajuste parfaitement. Avec une mèche à méplat, j'ai fait les ouvertures pour l'interrupteur d'alimentation, le bouton de contrôle et le capteur à ultrasons. Une fois toutes les pièces prêtes, j'ai assemblé le boîtier avec de l'époxy 5 minutes. Pour le couvercle, j'ai inséré et collé deux boulons à travers lesquels le panneau supérieur s'insère et se fixe avec des écrous. Le boîtier est prêt. J'ai soudé des connecteurs sur le LCD pour l'attacher facilement au PCB, ainsi que des fils sur l'interrupteur, le bouton et le connecteur de batterie. Finalement, j'ai tout assemblé : capteur à ultrasons sur le PCB et à travers les trous du panneau latéral, puis la carte Arduino, le module accéléromètre et le connecteur de batterie. Sur le panneau supérieur, j'ai fixé le LCD, l'interrupteur et le bouton, et les ai connectés au PCB. Enfin, j'ai inséré la pile 9V et fixé le panneau supérieur avec les écrous. Le projet de télémètre Arduino est terminé, il ne reste plus qu'à expliquer le programme. Examinons le code Arduino. Comme le code est long, je le posterai par sections avec description pour chacune. À la fin, je donnerai le code complet. D'abord, nous incluons la bibliothèque Wire.h pour la communication I2C de l'accéléromètre, et LiquidCrystal.h pour contrôler le LCD. Nous définissons le LCD, l'adresse I2C du MPU6050, les broches du capteur à ultrasons, et les variables nécessaires. Dans le setup, nous initialisons l'interface I2C de l'accéléromètre et l'écran LCD, et définissons les modes de broches pour le capteur à ultrasons (trigger, echo) et le bouton. Dans la boucle principale, nous avons un switch pour basculer entre les différents programmes. Au case 0, nous sélectionnons l'unité de mesure. Avec lcd.print() nous affichons le texte, et avec des if nous faisons défiler les quatre unités. La variable unitSelect agit dans la fonction personnalisée getDistance(), où elle indique vers quelle unité convertir l'unité de base cm fournie par le capteur à ultrasons. Pour sélectionner l'unité et accéder au premier programme, il suffit de maintenir le bouton enfoncé plus d'une demi-seconde. Au case 1 (programme mesure de distance), on obtient d'abord la distance à l'objet le plus proche avec la fonction getDistance(). Voyons comment fonctionne la fonction getDistance(). On utilise la broche trigger pour demander au capteur de générer une onde ultrasonore. Puis avec la broche echo et pulseIn(), on mesure la durée de l'aller-retour de l'onde. Connaissant la vitesse du son et le temps de trajet, on calcule facilement la distance. On affiche la distance mesurée avec du texte sur le LCD, et avec des "if", si on appuie sur le bouton, on affiche/sauvegarde les deux dernières mesures. Le programme suivant calcule une surface : on prend deux mesures perpendiculaires et on les multiplie pour obtenir l'aire du rectangle qu'elles forment. Le dernier case est le programme de mesure d'angle. Nous devons lire les données de l'accéléromètre, qui correspondent à l'intensité du champ gravitationnel terrestre sur trois axes X, Y, Z. La valeur de chaque axe est stockée sur 2 registres, il faut donc lire 6 registres au total et les combiner. Une fois qu'on a les valeurs X, Y, Z de l'accéléromètre, on calcule l'angle de Tangage (rotation autour de Y) et l'angle de Roulis (rotation autour de X) avec les deux équations. Plus de détails sur ces équations dans la note d'application Freescale Semiconductor Tilt Sensing Using a Three-Axis Accelerometer. Après, on affiche les valeurs sur le LCD, et en appuyant sur le bouton on change l'affichage entre Tangage et Roulis. C'est tout pour ce tutoriel. J'espère que vous avez apprécié ce projet Arduino et appris quelque chose de nouveau. N'hésitez pas à poser vos questions dans les commentaires ci-dessous.Vue d'ensemble




Schéma de câblage du télémètre Arduino

PCB à conception personnalisée



Assemblage de l'appareil









Code source du télémètre et niveau à bulle numérique Arduino
#include <Wire.h> // Bibliothèque communication I2C
#include <LiquidCrystal.h> // Bibliothèque LiquidCrystal
LiquidCrystal lcd(7, 6, 5, 4, 3, 2); // Objet LCD (rs, enable, d4, d5, d6, d7)
const int MPU = 0x68; // Adresse I2C du MPU6050
#define trigPin 8
#define echoPin 9
#define selectButton 10
int16_t AcX, AcY, AcZ;
long duration;
float distance;
int program = 0;
float d = 0, d1 = 0, d2 = 0, area = 0;
int axis = 0, angle = 0;
int unitSelect = 0;
String unit = "cm";void setup() {
Wire.begin();
Wire.beginTransmission(MPU);
Wire.write(0x6B);
Wire.write(0);
Wire.endTransmission(true);
lcd.begin(16, 2);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
pinMode(selectButton, INPUT_PULLUP);
}switch (program) {
case 0: // Sélection unité de mesure
lcd.setCursor(0, 0);
lcd.print("Select Unit: ");
lcd.setCursor(13, 0);
lcd.print(unit); lcd.print(" ");
delay(10);
// Si bouton pressé - changer unité
if (digitalRead(selectButton) == 0) {
if (unitSelect == 0) { unit = "in"; unitSelect = 1; }
else if (unitSelect == 1) { unit = "m"; unitSelect = 2; }
else if (unitSelect == 2) { unit = "ft"; unitSelect = 3; }
else if (unitSelect == 3) { unit = "cm"; unitSelect = 0; }
// Si bouton maintenu > 0.5s - changer programme
delay(500);
if (digitalRead(selectButton) == 0) {
program = 1; lcd.clear(); delay(500);
}
}
break;// Conversion des unités
if (unitSelect == 1) { distance = distance; unit = "cm"; } // cm vers cm
else if (unitSelect == 2) { distance = distance * 0.393701; unit = "in"; } // cm vers pouces
else if (unitSelect == 3) { distance = distance * 0.01; unit = "m"; } // cm vers mètres
else if (unitSelect == 0) { distance = distance * 0.0328; unit = "ft"; } // cm vers pieds// Si bouton maintenu > 0.5s - changer programme
delay(500);
if (digitalRead(selectButton) == 0) {
program = 1; lcd.clear(); delay(500);
}
break;case 1: // Programme mesure de distance
distance = getDistance();
lcd.setCursor(0, 0);
lcd.print("Dist: "); lcd.print(distance); lcd.print(" ");
lcd.setCursor(14, 0); lcd.print(unit); delay(10);
lcd.setCursor(0, 1); lcd.print("d:"); lcd.setCursor(8, 1); lcd.print("d:"); delay(200);
// Sauvegarder distance 1
if (digitalRead(selectButton) == 0) {
if (d == 0) {
lcd.setCursor(0, 1); lcd.print("d: "); lcd.setCursor(2, 1); lcd.print(distance); d = 1; delay(100);
}
// Sauvegarder distance 2
else if (d == 1) {
lcd.setCursor(8, 1); lcd.print("d: "); lcd.setCursor(10, 1); lcd.print(distance); d = 0; delay(100);
}
// Si bouton maintenu > 0.5s changer programme
delay(500);
if (digitalRead(selectButton) == 0) { program = 2; d = 0; lcd.clear(); delay(500); }
}
break;//===== getDistance - Fonction personnalisée
float getDistance() {
digitalWrite(trigPin, LOW);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
distance = duration * 0.034 / 2; // distance en cm
// Conversion des unités
if (unitSelect == 1) { distance = distance; unit = "cm"; }
else if (unitSelect == 2) { distance = distance * 0.393701; unit = "in"; }
else if (unitSelect == 3) { distance = distance * 0.01; unit = "m"; }
else if (unitSelect == 0) { distance = distance * 0.0328; unit = "ft"; }
return distance;
}
case 2: // Programme mesure de surface
distance = getDistance();
lcd.setCursor(0, 0);
lcd.print("Area: "); lcd.print(area); lcd.setCursor(12, 0); lcd.print(unit); lcd.print("^2"); delay(200);
if (d == 0) { lcd.setCursor(0, 1); lcd.print("d1: "); lcd.setCursor(3, 1); lcd.print(distance); delay(200); }
else if (d == 1) { lcd.setCursor(9, 1); lcd.print("d2: "); lcd.setCursor(12, 1); lcd.print(distance); delay(200); }
else if (d == 2) { lcd.setCursor(6, 0); lcd.print(area); delay(200); }
// Sauvegarder distance 1
if (digitalRead(selectButton) == 0) {
if (d == 0) { lcd.setCursor(0, 1); lcd.print("d1: "); lcd.setCursor(3, 1); lcd.print(distance); d = 1; d1 = distance; delay(100); }
// Sauvegarder distance 2
else if (d == 1) { lcd.setCursor(9, 1); lcd.print("d2: "); lcd.setCursor(12, 1); lcd.print(distance); d = 2; d2 = distance; area = d1 * d2; delay(100); }
else if (d == 2) { lcd.clear(); d = 0; area = 0; delay(100); }
// Si bouton maintenu > 0.5s changer programme
delay(500);
if (digitalRead(selectButton) == 0) { program = 3; d = 0; lcd.clear(); delay(500); }
}
break;case 3: // Programme mesure d'angle
// Lecture données accéléromètre
Wire.beginTransmission(MPU);
Wire.write(0x3B); // Registre de départ ACCEL_XOUT_H
Wire.endTransmission(false);
Wire.requestFrom(MPU, 6, true); // Lire 6 registres
AcX = Wire.read() << 8 | Wire.read(); // Axe X
AcY = Wire.read() << 8 | Wire.read(); // Axe Y
AcZ = Wire.read() << 8 | Wire.read(); // Axe Z
if (axis == 0) {
// Calcul angle Tangage (rotation autour de Y)
angle = atan(-1 * AcX / sqrt(pow(AcY, 2) + pow(AcZ, 2))) * 180 / PI;
lcd.setCursor(0, 0); lcd.print("Pitch");
} else if (axis == 1) {
// Calcul angle Roulis (rotation autour de X)
angle = atan(-1 * AcY / sqrt(pow(AcX, 2) + pow(AcZ, 2))) * 180 / PI;
lcd.setCursor(0, 0); lcd.print("Roll ");
}
lcd.setCursor(0, 1); lcd.print("Angle: "); lcd.print(abs(angle)); lcd.print(" "); lcd.setCursor(10, 1); lcd.print("deg"); delay(200);
// Changer d'axe
if (digitalRead(selectButton) == 0) {
if (axis == 0) { axis = 1; delay(100); }
else if (axis == 1) { axis = 0; delay(100); }
// Si bouton maintenu > 0.5s changer programme
delay(500);
if (digitalRead(selectButton) == 0) { program = 0; lcd.clear(); delay(500); }
}
break;
}Code source complet :
/* DIY Digital Range Measurer and Spirit Level
by Dejan Nedelkovski, www.HowToMechatronics.com */
#include <Wire.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);
const int MPU = 0x68;
#define trigPin 8
#define echoPin 9
#define selectButton 10
int16_t AcX, AcY, AcZ;
long duration;
float distance;
int program = 0;
float d = 0, d1 = 0, d2 = 0, area = 0;
int axis = 0, angle = 0;
int unitSelect = 0;
String unit = "cm";
void setup() {
Wire.begin();
Wire.beginTransmission(MPU);
Wire.write(0x6B); Wire.write(0); Wire.endTransmission(true);
lcd.begin(16, 2);
pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); pinMode(selectButton, INPUT_PULLUP);
}
void loop() {
switch (program) {
case 0:
lcd.setCursor(0, 0); lcd.print("Select Unit: "); lcd.setCursor(13, 0); lcd.print(unit); lcd.print(" "); delay(10);
if (digitalRead(selectButton) == 0) {
if (unitSelect == 0) { unit = "in"; unitSelect = 1; }
else if (unitSelect == 1) { unit = "m"; unitSelect = 2; }
else if (unitSelect == 2) { unit = "ft"; unitSelect = 3; }
else if (unitSelect == 3) { unit = "cm"; unitSelect = 0; }
delay(500);
if (digitalRead(selectButton) == 0) { program = 1; lcd.clear(); delay(500); }
}
break;
case 1:
distance = getDistance();
lcd.setCursor(0, 0); lcd.print("Dist: "); lcd.print(distance); lcd.print(" "); lcd.setCursor(14, 0); lcd.print(unit); delay(10);
lcd.setCursor(0, 1); lcd.print("d:"); lcd.setCursor(8, 1); lcd.print("d:"); delay(200);
if (digitalRead(selectButton) == 0) {
if (d == 0) { lcd.setCursor(0, 1); lcd.print("d: "); lcd.setCursor(2, 1); lcd.print(distance); d = 1; delay(100); }
else if (d == 1) { lcd.setCursor(8, 1); lcd.print("d: "); lcd.setCursor(10, 1); lcd.print(distance); d = 0; delay(100); }
delay(500);
if (digitalRead(selectButton) == 0) { program = 2; d = 0; lcd.clear(); delay(500); }
}
break;
case 2:
distance = getDistance();
lcd.setCursor(0, 0); lcd.print("Area: "); lcd.print(area); lcd.setCursor(12, 0); lcd.print(unit); lcd.print("^2"); delay(200);
if (d == 0) { lcd.setCursor(0, 1); lcd.print("d1: "); lcd.setCursor(3, 1); lcd.print(distance); delay(200); }
else if (d == 1) { lcd.setCursor(9, 1); lcd.print("d2: "); lcd.setCursor(12, 1); lcd.print(distance); delay(200); }
else if (d == 2) { lcd.setCursor(6, 0); lcd.print(area); delay(200); }
if (digitalRead(selectButton) == 0) {
if (d == 0) { lcd.setCursor(0, 1); lcd.print("d1: "); lcd.setCursor(3, 1); lcd.print(distance); d = 1; d1 = distance; delay(100); }
else if (d == 1) { lcd.setCursor(9, 1); lcd.print("d2: "); lcd.setCursor(12, 1); lcd.print(distance); d = 2; d2 = distance; area = d1 * d2; delay(100); }
else if (d == 2) { lcd.clear(); d = 0; area = 0; delay(100); }
delay(500);
if (digitalRead(selectButton) == 0) { program = 3; d = 0; lcd.clear(); delay(500); }
}
break;
case 3:
Wire.beginTransmission(MPU); Wire.write(0x3B); Wire.endTransmission(false);
Wire.requestFrom(MPU, 6, true);
AcX = Wire.read() << 8 | Wire.read(); AcY = Wire.read() << 8 | Wire.read(); AcZ = Wire.read() << 8 | Wire.read();
if (axis == 0) { angle = atan(-1 * AcX / sqrt(pow(AcY, 2) + pow(AcZ, 2))) * 180 / PI; lcd.setCursor(0, 0); lcd.print("Pitch"); }
else if (axis == 1) { angle = atan(-1 * AcY / sqrt(pow(AcX, 2) + pow(AcZ, 2))) * 180 / PI; lcd.setCursor(0, 0); lcd.print("Roll "); }
lcd.setCursor(0, 1); lcd.print("Angle: "); lcd.print(abs(angle)); lcd.print(" "); lcd.setCursor(10, 1); lcd.print("deg"); delay(200);
if (digitalRead(selectButton) == 0) {
if (axis == 0) { axis = 1; delay(100); }
else if (axis == 1) { axis = 0; delay(100); }
delay(500);
if (digitalRead(selectButton) == 0) { program = 0; lcd.clear(); delay(500); }
}
break;
}
}
float getDistance() {
digitalWrite(trigPin, LOW); digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH); distance = duration * 0.034 / 2;
if (unitSelect == 1) { distance = distance; unit = "cm"; }
else if (unitSelect == 2) { distance = distance * 0.393701; unit = "in"; }
else if (unitSelect == 3) { distance = distance * 0.01; unit = "m"; }
else if (unitSelect == 0) { distance = distance * 0.0328; unit = "ft"; }
return distance;
}
Processus de fabrication
- Construire une Centrale DCC Numérique pour Modélisme Ferroviaire avec Arduino – Application Android Gratuite Incluse
- Dé numérique Arduino sur écran LCD 16x2 – Générateur aléatoire à bouton poussoir
- Créer des animations et jeux sur LCD avec Arduino UNO
- Détecteur de fréquence audio Arduino — Mesurer le pic sonore avec module haute sensibilité
- Construisez votre propre Tamagotchi Arduino : Un animal de compagnie numérique DIY
- Morpion sur matrice LED MAX7219 avec boîtier en carton
- Construire un voltmètre DIY avec Arduino et écran Nokia 5110
- Construire un minuteur à rebours Arduino fiable avec afficheur 7 segments SparkFun
- Contrôle Arduino UNO depuis Python 3 – Communication Série et Démo LED