Traceur de randonnée avancé avec Arduino : GPS, capteurs et batterie
Composants et fournitures
- Arduino 101
- Piles AA + Support 4×AA
- Accessory Shield (carte d'extension)
- Capteur de pression Adafruit BMP180
- GPS Adafruit Ultimate GPS Breakout
- Capteur magnétique 3 axes Adafruit (HMC5883)
- Capteur d'humidité Adafruit AM2320
- Piles bouton CR2012 – 2 unités (pour RTC)
- Résistances : 10 kΩ, 3,9 kΩ
Outils et machines nécessaires
- Pistolet à colle chaude
- Fer à souder
Applications et services en ligne
- Arduino IDE
À propos du projet
Qu'est-ce qu'un Hiking Tracker ?
Le Hiking Tracker est un dispositif pour détecter les changements dans l'environnement d'un randonneur pendant la marche.
L'idée est d'observer les variations de température, pression, humidité, altitude, position, direction, etc. Cela donne des informations intéressantes sur la randonnée.
En montagne, où il fait froid, sec, avec une air de faible densité comparé aux plaines, beaucoup de gens ont du mal à respirer. Certains ressentent des irritations cutanées dues à la sécheresse. Ce dispositif permet aux randonneurs de connaître leurs limites. Il y a aussi le plaisir d'aller en haute altitude. Pouvoir connaître l'altitude est amusant !
Pas seulement les montagnes, mais aussi l'exploration de marais, déserts, forêts – chacun a son profil environnemental unique. Pouvoir surveiller l'environnement en déplacement est une meilleure façon de comprendre la nature.

Démonstration vidéo
[Vidéo non incluse dans le texte source]
Étape 1 : Matériel – quel capteur pour quoi ?
Il y a beaucoup de détection dans ce projet.
L'Accessory Shield embarque plusieurs dispositifs I2C :
- LM75B capteur de température pour mesurer la température ambiante
- ADXL345 accéléromètre 3 axes pour détecter l'inclinaison et la gravité
- DS3231 RTC haute précision pour mesurer l'heure
- HMC5883 capteur magnétique 3 axes pour détecter le cap compas
- AM2320 capteur d'humidité pour mesurer le % HR de l'air
- BMP180 capteur de pression pour mesurer la pression atmosphérique et l'altitude
- MTK3339 GPS pour mesurer la position et la distance parcourue
Sur l'Arduino Uno (via le shield) :
- Diviseur de tension 3,9 kΩ + 22 kΩ pour mesurer la tension de la batterie 4×AA
- OLED 1306 pour affichage des données
- Buzzer pour alarme sonore
- LED RGB non utilisée pour ce projet
- Interface XBee non utilisée mais broches D2, D3, D9, D10 accessibles pour d'autres projets (D2 connecté au reset, permet reset logiciel !)
- Joystick 5 directions non utilisé
- Potentiomètre 101 non utilisé
Étape 2 : Modification et connexion du matériel
Quelques modifications sur l'Arduino Uno. Il est monté sur un support 4 piles AA avec entretoises vissées et colle chaude.


4 piles AA et CR1220 (pour RTC) installées sur les supports.


Il y a un espace entre le support de piles et la carte Arduino Uno où peuvent être placés les capteurs de pression, humidité, magnétique et GPS.


Les capteurs I2C sont soudés ensemble sur une plaque d'essai et placés dans cet espace.


Ces capteurs sont connectés à l'Arduino Uno depuis le côté inférieur :

Un diviseur de tension est ajouté pour mesurer la tension du pack 4 piles AA.

La ligne de détection de tension du pack AA va sur l'ADC A1 :

Le joystick du shield est mappé sur la broche ACD A1 via la broche A5. C'est pourquoi le joystick est dessoudé et retiré.

En connectant certains pads sur l'Accessory Shield (voir schéma de référence) avec des ponts de soudure, les broches D2 (reset logiciel), D3, D9, D10 de l'Arduino sont rendues disponibles sur l'interface XBee.


Les composants s'empilent ainsi :
- Couche supérieure : Accessory Shield sur Arduino
- Couche intermédiaire : Autres capteurs et GPS entre Uno et boîtier piles
- Couche inférieure : Support 4 piles AA avec piles
Et les connexions ressemblent à ceci :

Étape 3 : Programmation du dispositif
Arduino IDE Build 1.8.5 est utilisé pour programmer le dispositif. D'abord, toutes les bibliothèques suivantes sont incluses ou téléchargées via le gestionnaire de bibliothèques.

En tapant le nom du capteur dans la zone de recherche du gestionnaire, les bibliothèques appropriées apparaissent.

Certaines bibliothèques de l'Accessory Shield (voir références) sont ajoutées via l'option fichier zip.

Après l'ajout des bibliothèques nécessaires, les codes d'exemple de chaque capteur sont examinés pour trouver les API associées.
Ensuite, tous les en-têtes de bibliothèques sont inclus dans un sketch Arduino vide.
Liste des fichiers d'en-tête
math.h, inttypes.h, Wire.h, lm75.h, ADXL345.h, ChainableLED.h, U8glib.h, ds3231.h,
Adafruit_Sensor.h, Adafruit_AM2320.h, Adafruit_BMP085_U.h, Adafruit_HMC5883_U.h, Adafruit_GPS.h
Après de multiples éditions, compilations et débogages (connexions lâches comprises, où j'ai découvert que le BMP180 fonctionne sans Vcc grâce à l'alimentation de fuite sur les broches I2C peut-être) et téléversement, le code était enfin prêt.
Les mises en garde (Caveats)
- Le calcul d'altitude est basé sur la chute de pression d'air, applicable seulement par conditions météorologiques normales.
- Le code du compas n'est pas compensé en inclinaison logiciellement ; l'appareil doit être tenu dans un plan horizontal. Il y a un cercle de compas fixe, dans lequel il y a un autre cercle de rayon variable. Quand l'appareil est incliné, le cercle intérieur s'agrandit. Quand il est en position horizontale (composantes x et y de l'accéléromètre proches de 0), le cercle intérieur se réduit à un point. C'est à ce moment que le cap compas est plus précis.
- L'angle de déclinaison du compas dépend de la position et de la variation du champ magnétique terrestre, qui peut être affecté par les tempêtes solaires. Sans angle de déclinaison, le cap compas sera décalé de quelques degrés. Trouvez la déclinaison pour votre zone : magnetic-declination.com
- Le cap compas est sensible aux objets magnétiques proches, comme la présence de minéraux magnétiques forts en montagne.
- Tension minimale de fonctionnement : environ 4,5 V. C'est quand les piles AA doivent être remplacées.
- L'heure et la date sont programmées depuis le code ; pour changer l'heure, la pile bouton doit être débranchée et rebranchée. Un nouveau téléversement avec la nouvelle heure dans le code changera l'heure.
- Pendant le développement, le module GPS n'était pas disponible. Des coordonnées de démonstration sont placées dans Lat-Long. Pour reproduire ce projet, il faut inclure la bibliothèque GPS et les codes associés.
- Le plan XY de l'accéléromètre et du magnétomètre dépend du placement sur le PCB. Le code doit être ajusté en conséquence.
- La précision de l'accéléromètre est sensible aux vibrations. Il est conseillé d'utiliser l'appareil à l'arrêt.
Pistes d'amélioration
Des améliorations peuvent être faites côté firmware pour plus de fonctionnalités :
- Journalisation périodique des paramètres sur EEPROM
- Alarme buzzer à l'atteinte d'étapes d'altitude/position
- Rappel boire de l'eau
- Rappel faire une pause
- Alarme batterie faible
- Alerte température/humidité basse
- Calibration logicielle du compas pour compensation d'inclinaison (beaucoup de trigonométrie)
- Récupération auto de la déclinaison via GPS et connectivité IoT par application passerelle
Côté matériel :
- Interrupteurs utilisateur pour régler l'heure, la déclinaison, etc.
- Boîtier personnalisé imprimé en 3D
- Utilisation batterie LiPo rechargeable
- Conception PCB compacte mono-carte pour plus de portabilité
Conclusion
Voyager et randonner c'est cool, quand on peut vérifier les changements de l'environnement, ça rend les choses plus intéressantes. Spécialement, vérifier l'altitude, l'humidité, la pression et les changements de température en quelques heures de randonnée. Cet appareil vous laisse savoir à quelle hauteur vous ressentez le mal d'altitude, quel niveau d'humidité assèche votre peau – des trucs comme ça. Bien qu'il y ait de la place pour l'amélioration tant sur la disposition du circuit que sur le code pour gérer les mises en garde, c'est encore cool d'avoir un gadget comme ça en partant dans la nature !
Ressources externes
https://www.waveshare.com/wiki/Accessory_Shield
Matériel recommandé pour une meilleure version de ce projet
Kit de prototypage rapide
Code
Hiking_Tracker.ino
/*/////////// NOTE //////////
D2 allows soft reset assertable from code
D3,D9,D10 are available through 12,13,16 of xbee interface
D4, D13 are not accessable
///////////////////////////*/
//// HEADER FILES FOR LIBRARY /////
#include
#include
#include
#include
#include
#include
#include "U8glib.h"
#include "ds3231.h"
#include "Adafruit_Sensor.h"
#include "Adafruit_AM2320.h"
#include
#include
#include
/////////////////////// RTC Variables ///////////////////
uint8_t time[8];
struct ts t;
int s, m, h, dy, mo, yr;
///////////////// Accelerometer Variables ///////////////
float X = 0.0, Y = 0.0, Z = 0.0, Gravity = 0.0;
///////////////// Magnetometer Variables ////////////////
float Xm = 0.0, Ym = 0.0, Zm = 0.0;
/////////////////////// RGB LED Variables ///////////////
const int rgb_pwr = 12;
const int clk_pin = 6;
const int data_pin = 5;
float hue = 0.0;
boolean up = true;
////////////////////// Potentiometer ///////////////////
int pot = 0;
//////////////////// Batt/Supply Vin ///////////////////
float Vbatt = 0.0;
////////////////////// Thermometer //////////////////////
float temp = 0.0;
///////////////////// Humidity /////////////////////////
float humid = 0.0;
//////////////////// Air pressure //////////////////////
double prsr = 0.0;
//////////////////// Altitude ////////////////////////
float alt = 0.0;
//////////////// Lat, Long ////////////////
float lat = 0.0, lon = 0.0;
//////////////// Compass Heading ////////////////
float heading = 0.0;
/////////////////// Other Variables ///////////////
int mstime = 0;
int sensor_selector = 1;
//////////// ENUM //I2C Device type Object /////////////////
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE | U8G_I2C_OPT_DEV_0);
TempI2C_LM75 termo = TempI2C_LM75(0x48, TempI2C_LM75::nine_bits);
ADXL345 accelerometer;
ChainableLED leds(clk_pin, data_pin, rgb_pwr, 1);
Adafruit_AM2320 am2320 = Adafruit_AM2320();
Adafruit_BMP085_Unified bmp180 = Adafruit_BMP085_Unified(10085);
Adafruit_HMC5883_Unified mag = Adafruit_HMC5883_Unified(12345);
// Uncomment to enable GPS (Serial debugging won't be available)
// HardwareSerial mySerial = Serial;
// Adafruit_GPS GPS(&mySerial);
void setup(void) {
// 1.1V Internal Analog Ref
// analogReference(INTERNAL);
// Signals for OLED on Accessory Shield
// solder bridged on shield needed for D2,D3,D9,D10
pinMode(2, OUTPUT); // self reset D2 to RST
pinMode(3, OUTPUT); // outs at xbee int 12
pinMode(9, OUTPUT); // outs at xbee int 13
pinMode(10, OUTPUT); // outs at xbee int 16
digitalWrite(2, HIGH); digitalWrite(3, HIGH);
digitalWrite(9, LOW); digitalWrite(10, HIGH);
pinMode(7, OUTPUT); pinMode(8, OUTPUT);
digitalWrite(7, HIGH); digitalWrite(8, LOW);
// 10k POT on A0
// Vin Batt/Supply on A1 (3.91k/21.76k)
// Serial Comm for Debuging (optional)
// Serial.begin(9600);
// Accel Init Waiting
if (!accelerometer.begin()) { delay(50); }
// RTC Interrupt enabling
DS3231_init(DS3231_INTCN);
// Buzzer Init
pinMode(11, OUTPUT);
digitalWrite(11, LOW);
}
void loop(void) {
// picture loop
u8g.firstPage();
do { draw(); } while (u8g.nextPage());
// switch between I2C sensors
sensor_selector++;
if (sensor_selector >= 3) sensor_selector = 0;
////// Temperature Fetch API //////
temp = termo.getTemp();
delay(5);
/////// Pressure Fetch API ////////
if (sensor_selector == 0) {
if (!bmp180.begin()) delay(11);
sensors_event_t event;
bmp180.getEvent(&event);
if (event.pressure) {
prsr = event.pressure / 10; // hPa to kPa
delay(50);
}
}
////////////// GPS Init //////////
// GPS.begin(9600);
/////// Altitude Fetch API ////////
if (sensor_selector == 0) {
sensors_event_t event;
bmp180.getEvent(&event);
alt = bmp180.pressureToAltitude(1013.25, event.pressure);
delay(50);
}
////////////// Humidity Sensor Init ///////
if (sensor_selector == 1) {
am2320.begin();
delay(50);
humid = am2320.readHumidity();
delay(50);
}
////// Acceleration Fetch API //////
Vector norm = accelerometer.readNormalize();
X = norm.XAxis; Y = norm.YAxis; Z = norm.ZAxis;
Gravity = sqrt(X*X + Y*Y + Z*Z) - 0.3; // offset
///// Time Fetch API ////////
DS3231_get(&t);
s = t.sec; m = t.min; h = t.hour; dy = t.mday; mo = t.mon; yr = t.year;
///// Pot Position Fetch ///////
pot = analogRead(A0) * 5 / (10 * 3);
delay(2);
///// VBatt/Supply Fetch ///////
Vbatt = (1.08 * analogRead(A1) / 1023) / 3.91 * ((3.91 + 21.76));
delay(2);
///////// Compass Heading ////////
if (sensor_selector == 2) {
if (!mag.begin()) { while(1); }
delay(70);
sensor_t sensor2;
mag.getSensor(&sensor2);
delay(70);
float declination = 0.0;
sensors_event_t event2;
mag.getEvent(&event2);
heading = atan2(event2.magnetic.y, event2.magnetic.x);
heading += declination;
if (heading < 0) heading += 2*PI;
if (heading > 2*PI) heading -= 2*PI;
heading = heading * 180 / M_PI;
}
///// Buzzer Control //////////
if (pot > 80) digitalWrite(11, HIGH); else digitalWrite(11, LOW);
///// RGB Addressable LED Control /////////////
if (pot > 40) {
leds.pwr_set(PWR_ENABLE);
for (byte i = 0; i < 1; i++) leds.setColorHSB(i, hue, 1.0, 0.5);
if (up) hue += 0.025; else hue -= 0.025;
if (hue >= 1.0 && up) up = false;
else if (hue <= 0.0 && !up) up = true;
}
////////// Self Reset ///////////
// digitalWrite(2, LOW);
} ///////// Void Loop ends Here ///
////////////////// Oled Picture Loop Draw Fn ///////////////////
void draw(void) {
u8g.setFont(u8g_font_7x13);
u8g.drawHLine(37, 0, 62);
u8g.setPrintPos(41, 12); if (h < 10) u8g.print(0); u8g.print(h); u8g.drawStr(54, 12, ":");
u8g.setPrintPos(62, 12); if (m < 10) u8g.print(0); u8g.print(m); u8g.drawStr(75, 12, ":");
u8g.setPrintPos(83, 12); if (s < 10) u8g.print(0); u8g.print(s);
u8g.drawHLine(37, 14, 62);
u8g.setFont(u8g_font_5x8);
u8g.drawVLine(37, 0, 14);
u8g.setPrintPos(0, 7); if (dy < 10) u8g.print(0); u8g.print(dy); u8g.drawStr(11, 7, "/");
u8g.setPrintPos(17, 7); if (mo < 10) u8g.print(0); u8g.print(mo); u8g.drawStr(0, 16, "/");
u8g.setPrintPos(6, 16); u8g.print(yr);
u8g.drawVLine(99, 0, 14);
u8g.drawStr(104, 7, "BATT");
u8g.setPrintPos(102, 15); u8g.print(Vbatt); u8g.drawStr(123, 15, "V");
u8g.print(round(temp)); u8g.drawStr(55, 25, "'C");
u8g.setFont(u8g_font_5x8);
u8g.setPrintPos(15, 40); u8g.print(round(X));
u8g.setPrintPos(60, 40); u8g.print(round(Y));
u8g.setPrintPos(100, 40); u8g.print(round(Z));
u8g.setPrintPos(95, 22); u8g.print(Vbatt); u8g.drawStr(123, 22, "V");
u8g.drawVLine(37, 18, 36);
u8g.drawStr(39, 24, "AIR TEMP: "); u8g.setPrintPos(85, 24); u8g.print(temp); u8g.drawStr(118, 24, "C");
u8g.drawStr(39, 34, "HUMIDITY: "); u8g.setPrintPos(85, 34); u8g.print(humid); u8g.drawStr(118, 34, "%");
u8g.drawStr(39, 44, "PRESSURE: "); u8g.setPrintPos(85, 44); u8g.print(prsr); u8g.drawStr(118, 44, "hP");
u8g.drawStr(39, 54, "ALTITUDE: "); u8g.setPrintPos(85, 54); u8g.print(round(alt)); u8g.drawStr(118, 54, "m");
u8g.drawHLine(0, 56, 128);
u8g.drawStr(19, 64, "LAT:"); u8g.setPrintPos(39, 64); u8g.print(23.57); // Demo
u8g.drawStr(69, 64, "LONG:"); u8g.setPrintPos(94, 64); u8g.print(90.36); // Demo
u8g.print(round(temp)); u8g.drawStr(55, 25, "'C");
int r = round(sqrt(X*X + Y*Y));
u8g.drawStr(0, 22, "heading");
u8g.drawCircle(18, 34, r, U8G_DRAW_ALL); // inner leveling circle
u8g.drawCircle(18, 34, 10, U8G_DRAW_ALL); // outer fixed circle
u8g.setPrintPos(0, 53); u8g.print(heading);
if ((heading > 315) || (heading <= 45)) u8g.drawLine(18, 34, 8, 34); // N
if ((heading > 45) && (heading <= 135)) u8g.drawLine(18, 34, 18, 24); // E
if ((heading > 135) && (heading <= 225)) u8g.drawLine(18, 34, 28, 34); // S
if ((heading > 225) && (heading < 315)) u8g.drawLine(18, 34, 18, 44); // W
}
Bibliothèques
Décompressez et ajoutez les fichiers zip individuels au gestionnaire de bibliothèques Arduino.
No preview (download only).
Schémas

Processus de fabrication
- Contrôler une LED avec un capteur de mouvement PIR sur Raspberry Pi
- Construire un capteur d'humidité du sol Raspberry Pi low-cost pour irrigation intelligente
- Suivre l'exercice quotidien de votre hamster avec un tracker de fitness Raspberry Pi
- Test du capteur de température DS18B20 sur Raspberry Pi
- Construire un moniteur de température domestique avec Raspberry Pi, MCP9808, InfluxDB et Grafana
- Moniteur d'hygiène des toilettes alimenté par Walabot
- Capteur d'émotion & EEG : Matériel low-cost pour détection d'émotion en temps réel
- Envoyer les données IMU 10DOF Adafruit du Raspberry Pi 2 vers Azure Event Hubs avec Windows 10 IoT Core
- Suivi WiFi RSSI précis pour capteurs ISS