Fortgeschrittener GPS-Datenlogger: Echtzeit-Flugverfolgung, Höchsthöhe & Geschwindigkeitsüberwachung
Komponenten und Zubehör
| Komponente | Menge | Hinweise |
|---|---|---|
| Arduino UNO | 1 | Arduino Uno R3 |
| Jumper (Sammelschiene), Jumper-Kabel-Set | 1 | |
| Arduino Proto Shield | 1 | |
| 1,8" TFT SPI LCD-Bildschirm mit MicroSD-Sockel | 1 | oder ein anderer Bildschirm mit SD-Kartensteckplatz |
| u-blox GPS NEO-6M | 1 |
Benötigte Werkzeuge und Maschinen
- Lötkolben (Standard)
- Lötzinn, bleifrei
- Abisolierzange & Seitenschneider, 18-10 AWG / 0,75-4mm²
Über dieses Projekt
Einführung
Ich betreibe Flugmodellbau und möchte die Geschwindigkeit und Höhe meiner Flugzeuge kennen. Leider sind kommerzielle GPS-Datenlogger sehr teuer.
Deshalb entschied ich mich, einen GPS-Datenlogger auf Arduino-Basis für unter 50 € zu bauen.
Mein erster Prototyp basiert auf einem Arduino Uno R3 mit einem Sainsmart ST7735-Bildschirm mit integrierter SD-Karte und einem NEO-6M-V2-GPS-Modul.
Im zweiten Projekt möchte ich einen Arduino Nano mit einem SSD1306-OLED-Display, dem gleichen GPS-Modul und einer Micro-SD-Karte verwenden. Das Gewicht mit Gehäuse soll ca. 40 g betragen und sich leicht in ein mittelgroßes Flugzeug integrieren lassen (Größe ca. 50 mm × 30 mm × 22 mm). Dies wird mein nächstes Projekt (ich warte noch auf die Bauteile).
Test
Einen Arduino-Bildschirm im Auto zu filmen ist nicht einfach, aber ich habe es geschafft – das Ergebnis ist im Video zu sehen.
Der nächste Test erfolgt mit dem neuen, kleineren und leichteren Prototyp an einem ferngesteuerten Flugzeug. Fortsetzung folgt!
Code
GPS-Datenlogger (nur Anzeige)
#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; // GPS-Kommunikation
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("Initialisierung");
}
void loop() {
tft.setTextSize(1);
tft.setTextColor(ST7735_GREEN, ST7735_BLACK);
while (ss.available() > 0) {
gps.encode(ss.read());
if (gps.location.isUpdated()) {
drawFrame();
// Position
tft.setCursor(5, 44);
tft.setTextColor(ST7735_GREEN, ST7735_BLACK);
tft.print("Breite: ");
tft.setTextColor(ST7735_CYAN, ST7735_BLACK);
tft.print(gps.location.lat(), 6);
tft.setCursor(5, 58);
tft.setTextColor(ST7735_GREEN, ST7735_BLACK);
tft.print("Länge: ");
tft.setTextColor(ST7735_CYAN, ST7735_BLACK);
tft.print(gps.location.lng(), 6);
// Datum
tft.setCursor(5, 7);
tft.setTextColor(ST7735_GREEN, ST7735_BLACK);
tft.print("Datum: ");
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());
// Uhrzeit
tft.setCursor(5, 20);
tft.setTextColor(ST7735_GREEN, ST7735_BLACK);
tft.print("Uhrzeit: ");
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());
// Aktuelle Höhe
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(" ");
// Max. Höhe
tft.setCursor(5, 95);
updateMaxHeight();
tft.print("Hmax: ");
tft.setTextColor(ST7735_CYAN, ST7735_BLACK);
tft.print(maxhigh);
tft.print(" ");
drawHeightGraph();
// Aktuelle Geschwindigkeit
tft.setCursor(5, 115);
tft.setTextColor(ST7735_GREEN, ST7735_BLACK);
tft.print("V akt: ");
tft.setTextColor(ST7735_CYAN, ST7735_BLACK);
tft.print(gps.speed.kmph(), 0);
tft.print(" ");
// Max. Geschwindigkeit
tft.setCursor(5, 130);
tft.setTextColor(ST7735_GREEN, ST7735_BLACK);
updateMaxSpeed();
tft.print("Vmax: ");
tft.setTextColor(ST7735_CYAN, ST7735_BLACK);
tft.print(maxspeed);
tft.print(" ");
drawSpeedGraph();
// Satellitenanzahl
tft.setCursor(5, 147);
tft.setTextColor(ST7735_GREEN, ST7735_BLACK);
tft.print("Satelliten: ");
tft.setTextColor(ST7735_CYAN, ST7735_BLACK);
tft.print(gps.satellites.value());
// HDOP seriell ausgeben
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 drawFrame() {
// Rahmen zeichnen
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 drawSpeedGraph() {
int neueWert = map(gps.speed.kmph(), 0, 150, 137, 110);
x++;
tft.drawPixel(x, neueWert, ST7735_CYAN);
if (x > 123) {
x = 80;
tft.fillRect(82, 110, 43, 30, ST7735_BLACK);
}
}
void drawHeightGraph() {
int neueWertH = map(gps.altitude.meters(), 0, 1000, 104, 72);
xh++;
tft.drawPixel(xh, neueWertH, ST7735_CYAN);
if (xh > 123) {
xh = 80;
tft.fillRect(82, 72, 43, 35, ST7735_BLACK);
}
}
void updateMaxSpeed() {
speed1 = gps.speed.kmph();
if (speed1 > maxspeed) maxspeed = speed1;
}
void updateMaxHeight() {
high1 = gps.altitude.meters();
if (high1 > maxhigh) maxhigh = high1;
}
GPS-Datenlogger mit SD-Karten-Logging
#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("Initialisierung");
tft.setCursor(5, 70);
tft.print("SD init");
delay(1000);
if (!SD.begin(cs_sd)) {
tft.setCursor(5, 82);
tft.print("SD Fehler");
return;
}
tft.setCursor(5, 82);
tft.print("SD OK");
delay(1000);
tft.fillScreen(ST7735_BLACK);
File data = SD.open("daten.txt", FILE_WRITE);
data.println("");
data.println("Aufnahme gestartet");
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()) {
drawFrame();
// ... (Anzeigecode wie oben, identisch) ...
// Daten auf SD-Karte schreiben
String datum = String(gps.date.day()) + " " + gps.date.month() + " " + gps.date.year();
String zeit = String(gps.time.hour() + 1) + " " + gps.time.minute() + " " + gps.time.second();
File data = SD.open("daten.txt", FILE_WRITE);
data.println(datum + " " + zeit + " " +
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);
}
}
}
// Hilfsfunktionen (smartDelay, drawFrame, drawSpeedGraph, drawHeightGraph, updateMaxSpeed, updateMaxHeight)
// sind identisch mit der ersten Version.
Schaltplan

Herstellungsprozess
- Schnelles, zuverlässiges Branderkennungssystem mit Samsung SAMI, Arduino UNO & Raspberry Pi
- Echtzeit-Solarmonitoring mit Arduino: Low-Cost Datenerfassungssystem
- Arduino Energiemonitor & Datenlogger (Dr. Wattson, MCP39F521) – Schritt-für-Schritt
- LCD-Animationen & Spiele mit Arduino UNO erstellen
- Arduino Temperatur- & Feuchtelogger mit DHT11 & Ethernet Shield
- Einfacher Taschenrechner mit Arduino UNO – Einsteigerprojekt
- Tragbares Persistence-of-Vision-Display mit Arduino UNO und ATtiny85 bauen
- u-blox LEA-6H 02 GPS-Modul: Arduino & Python Integrationsanleitung
- 4x4x4 LED-Würfel mit Arduino Uno & 1Sheeld bauen – Interaktives LED-Projekt
- Python 3 zu Arduino UNO: Einfache Steuerung & LED-Demo