Rastreador de Trilha Avançado com Arduino: GPS, Sensores e Bateria
Componentes e Materiais
- 1x Arduino 101
- 1x Suporte para 4 pilhas AA + pilhas AA
- 1x Accessory Shield (Waveshare)
- 1x Sensor de pressão BMP180 (Adafruit)
- 1x GPS Ultimate Breakout (Adafruit MTK3339)
- 1x Sensor magnético 3 eixos (Adafruit HMC5883)
- 1x Sensor de umidade AM2320 (Adafruit)
- 2x Bateria de moeda CR2012 (para RTC)
- Resistores: 1x 10k Ω, 1x 3.9k Ω
Ferramentas Necessárias
- Pistola de cola quente
- Ferro de solda
Software
- Arduino IDE 1.8.5
Sobre o Projeto
O Que é o Hiking Tracker?
O Hiking Tracker é um dispositivo para detectar mudanças no ambiente ao redor do caminhante durante a trilha. A ideia é observar variações de temperatura, pressão, umidade, altitude, localização, direção etc., fornecendo insights interessantes sobre a caminhada.
Em montanhas, onde o ar é frio, seco e rarefeito, muitas pessoas sentem dificuldade para respirar ou irritação na pele seca. Este dispositivo permite que entusiastas conheçam seus limites. Também é divertido saber a altitude atingida!
Não só montanhas: explorando pântanos, desertos, florestas — cada um com perfil ambiental único — monitorar o ambiente em tempo real é uma forma melhor de entender a natureza.

Passo 1: Hardware – Para Que Serve Cada Item
O Accessory Shield já traz vários dispositivos I2C a bordo:
- LM75B – sensor de temperatura ambiente
- ADXL345 – acelerômetro 3 eixos (inclinação/gravidade)
- DS3231 – RTC de alta precisão (hora/data)
- HMC5883 – magnetômetro 3 eixos (bússola)
- AM2320 – sensor de umidade relativa
- BMP180 – sensor de pressão atmosférica e altitude
- MTK3339 GPS – localização e distância percorrida
No Arduino Uno (via shield):
- Divisor de tensão 3.9k + 22k → leitura da tensão das 4 pilhas AA
- Display OLED 1306 para visualização
- Buzzer para alarme
- LED RGB (não usado neste projeto)
- Interface XBee (não usada, mas pinos D2, D3, D9, D10 disponíveis; D2 conectado a reset, permitindo reset por software)
- Joystick 5 vias e potenciômetro 10k (não usados)
Passo 2: Modificando e Conectando o Hardware
O Arduino Uno é montado sobre o suporte de 4 pilhas AA com espaçadores e cola quente.


Pilhas AA e CR1220 (RTC) instaladas.


Há um espaço entre o suporte de pilhas e o Arduino onde cabem os sensores de pressão, umidade, magnético e GPS.


Sensores I2C soldados juntos em uma placa de perfuração e colocados nesse espaço.


Sensores conectados ao Arduino pelo lado inferior.

Divisor de tensão para medir voltagem das 4 pilhas AA.

Linha de leitura da bateria vai para ADC A1.

O joystick do shield usa o pino A5, por isso foi dessoldado e removido.

Ponte de solda no shield libera pinos D2 (soft reset), D3, D9, D10 na interface XBee.


Empilhamento final:
- Camada superior: Accessory Shield no Arduino
- Camada intermediária: Sensores extras e GPS entre Uno e suporte de pilhas
- Camada inferior: Suporte 4×AA com pilhas

Passo 3: Programando o Dispositivo
Usado Arduino IDE 1.8.5. Bibliotecas incluídas ou instaladas via Gerenciador de Bibliotecas.

Buscando pelo nome do sensor no gerenciador, as bibliotecas aparecem.

Bibliotecas do Accessory Shield (ver referências) adicionadas via .zip.

Após adicionar, exemplos de cada sensor foram revisados para obter as APIs. Todos os headers incluídos em um sketch vazio.
Lista de Headers
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
Após múltiplas edições, compilações, depuração (incluindo conexão solta onde descobri que o BMP180 funciona sem Vcc por vazamento nos pinos I2C) e upload, o código ficou pronto.
Ressalvas (Caveats)
- Cálculo de altitude baseado em queda de pressão — válido apenas em condições climáticas normais.
- Código da bússola não tem compensação de inclinação — dispositivo deve ser mantido nivelado. Há um círculo fixo e outro variável; quando inclinado, o círculo interno aumenta. Quando nivelado (componentes X e Y do acelerômetro ~0), o círculo interno reduz a um ponto — momento em que o heading é mais preciso.
- Declinação magnética depende da localização e varia com o campo terrestre (tempestades solares). Se não incluída, a bússola erra alguns graus. Calcule a declinação para sua área.
- Heading suscetível a objetos magnéticos próximos (minerais em montanhas).
- Tensão mínima de operação ~4,5 V — trocar pilhas AA abaixo disso.
- Hora/data programadas no código; para alterar, deve remover e recolocar a bateria de moeda e fazer novo upload com hora atualizada.
- Durante desenvolvimento, módulo GPS não estava disponível; coordenadas demo fixadas no código. Para replicar, inclua biblioteca GPS e códigos associados.
- Plano XY do acelerômetro e magnetômetro depende da colocação na PCB; código precisa de ajuste.
- Leitura do acelerômetro sensível a vibrações — use o dispositivo parado.
Escopo de Melhorias
Firmware:
- Log periódico de parâmetros na EEPROM
- Alerta sonoro ao atingir marcos de altitude/localização
- Lembrete de beber água / fazer pausa
- Alarme de bateria baixa
- Alerta de temperatura/umidade baixa
- Calibração de software da bússola para compensação de inclinação (trigonometria)
- Busca automática de declinação via GPS e IoT através de app gateway
Hardware:
- Chaves de entrada do usuário para ajustar hora, declinação etc.
- Caixa personalizada impressa em 3D
- Bateria LiPo recarregável
- PCB compacto de placa única para maior portabilidade
Conclusão
Caminhadas e trilhas são legais, mas quando você pode conferir as mudanças no ambiente, fica mais interessante. Especialmente ver altitude, umidade, pressão e temperatura mudando em poucas horas. Este dispositivo mostra em que altura você sente mal de altitude, qual umidade resseca a pele, etc. Embora haja espaço para melhorias no layout e código, ainda é legal ter um gadget assim na natureza!
Recursos Externos
Waveshare Accessory Shield Wiki
Hardware Recomendado para Versão Melhorada
Kit de Prototipagem Rápida
Código
Hiking_Tracker.ino (C/C++)
/*/////////// NOTE ///////////
D2 permite soft reset via código
D3,D9,D10 disponíveis via interface XBee (pinos 12,13,16)
D4, D13 não acessíveis
/////////////////////////////*/
//// HEADER FILES /////
#include <math.h>
#include <inttypes.h>
#include <Wire.h>
#include <lm75.h>
#include <ADXL345.h>
#include <ChainableLED.h>
#include "U8glib.h"
#include "ds3231.h"
#include "Adafruit_Sensor.h"
#include "Adafruit_AM2320.h"
#include <Adafruit_BMP085_U.h>
#include <Adafruit_HMC5883_U.h>
#include <Adafruit_GPS.h>
/////////////////////// Variáveis RTC ///////////////////
uint8_t time[8];
struct ts t;
int s, m, h, dy, mo, yr;
///////////////// Variáveis Acelerômetro ///////////////
float X=0.0, Y=0.0, Z=0.0, Gravity=0.0;
///////////////// Variáveis Magnetômetro ///////////////
float Xm=0.0, Ym=0.0, Zm=0.0;
////////////////////// Variáveis LED RGB ///////////////
const int rgb_pwr = 12;
const int clk_pin = 6;
const int data_pin = 5;
float hue = 0.0;
boolean up = true;
////////////////////// Potenciômetro ///////////////////
int pot = 0;
////////////////////// Bateria/Alimentação ////////////
float Vbatt = 0.0;
////////////////////// Termômetro /////////////////////
float temp = 0.0;
////////////////////// Umidade ////////////////////////
float humid = 0.0;
////////////////////// Pressão ////////////////////////
double prsr = 0.0;
////////////////////// Altitude ///////////////////////
float alt = 0.0;
////////////////////// Lat, Long //////////////////////
float lat = 0.0, lon = 0.0;
////////////////////// Bússola ////////////////////////
float heading = 0.0;
////////////////////// Outras /////////////////////////
int mstime = 0;
int sensor_selector = 1;
//////////// ENUM / Objetos I2C ///////////////
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE | U8G_I2C_OPT_DEV_0); // OLED I2C
TempI2C_LM75 termo = TempI2C_LM75(0x48, TempI2C_LM75::nine_bits); // Temp I2C
ADXL345 accelerometer; // Acel I2C
ChainableLED leds(clk_pin, data_pin, rgb_pwr, 1); // RGB LED
Adafruit_AM2320 am2320 = Adafruit_AM2320(); // Umidade I2C
Adafruit_BMP085_Unified bmp180 = Adafruit_BMP085_Unified(10085); // Pressão I2C
Adafruit_HMC5883_Unified mag = Adafruit_HMC5883_Unified(12345); // Bússola I2C
// Descomente para habilitar GPS (Serial debugging não estará disponível)
// HardwareSerial mySerial = Serial;
// Adafruit_GPS GPS(&mySerial);
void setup(void) {
// Referência analógica interna 1.1V
// analogReference(INTERNAL);
///// Sinais para OLED no Accessory Shield /////
// Ponte de solda no shield necessária para D2,D3,D9,D10
pinMode(2, OUTPUT); // self reset D2 -> RST
pinMode(3, OUTPUT); // saída no XBee int 12
pinMode(9, OUTPUT); // saída no XBee int 13
pinMode(10, OUTPUT); // saída no 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 no A0
// Vin Bateria no A1 (divisor 3.91k/21.76k)
///// Serial para Debug (opcional) /////
// Serial.begin(9600);
///// Init Acelerômetro /////
if (!accelerometer.begin()) delay(50);
///// RTC Interrupt Enable /////
DS3231_init(DS3231_INTCN);
///// Buzzer Init /////
pinMode(11, OUTPUT);
digitalWrite(11, LOW);
}
void loop(void) {
// Picture loop para OLED
u8g.firstPage();
do { draw(); } while (u8g.nextPage());
// Alterna entre sensores I2C
sensor_selector++;
if (sensor_selector >= 3) sensor_selector = 0;
///// Temperatura /////
temp = termo.getTemp();
delay(5);
///// Pressão /////
if (sensor_selector == 0) {
if (!bmp180.begin()) delay(11);
sensors_event_t event;
bmp180.getEvent(&event);
if (event.pressure) {
prsr = event.pressure / 10; // hPa para kPa
delay(50);
}
}
///// GPS Init /////
// GPS.begin(9600);
///// Altitude /////
if (sensor_selector == 0) {
sensors_event_t event;
bmp180.getEvent(&event);
alt = bmp180.pressureToAltitude(1013.25, event.pressure);
delay(50);
}
///// Umidade /////
if (sensor_selector == 1) {
am2320.begin();
delay(50);
humid = am2320.readHumidity();
delay(50);
}
///// Aceleração /////
Vector norm = accelerometer.readNormalize();
X = norm.XAxis; Y = norm.YAxis; Z = norm.ZAxis;
Gravity = sqrt(X*X + Y*Y + Z*Z) - 0.3; // offset
///// Tempo (RTC) /////
DS3231_get(&t);
s = t.sec; m = t.min; h = t.hour;
dy = t.mday; mo = t.mon; yr = t.year;
///// Potenciômetro /////
pot = analogRead(A0) * 5 / (10 * 3);
delay(2);
///// Tensão Bateria /////
// 1.1V é 1.08 neste chip
Vbatt = (1.08 * analogRead(A1) / 1023) / 3.91 * ((3.91 + 21.76));
delay(2);
///// Bússola /////
if (sensor_selector == 2) {
if (!mag.begin()) while(1);
delay(70);
sensor_t sensor2;
mag.getSensor(&sensor2);
delay(70);
// Declinação depende da localização (use GPS para calcular)
sensors_event_t event2;
mag.getEvent(&event2);
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; // graus
}
///// Buzzer /////
if (pot > 80) digitalWrite(11, HIGH); else digitalWrite(11, LOW);
///// LED RGB /////
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;
}
///// Auto Reset /////
// digitalWrite(2, LOW);
}
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.setPrintPos(40, 25); 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.setPrintPos(40, 25); 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); // círculo interno de nivelamento
u8g.drawCircle(18, 34, 10, U8G_DRAW_ALL); // círculo externo fixo
u8g.setPrintPos(0, 53); u8g.print(heading); // 0/360=N, 90=E, 180=S, 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); // 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
}
Bibliotecas
Descompacte e adicione os zips individuais ao Gerenciador de Bibliotecas do Arduino.
Esquemático

Processo de manufatura
- Entendendo o Sensor de Oxigênio (O2): Função, Localização e Sinais de Falha
- Controle um LED com Sensor de Movimento PIR no Raspberry Pi
- Construa um Sensor de Umidade do Solo de Baixo Custo para Irrigação Inteligente com Raspberry Pi
- Monitore o Exercício Diário do Seu Hamster com Rastreador de Fitness Raspberry Pi
- Testando o Sensor de Temperatura DS18B20 no Raspberry Pi
- Construa Monitor de Temperatura Doméstico com Raspberry Pi, MCP9808, InfluxDB e Grafana
- Monitor de Higiene de Vaso Sanitário com Walabot
- Sensor de Emoção & EEG: Hardware de Baixo Custo para Detecção de Emoções em Tempo Real
- Enviando Dados do IMU Adafruit 10DOF do Raspberry Pi 2 ao Azure Event Hubs com Windows 10 IoT Core
- Rastreamento Preciso de RSSI WiFi para Sensores na ISS