Registrador de Dados GPS Avançado: Rastreamento de Voo em Tempo Real, Monitoramento de Altitude e Velocidade Máximas
Componentes e Materiais
| Componente | Quantidade |
|---|---|
| Arduino UNO | 1 |
| Jumpers (Barramento), Conjunto de Jumpers | 1 |
| Shield Proto para Arduino | 1 |
| Tela LCD TFT SPI 1.8" com Socket MicroSD | 1 |
| Módulo GPS u-blox NEO-6M | 1 |
Ferramentas Necessárias
- Ferro de Solda (genérico)
- Solda Sem Chumbo
- Alicate Descascador e Cortador de Fios (18-10 AWG / 0.75-4mm²)
Sobre o Projeto
Introdução
Pratico aeromodelismo e gosto de saber a velocidade e altitude dos meus aviões. Infelizmente, registradores de dados GPS comerciais são muito caros.
Decidi construir meu próprio registrador de dados GPS baseado em Arduino por um custo inferior a 50€.
Meu primeiro protótipo utiliza um Arduino Uno R3 com uma tela ST7735 da Sainsmart (com slot para cartão SD integrado) e um módulo GPS NEO 6M V2.
No segundo projeto, pretendo usar um Arduino Nano com tela OLED SSD1306, o mesmo módulo GPS e um cartão micro SD. O peso total com caixa deve ser de cerca de 40 gramas, podendo ser facilmente integrado em uma aeronave de médio porte (dimensões: 50mm x 30mm x 22mm). Este será meu próximo projeto (estou aguardando os materiais).
Testes
Não é fácil filmar a tela do Arduino dentro de um carro, mas consegui e o resultado pode ser visto no vídeo.
O próximo teste será com o novo protótipo menor e mais leve em uma aeronave radiocontrolada. Continuará!
Código
Registrador de Dados GPS (sem SD)
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#define cs 10
#define dc 9
#define rst 8
#include <TinyGPS++.h>
#include <SoftwareSerial.h>
Adafruit_ST7735 tft = Adafruit_ST7735(cs, dc, rst);
static const int RXPin = 4, TXPin = 3;
static const uint32_t GPSBaud = 9600;
#define OLED_RESET 5
TinyGPSPlus gps;
SoftwareSerial ss(RXPin, TXPin);
int x = 80;
int xh = 80;
int maxhigh = 0;
int maxspeed = 0, speed1 = 0;
int high1 = 0;
void setup() {
Serial.begin(9600);
ss.begin(GPSBaud);
tft.initR(INITR_GREENTAB);
tft.fillScreen(ST7735_BLACK);
tft.setCursor(5, 58);
tft.setTextSize(1);
tft.setTextColor(ST7735_GREEN, ST7735_BLACK);
tft.print("inicializacao");
}
void loop() {
tft.setTextSize(1);
tft.setTextColor(ST7735_GREEN, ST7735_BLACK);
while (ss.available() > 0) {
gps.encode(ss.read());
if (gps.location.isUpdated()) {
desenhaMoldura();
// Latitude
tft.setCursor(5, 44);
tft.setTextColor(ST7735_GREEN, ST7735_BLACK);
tft.print("Latitude: ");
tft.setTextColor(ST7735_CYAN, ST7735_BLACK);
tft.print(gps.location.lat(), 6);
// Longitude
tft.setCursor(5, 58);
tft.setTextColor(ST7735_GREEN, ST7735_BLACK);
tft.print("Longitude: ");
tft.setTextColor(ST7735_CYAN, ST7735_BLACK);
tft.print(gps.location.lng(), 6);
// Data
tft.setCursor(5, 7);
tft.setTextColor(ST7735_GREEN, ST7735_BLACK);
tft.print("data: ");
tft.setTextColor(ST7735_CYAN, ST7735_BLACK);
tft.print(gps.date.day()); tft.print(" ");
tft.print(gps.date.month()); tft.print(" ");
tft.print(gps.date.year());
// Hora
tft.setCursor(5, 20);
tft.setTextColor(ST7735_GREEN, ST7735_BLACK);
tft.print("hora: ");
tft.setTextColor(ST7735_CYAN, ST7735_BLACK);
tft.print(gps.time.hour() + 1); tft.print(" ");
tft.print(gps.time.minute()); tft.print(" ");
tft.print(gps.time.second()); tft.print(" ");
// Altitude atual
tft.setCursor(5, 80);
tft.setTextColor(ST7735_GREEN, ST7735_BLACK);
tft.print("H m: ");
tft.setTextColor(ST7735_CYAN, ST7735_BLACK);
tft.print(gps.altitude.meters(), 0); tft.print(" ");
// Altitude máxima
tft.setCursor(5, 95);
tft.setTextColor(ST7735_GREEN, ST7735_BLACK);
atualizaAltitudeMaxima();
tft.print("Hmax: ");
tft.setTextColor(ST7735_CYAN, ST7735_BLACK);
tft.print(maxhigh); tft.print(" ");
desenhaGraficoAltitude();
// Velocidade atual
tft.setCursor(5, 115);
tft.setTextColor(ST7735_GREEN, ST7735_BLACK);
tft.print("V act: ");
tft.setTextColor(ST7735_CYAN, ST7735_BLACK);
tft.print(gps.speed.kmph(), 0); tft.print(" ");
// Velocidade máxima
tft.setCursor(5, 130);
tft.setTextColor(ST7735_GREEN, ST7735_BLACK);
atualizaVelocidadeMaxima();
tft.print("vmax: ");
tft.setTextColor(ST7735_CYAN, ST7735_BLACK);
tft.print(maxspeed); tft.print(" ");
desenhaGraficoVelocidade();
// Satélites
tft.setCursor(5, 147);
tft.setTextColor(ST7735_GREEN, ST7735_BLACK);
tft.print("num Sat: ");
tft.setTextColor(ST7735_CYAN, ST7735_BLACK);
tft.print(gps.satellites.value()); tft.print(" ");
// HDOP
Serial.print("HDOP = "); Serial.println(gps.hdop.value());
smartDelay(400);
}
}
}
static void smartDelay(unsigned long ms) {
unsigned long start = millis();
do {
while (ss.available()) gps.encode(ss.read());
} while (millis() - start < ms);
}
void desenhaMoldura() {
// Desenha linhas da moldura na tela
tft.drawLine(0, 0, 130, 0, ST7735_RED);
tft.drawLine(0, 1, 130, 1, ST7735_RED);
tft.drawLine(0, 158, 130, 158, ST7735_RED);
tft.drawLine(0, 142, 130, 142, ST7735_RED);
tft.drawLine(0, 141, 130, 141, ST7735_RED);
tft.drawLine(0, 107, 130, 107, ST7735_RED);
tft.drawLine(0, 108, 130, 108, ST7735_RED);
tft.drawLine(80, 108, 80, 140, ST7735_RED);
tft.drawLine(81, 109, 81, 140, ST7735_RED);
tft.drawLine(80, 70, 80, 108, ST7735_RED);
tft.drawLine(81, 70, 81, 108, ST7735_RED);
tft.drawLine(0, 159, 130, 159, ST7735_RED);
tft.drawLine(0, 0, 0, 156, ST7735_RED);
tft.drawLine(1, 1, 1, 157, ST7735_RED);
tft.drawLine(127, 0, 127, 156, ST7735_RED);
tft.drawLine(126, 0, 126, 156, ST7735_RED);
tft.drawLine(0, 35, 130, 35, ST7735_RED);
tft.drawLine(0, 36, 130, 36, ST7735_RED);
tft.drawLine(0, 70, 130, 70, ST7735_RED);
tft.drawLine(0, 71, 130, 71, ST7735_RED);
}
void desenhaGraficoVelocidade() {
int novaValor = map(gps.speed.kmph(), 0, 150, 137, 110);
x++;
tft.drawPixel(x, novaValor, ST7735_CYAN);
if (x > 123) {
x = 80;
tft.fillRect(82, 110, 43, 30, ST7735_BLACK);
}
}
void desenhaGraficoAltitude() {
int novaValorh = map(gps.altitude.meters(), 0, 1000, 104, 72);
xh++;
tft.drawPixel(xh, novaValorh, ST7735_CYAN);
if (xh > 123) {
xh = 80;
tft.fillRect(82, 72, 43, 35, ST7735_BLACK);
}
}
void atualizaVelocidadeMaxima() {
speed1 = gps.speed.kmph();
if (speed1 > maxspeed) maxspeed = speed1;
}
void atualizaAltitudeMaxima() {
high1 = gps.altitude.meters();
if (high1 > maxhigh) maxhigh = high1;
}
Registrador de Dados GPS com Salvamento em SD
#include <SPI.h>
#include <SD.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#define cs 10
#define dc 9
#define rst 8
#include <TinyGPS++.h>
#include <SoftwareSerial.h>
Adafruit_ST7735 tft = Adafruit_ST7735(cs, dc, rst);
static const int RXPin = 4, TXPin = 3;
static const uint32_t GPSBaud = 9600;
const int cs_sd = 4;
#define OLED_RESET 5
TinyGPSPlus gps;
SoftwareSerial ss(RXPin, TXPin);
int x = 80, xh = 80;
int maxhigh = 0, maxspeed = 0, speed1 = 0, high1 = 0;
void setup() {
Serial.begin(9600);
ss.begin(GPSBaud);
tft.initR(INITR_GREENTAB);
tft.fillScreen(ST7735_BLACK);
tft.setCursor(5, 58);
tft.setTextSize(1);
tft.setTextColor(ST7735_GREEN, ST7735_BLACK);
tft.print("inicializacao");
tft.setCursor(5, 70);
tft.print("init SD");
delay(1000);
if (!SD.begin(cs_sd)) {
tft.setCursor(5, 82);
tft.print("Falha SD");
return;
}
tft.setCursor(5, 82);
tft.print("Cartao SD OK");
delay(1000);
tft.fillScreen(ST7735_BLACK);
File data = SD.open("dados.txt", FILE_WRITE);
data.println("");
data.println("Inicio aquisicao");
data.close();
}
void loop() {
tft.setTextSize(1);
tft.setTextColor(ST7735_GREEN, ST7735_BLACK);
while (ss.available() > 0) {
gps.encode(ss.read());
if (gps.location.isUpdated()) {
desenhaMoldura();
// ... (mesma exibição da versão anterior) ...
// Escrita no cartão SD
String Data = String(gps.date.day()) + " " + gps.date.month() + " " + gps.date.year();
String Tempo = String(gps.time.hour() + 1) + " " + gps.time.minute() + " " + gps.time.second();
File data = SD.open("dados.txt", FILE_WRITE);
data.println(Data + " " + Tempo + " " + String(gps.location.lat(), 6) + " " +
String(gps.location.lng(), 6) + " " + String(gps.altitude.meters(), 0) + " " +
String(maxhigh) + " " + String(gps.speed.kmph(), 0) + " " + String(maxspeed));
data.close();
smartDelay(400);
}
}
}
// Funções auxiliares (desenhaMoldura, desenhaGraficoVelocidade, desenhaGraficoAltitude,
// atualizaVelocidadeMaxima, atualizaAltitudeMaxima, smartDelay) são idênticas à versão anterior.
Esquemático
Consulte a imagem do esquemático de conexão (não incluída neste texto).
Processo de manufatura
- Construa um Sistema Rápido e Confiável de Detecção de Incêndio com Samsung SAMI, Arduino UNO e Raspberry Pi
- Monitoramento em Tempo Real de Painel Solar com Arduino: Sistema de Aquisição de Dados de Baixo Custo
- Monitore e Registre Energia com Arduino – Guia Passo a Passo (Dr. Wattson)
- Crie Animações e Jogos Envolventes em LCD com Arduino UNO
- Registrador de Temperatura e Umidade com Arduino, DHT11 e Ethernet Shield
- Construa uma Calculadora Básica com Arduino UNO – Projeto Fácil
- Display Portátil de Persistência da Visão com Arduino UNO e ATtiny85
- Módulo GPS u-blox LEA‑6H 02: Guia de Integração com Arduino e Python
- Construa um Cubo de LED 4x4x4 com Arduino Uno e 1Sheeld – Projeto Interativo de LED
- Python 3 para Arduino UNO: Controle de Comandos Fácil e Demo com LED