Geavanceerde wandeltracker met Arduino: GPS, sensoren & batterijpack
Onderdelen en benodigdheden
| Onderdeel | Aantal |
|---|---|
| Arduino 101 | 1 |
| AA Batterijen | 1 pak |
| 4xAA batterijhouder | 1 |
| Accessory Shield | 1 |
| Adafruit BMP180 Druksensor | 1 |
| Adafruit Ultimate GPS Breakout | 1 |
| Adafruit 3-Axis Magneticsensor (HMC5883) | 1 |
| Adafruit AM2320 Vochtigheidssensor | 1 |
| Adafruit Knopcel CR2012 (voor RTC) | 2 |
| Weerstand 10k ohm | 1 |
| Weerstand 3.9k ohm | 1 |
Benodigde tools en machines
- Lijmpistool
- Soldeerbout
Apps en online diensten
- Arduino IDE
Over dit project
Wat is een Hiking Tracker?
Een Hiking Tracker is een apparaat dat veranderingen in de omgeving van een wandelaar tijdens het wandelen meet.
Het idee is om veranderingen in temperatuur, druk, vochtigheid, hoogte, locatie, richting, etc. te observeren. Het geeft interessante inzichten in het wandelen.
In de bergen, waar het koud, droog en de luchtdichtheid laag is ten opzichte van laaggelegen gebieden, vinden veel mensen het moeilijk te ademen. Sommigen ervaren droge huidirritatie. Dit apparaat laat wandelliefhebbers hun grenzen kennen. Er is ook de plezier van het bezoeken van hoge locaties. In staat zijn om de hoogte te weten is leuk!
Niet alleen bergen, maar ook moerassen, woestijnen, bossen verkennen – elk met zijn unieke omgevingsprofiel – de omgeving on-the-go te monitoren is een betere manier om de natuur te begrijpen.

Stap 1: Hardware, wat voor wat?
Er vindt veel meting plaats in dit project.
De Accessory Shield bevat een aantal I2C-apparaten aan boord:
- LM75B temperatuursensor voor omgevingstemperatuur
- ADXL345 3-as versnellingsmeter voor kanteling en zwaartekracht
- DS3231 hoge-precisie RTC voor tijdmeting
- HMC5883 3-as magnetische sensor voor kompasrichting
- AM2320 vochtigheidssensor voor % RH van lucht
- BMP180 druksensor voor atmosferische druk en hoogte
- MTK3339 GPS-sensor voor locatie en gelopen afstand
Op de Arduino Uno (via shield):
- 3.9k + 22k spanningsdeler voor meting 4xAA batterijspanning
- 1306 OLED voor dataweergave
- Buzzer voor alarm piep
- RGB LED niet nodig voor dit project
- XBee-interface niet gebruikt, maar Arduino D2, D3, D9, D10 kunnen hieruit gehaald worden voor andere projecten; D2 is verbonden met reset, wat resetten vanuit code toestaat!
- 5-way joystick niet gebruikt
- 101 potmeter niet gebruikt
Stap 2: Hardware modificeren & aanpassen
Enkele aanpassingen zijn gemaakt aan de Arduino Uno. Deze wordt op een 4xAA batterijhouder gemonteerd met schroefstand-offs en lijm.


4 AA en CR1220 (voor RTC) worden in de batterijhouders geplaatst.


Er is ruimte tussen de batterijhouder en de Arduino Uno waar de druk-, vochtigheids-, magnetische en GPS-sensor geplaatst kunnen worden.


I2C-sensoren zijn samen gesoldeerd op een stukje printplaat en in deze ruimte geplaatst.


Deze sensoren zijn vanaf de onderkant met de Arduino verbonden.

Een spanningsdeler is toegevoegd om de batterijspanning van de 4 AA-batterijen te meten.

De AA-batterijpakket meetlijn gaat naar ADC A1.

De joystick van de shield is gemapt op de ADC-pin A1 via pin A5. Daarom is de joystick gedesoldeerd en verwijderd.

Door sommige pads op de Accessory Shield (zie referentie voor schema) met soldeerbruggen te verbinden, worden D2 (voor soft reset), D3, D9, D10 pinnen van de Arduino beschikbaar op de XBee-interface.


De componenten stapelen zich als volgt:
- Bovenlaag: Accessory Shield op Arduino
- Middenlaag: Overige sensoren en GPS tussen Uno en batterijhouder
- Onderlaag: 4xAA Batterijhouder met batterijen

De verbindingen zien er zo uit:

Stap 3: Het apparaat programmeren
Arduino IDE Build 1.8.5 wordt gebruikt om het apparaat te programmeren. Eerst worden alle volgende bibliotheken toegevoegd of gedownload via de bibliotheekbeheerder.

Door de naam van de sensor in het zoekvak van de bibliotheekbeheerder te typen, verschijnen de geschikte bibliotheken.

Sommige Accessory Shield-bibliotheken (zie referentie) worden toegevoegd via de zip-bestandsoptie.

Na het toevoegen van de benodigde bibliotheken, worden de voorbeeldcodes voor elke sensor bekeken om de API's te vinden.
Vervolgens worden alle bibliotheekheaders in één lege Arduino-sketch opgenomen.
Lijst met header-bestanden
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
Na meerdere bewerkingen, compileren en debuggen (inclusief losse verbindingen, waarbij ik ontdekte dat de BMP180 werkt zonder Vcc door lekkage via I2C-pins) en uploaden, was de code klaar.
De voorbehouden
- Hoogteberekening is gebaseerd op luchtdrukdaling, alleen toepasbaar bij normale weersomstandigheden.

- Kompascode is niet softwarematig hellinggecompenseerd; het apparaat moet in een vlakke vlak gehouden worden. Er is een vaste kompas-cirkel, waarin een variabele straalcirkel zit. Wanneer het apparaat gekanteld is, neemt de binnenste cirkel toe. Wanneer het in een vlakke positie is (d.w.z. zowel x- als y-component van de versnellingsmeter bijna 0), krimpt de binnenste cirkel tot een punt. Dit is het moment dat de kompasrichting nauwkeuriger is.
- Kompaswijzer declinatiehoek hangt af van locatie en variatie van het aardmagnetische veld. Dit kan beïnvloed worden door zonnestormen. Als de declinatiehoek niet meegerekend wordt, zal de kompasrichting enkele graden afwijken.
Vind declinatie voor jouw gebied: https://www.magnetic-declination.com - Kompasrichting is gevoelig voor nabijgelegen magnetische objecten, zoals sterke magnetische mineralen in bergen.
- Minimale werkspanning van het apparaat is ongeveer 4,5 volt. Dit is het moment dat de AA-batterijen vervangen moeten worden.
- Tijd en datum worden vanuit code geprogrammeerd. Als de tijd gewijzigd moet worden, moet de knopcelbatterij uitgehaald en weer ingeplugd worden. Een verse upload met nieuwe tijd in de code wijzigt de tijd.
- Tijdens ontwikkeling was de GPS-module niet beschikbaar. Daarom zijn democoördinaten in Lat-Long geplaatst. Als iemand dit project wil repliceren, is het vereist om de GPS-bibliotheek en bijbehorende code op te nemen.
- XY-vlak van versnellingsmeter en magnetometer zijn onderhevig aan plaatsing op PCB. Code moet dienovereenkomstig aangepast worden.
- Versnellingsmeter leesnauwkeurigheid is gevoelig voor trillingen. Het wordt geadviseerd om het apparaat in rust te gebruiken.
Verbetermogelijkheden
Verbeteringen kunnen vanuit de firmware voor extra features:
- Periodieke logging van parameters op EEPROM
- Buzzer alarm piep bij bereiken hoogte/locatie mijlpaal
- Drink water herinnering
- Pauze herinnering
- Lage batterij alarm
- Lage temperatuur, vochtigheid alert
- Kompas software kalibratie voor hellingcompensatie (veel trigonometrie)
- Automatisch declinatie ophalen via GPS en IoT-connectiviteit via Gateway-app
Wat de hardwareverbeteringen betreft:
- Gebruikersinvoerschakelaars voor tijd, declinatie, etc. instellen
- Custom 3D-print behuizing
- Herlaadbare LiPo-batterij gebruiken
- Enkelvoudig compact PCB-ontwerp voor meer draagbaarheid
Conclusie
Reizen en wandelen is cool, en als je de verandering in de omgeving kunt checken, wordt het nog interessanter. Vooral de hoogte, vochtigheid, druk en temperatuurveranderingen binnen uren tijdens het wandelen controleren. Dit apparaat laat je weten op welke hoogte je hoogteziekte krijgt, welk vochtigheidsniveau je huid droog maakt – zaken als die. Hoewel er ruimte is voor verbetering in zowel schakelayout als code om de voorbehouden aan te pakken, is het nog steeds cool om een gadget als deze te hebben tijdens het trekken in de wildernis!
Externe bronnen
https://www.waveshare.com/wiki/Accessory_Shield
Aanbevolen hardware voor een betere versie van dit project
Rapid Prototyping Kit
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 Variabelen ///////////////////
uint8_t time[8];
struct ts t;
int s, m, h, dy, mo, yr;
///////////////// Versnellingsmeter Variabelen /////////////
float X=0.0, Y=0.0, Z=0.0, Gravity = 0.0;
///////////////// Magnetometer Variabelen /////////////////
float Xm=0.0, Ym=0.0, Zm=0.0;
////////////////////// RGB LED Variabelen /////////////////
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;
///////////////////// Vochtigheid ///////////////////////
float humid = 0.0;
//////////////////// Luchtdruk ////////////////////////
double prsr = 0.0;
//////////////////// Hoogte ////////////////////////
float alt = 0.0;
//////////////// Lat, Long ////////////////////
float lat = 0.0, lon = 0.0;
//////////////// Kompas Hoek //////////////////
float heading = 0.0;
/////////////////// Overige Variabelen ////////////////
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); // I2C OLED Display
TempI2C_LM75 termo = TempI2C_LM75(0x48, TempI2C_LM75::nine_bits); // I2C Temp Sensor
ADXL345 accelerometer; // I2C Versnellingsmeter
ChainableLED leds(clk_pin, data_pin, rgb_pwr, 1); // I2C RGB LED
Adafruit_AM2320 am2320 = Adafruit_AM2320(); // I2C Vochtigheidssensor
Adafruit_BMP085_Unified bmp180 = Adafruit_BMP085_Unified(10085); // I2C Druksensor
Adafruit_HMC5883_Unified mag = Adafruit_HMC5883_Unified(12345); // I2C Kompas
// Uncomment de volgende 2 regels om GPS in te schakelen
// Serial Debugging niet beschikbaar
// HardwareSerial mySerial = Serial;
// Adafruit_GPS GPS(&mySerial);
void setup(void) {
// 1.1V Interne Analog Referentie
// analogReference(INTERNAL);
/////////// Signalen voor OLED op Accessory Shield ///////////
// Soldeerbruggen op shield nodig voor D2,D3,D9,D10
pinMode(2, OUTPUT); // self reset D2 naar RST
pinMode(3, OUTPUT); // uitgang op xbee int 12
pinMode(9, OUTPUT); // uitgang op xbee int 13
pinMode(10, OUTPUT); // uitgang op 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 op A0
// Vin Batt/Supply op A1 (3.91k/21.76k)
/////////// Seriële Communicatie voor Debuggen (optioneel) ///////////
// Serial.begin(9600);
////////////// Versnellingsmeter Init Wachten ///////////
if (!accelerometer.begin()) { delay(50); }
/////////////// RTC Interrupt Inschakelen ///////////
DS3231_init(DS3231_INTCN);
//////////////// Buzzer Init ////////////////////
pinMode(11, OUTPUT);
digitalWrite(11, LOW);
}
void loop(void) {
// Picture loop
u8g.firstPage();
do { draw(); } while (u8g.nextPage());
// Schakel tussen I2C sensoren
sensor_selector++;
if (sensor_selector >= 3) sensor_selector = 0;
////// Temperatuur Ophalen API //////
temp = termo.getTemp();
delay(5);
/////// Druk Ophalen API /////////
if (sensor_selector == 0) {
///////////// Druksensor Init ///////////
if (!bmp180.begin()) delay(11);
sensors_event_t event;
bmp180.getEvent(&event);
if (event.pressure) {
prsr = event.pressure / 10; // hPa naar kPa
delay(50);
}
}
////////////// GPS Init //////////
// GPS.begin(9600);
/////// Hoogte Ophalen API ////////
if (sensor_selector == 0) {
sensors_event_t event;
bmp180.getEvent(&event);
alt = bmp180.pressureToAltitude(1013.25, event.pressure);
delay(50);
} // in meter
////////////// Vochtigheidssensor Init ///////
if (sensor_selector == 1) {
am2320.begin();
delay(50);
////// Vochtigheid Ophalen API /////////
humid = am2320.readHumidity();
delay(50);
} // in % RH
////// Versnelling Ophalen 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
///// Tijd Ophalen API ////////
DS3231_get(&t);
s = t.sec; m = t.min; h = t.hour;
dy = t.mday; mo = t.mon; yr = t.year;
///// Pot Positie Ophalen ///////
pot = analogRead(A0) * 5 / (10 * 3);
delay(2);
///// VBatt/Supply Ophalen ///////
// 1.1 is 1.08 voor deze chip
Vbatt = (1.08 * analogRead(A1) / 1023) / 3.91 * ((3.91 + 21.76));
delay(2);
///////// Kompas Hoek //////////
if (sensor_selector == 2) {
if (!mag.begin()) { while(1); }
delay(70);
sensor_t sensor2;
mag.getSensor(&sensor2);
delay(70);
// Declinatiehoek hangt af van geografische locatie
// Gebruik Lat Long van GPS om te berekenen
sensors_event_t event2;
mag.getEvent(&event2);
delay(70);
float declination = 0.0;
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);
///////////////////////////////////
}
//////////////////// 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.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
int r = round(sqrt(X*X + Y*Y));
u8g.drawStr(0, 22, "heading");
u8g.drawCircle(18, 34, r, U8G_DRAW_ALL); // Binnenste hellingscirkel
u8g.drawCircle(18, 34, 10, U8G_DRAW_ALL); // Buitenste vaste cirkel
// Binnenste cirkel wordt een punt bij geen helling in x en y as
// Dit is wanneer de kompasrichting nauwkeuriger is
u8g.setPrintPos(0, 53); u8g.print(heading);
// 0 of 360 = N, 90 = O, 180 = Z, 270 = W
if ((heading > 315) || (heading <= 45)) u8g.drawLine(18, 34, 8, 34); // N
if ((heading > 45) && (heading <= 135)) u8g.drawLine(18, 34, 18, 24); // O
if ((heading > 135) && (heading <= 225)) u8g.drawLine(18, 34, 28, 34); // Z
if ((heading > 225) && (heading < 315)) u8g.drawLine(18, 34, 18, 44); // W
}
Bibliotheken
Uitpakken en de individuele bibliotheek-zips toevoegen aan Arduino Library Manager.
Schema's
Productieproces
- Een LED Besturen met een PIR-bewegingssensor op Raspberry Pi
- Een Goedkope Raspberry Pi Grondvochtigheidssensor Bouwen voor Slimme Irrigatie
- Uw Hamster's Dagelijkse Oefening Volgen met een Raspberry Pi Fitness Tracker
- De DS18B20 Temperatuursensor Testen op Raspberry Pi
- Een Raspberry Pi thuistemperatuurmonitor bouwen met MCP9808, InfluxDB & Grafana
- Walabot-aangedreven toilet-hygiënemonitor
- Emotiesensor & EEG: Goedkope Hardware voor Real-time Emotiedetectie
- Adafruit 10DOF IMU-data van Raspberry Pi 2 naar Azure Event Hubs Sturen met Windows 10 IoT Core
- UnifiedWater v1 – Complete Arduino Waterkwaliteit Sensor Kit
- De zuurstofsensor (O2) begrijpen: functie, plaatsing en defectherkenning
- Accurate WiFi RSSI Tracking Voor ISS Sensoren