NEO-6M GPS-Modul am Arduino: Anschluss, NMEA und TinyGPSPlus
NEO-6M GPS-Modul am Arduino: TX/RX-Anschluss, Zeit bis zum ersten Fix, NMEA-Sätze $GPGGA und $GPRMC, TinyGPSPlus-Code, ESP32 mit OLED und Pico MicroPython.
Das NEO-6M GPS-Modul ist ein günstiger und sehr verbreiteter GPS-Empfänger, der deinem Arduino-, ESP32- oder Raspberry-Pi-Pico-Projekt Breitengrad, Längengrad, Geschwindigkeit, Höhe und die extrem genaue UTC-Zeit der Satelliten liefert. Für den Arduino reichen vier Leitungen (VCC, GND, TX, RX): Das Modul sendet einmal pro Sekunde mit 9600 Baud Textzeilen, die sogenannten NMEA-Sätze, und die Bibliothek TinyGPSPlus macht daraus Zahlen, mit denen du direkt arbeiten kannst.
In dieser Anleitung lernst du Schritt für Schritt, wie das Modul funktioniert, wie du es an Arduino Uno, ESP32 und Pico anschließt, warum der erste Fix manchmal Minuten dauert, was jedes Feld der Sätze $GPGGA und $GPRMC bedeutet, wie du aus Breiten- und Längengrad einen Google-Maps-Link erzeugst und wie du die Position auf einem OLED-Display anzeigst. Am Ende findest du eine Tabelle mit Ursachen und Lösungen für die häufigsten Probleme: "keine Daten" und "kein Fix".

Was ist das NEO-6M GPS-Modul und wie funktioniert es?
GPS (Global Positioning System) besteht aus mehr als 30 Satelliten, die in etwa 20.200 km Höhe die Erde umkreisen. Jeder Satellit sendet ständig die Zeit seiner Atomuhr und seine eigenen Bahndaten. Der NEO-6M misst die Differenz zwischen dem Moment, in dem ein Signal den Satelliten verlassen hat, und dem Moment, in dem es ankommt, und berechnet daraus die Entfernung zu jedem Satelliten; sieht er mindestens 4 Satelliten, bestimmt er Breitengrad, Längengrad, Höhe und den Fehler seiner eigenen Uhr. Mit nur 3 Satelliten gelingt eine zweidimensionale (2D) Position ohne Höhe. Die Satellitensignale kommen am Boden extrem schwach an (etwa -130 dBm); Beton, Metalldächer und sogar dichtes Laub schirmen sie stark ab. Deshalb gilt die goldene GPS-Regel: Die Antenne muss den Himmel sehen.
| Merkmal | Wert |
|---|---|
| Empfängerchip | u-blox NEO-6M (u-blox-6-Positionierungs-Engine) |
| Kanäle und Signal | 50 Kanäle, GPS L1 C/A (1575,42 MHz), SBAS: EGNOS, WAAS, MSAS |
| Horizontale Genauigkeit | 2,5 m CEP (mit SBAS 2,0 m) |
| Geschwindigkeits- und Kursgenauigkeit | 0,1 m/s und 0,5 Grad |
| Zeit bis zum ersten Fix (TTFF) | Kaltstart 27 s, Warmstart 27 s, Heißstart 1 s |
| Empfindlichkeit | Tracking -161 dBm, Kaltstart -147 dBm |
| Update-Rate | Standard 1 Hz, maximal 5 Hz |
| Schnittstelle | UART, standardmäßig 9600 Baud 8N1, NMEA 0183 |
| Versorgung | Platine: 3,3–5 V (mit Spannungsregler); Chip: 2,7–3,6 V |
| Stromaufnahme | ~47 mA bei der Suche, ~39 mA im Tracking |
| Betriebstemperatur | -40 bis +85 °C |
Die Platine, die du kaufst, besteht nicht nur aus dem 16×12 mm großen NEO-6M-Chip. Verbreitete GY-NEO6MV2-Boards haben zusätzlich eine 25×25 mm große Keramik-Patchantenne, einen Spannungsregler, mit dem du das Modul an 3,3–5 V betreiben kannst, ein kleines EEPROM für die Einstellungen, einen wiederaufladbaren Pufferakku für Uhrzeit und Satellitendaten sowie eine LED, die bei einem Fix blinkt. Manche Boards, wie das auf dem Foto oben, haben außerdem eine SMA- oder kleine u.FL-Buchse für eine externe Antenne und einen Micro-USB-Anschluss für die direkte Verbindung zum Computer.
NEO-6M anschließen: Arduino Uno, ESP32 und Raspberry Pi Pico
Der NEO-6M kommuniziert über UART, das wie die serielle Schnittstelle eines Computers funktioniert und zwei Datenleitungen nutzt. Die Regel ist einfach: Die Datenleitungen werden gekreuzt. Der TX-Pin (Senden) des Moduls kommt an den RX-Pin (Empfangen) des Boards, der RX-Pin des Moduls an den TX-Pin des Boards. Die einzige Hardware-Schnittstelle des Arduino Uno (Pins 0 und 1) wird zum Hochladen per USB und für den seriellen Monitor gebraucht, deshalb schließen wir das GPS mit SoftwareSerial an D4 und D3 an. Details zur seriellen Kommunikation findest du im Artikel UART: serielle Kommunikation.
| NEO-6M-Pin | Arduino Uno | ESP32 | Raspberry Pi Pico |
|---|---|---|---|
| VCC | 5V | VIN (5V) oder 3V3 | VBUS (5V) oder 3V3(OUT) |
| GND | GND | GND | GND |
| TX | D4 (SoftwareSerial RX) | GPIO 16 (RX2) | GP1 (UART0 RX) |
| RX | D3, über Spannungsteiler 1 kΩ / 2 kΩ | GPIO 17 (TX2) | GP0 (UART0 TX) |
| PPS (falls vorhanden) | Kann frei bleiben | Kann frei bleiben | Kann frei bleiben |
Der erste Fix: Kaltstart, Warmstart und Heißstart
Es ist völlig normal, dass ein GPS-Modul beim allerersten Einschalten nicht sofort eine Position liefert. Für die Berechnung braucht es die genauen Bahndaten (Ephemeriden) der sichtbaren Satelliten, und jeder Satellit sendet sie nur etwa alle 30 Sekunden; den kompletten Almanach, die grobe Bahnliste aller Satelliten, herunterzuladen dauert 12,5 Minuten. Je nachdem, wie viele Daten das Modul seit dem Ausschalten behalten hat, startet es auf eine von drei Arten. Die Zeiten im Datenblatt wurden unter Testbedingungen mit starken Signalen aller Satelliten gemessen; mit der kleinen Keramikantenne des Boards sind ein paar Minuten Wartezeit normal.
| Startart | Im Modul gespeicherte Daten | Datenblatt | In der Praxis (im Freien) |
|---|---|---|---|
| Kaltstart | Keine Zeit, Position oder Satellitendaten (erste Nutzung oder leerer Pufferakku) | 27 s | 1–5 Minuten; bei schwachem Signal auch über 10 Minuten |
| Warmstart | Almanach, ungefähre Zeit und Position vorhanden; Ephemeriden veraltet (länger als etwa 4 Stunden aus) | 27 s | 30 Sekunden – 1 Minute |
| Heißstart | Aktuelle Ephemeriden und Zeit (erst kurz ausgeschaltet, Pufferakku geladen) | 1 s | Wenige Sekunden |
- Geh ins Freie: In Innenräumen, besonders in Betonbauten, findet das Modul oft gar keine Position. Teste auf dem Balkon, im Garten oder wenigstens direkt an einem offenen Fenster.
- Richte die Antenne richtig aus: Die flache, helle Seite der Keramikantenne muss zum Himmel zeigen; umgedreht oder mit der Hand abgedeckt wird das Signal stark geschwächt.
- Halte die Antenne von Elektronik fern: Die WLAN-Antenne des ESP32, Schaltregler und lange USB-Kabel strahlen Störungen ab; platziere die Antenne einige Zentimeter von den Platinen entfernt.
- Sei geduldig und lass das Modul in Ruhe: Unterbrich beim ersten Fix nicht die Stromversorgung; jeder Neustart beginnt die Suche von vorn.
- Beobachte die LED: Die LED auf der Platine bleibt dunkel, bis ein Fix gefunden ist, und blinkt dann einmal pro Sekunde.
- Lade den Pufferakku: Ist er leer, wird jeder Start zum Kaltstart. Lässt du das Modul ein paar Stunden eingeschaltet, lädt sich der Akku und spätere Starts dauern nur noch Sekunden.
NMEA-Sätze: So liest du $GPGGA und $GPRMC
Der NEO-6M sendet alles, was er ermittelt, als kommagetrennte Klartextzeilen nach dem Standard NMEA 0183. In der Werkseinstellung kommen jede Sekunde sechs Satzarten: GGA, GLL, GSA, GSV, RMC und VTG; TXT-Sätze erscheinen meist nur beim Einschalten und enthalten Infomeldungen wie die Firmware-Version. Jeder Satz beginnt mit $; das Präfix GP zeigt, dass die Daten vom GPS stammen, die nächsten drei Buchstaben geben den Satztyp an. Die zwei Zeichen nach dem * am Zeilenende sind die Prüfsumme, die durch XOR-Verknüpfung aller Zeichen zwischen $ und * entsteht; damit werden fehlerhafte Zeilen aussortiert. Die zwei wichtigsten Sätze für die Position sind: $GPGGA,092750.00,4100.82500,N,02858.74000,E,1,08,1.01,39.2,M,36.9,M,,*67 und $GPRMC,092750.00,A,4100.82500,N,02858.74000,E,0.512,,281026,,,A*7E
| $GPGGA-Feld | Beispiel | Bedeutung |
|---|---|---|
| Uhrzeit (UTC) | 092750.00 | 09:27:50 UTC (10:27:50 MEZ) |
| Breitengrad | 4100.82500,N | 41 Grad 00,825 Minuten Nord |
| Längengrad | 02858.74000,E | 28 Grad 58,74 Minuten Ost |
| Fix-Qualität | 1 | 0 = kein Fix, 1 = GPS, 2 = differenziell (SBAS) korrigiert |
| Satelliten | 08 | Für die Position genutzte Satelliten |
| HDOP | 1.01 | Horizontale Präzisionsverringerung; unter 2 ist sehr gut |
| Höhe | 39.2,M | 39,2 m über dem mittleren Meeresspiegel |
| Geoidundulation | 36.9,M | Abstand zwischen Meeresspiegel und WGS84-Ellipsoid |
| $GPRMC-Feld | Beispiel | Bedeutung |
|---|---|---|
| Uhrzeit (UTC) | 092750.00 | Stunden, Minuten, Sekunden |
| Status | A | A = gültige Position, V = kein Fix |
| Breiten- / Längengrad | 4100.82500,N / 02858.74000,E | Gleiches Format wie bei GGA |
| Geschwindigkeit | 0.512 | In Knoten (0,512 × 1,852 ≈ 0,95 km/h) |
| Kurs | (leer) | Bewegungsrichtung in Grad; im Stand oft leer |
| Datum | 281026 | Format TTMMJJ: 28.10.2026 |
| Modus | A | A = autonom, D = differenziell, N = keine Daten |
Breiten- und Längengrad stehen im NMEA-Satz nicht in Dezimalgrad, sondern in Grad und Minuten (ggmm.mmmm); Google Maps und die meisten Programme erwarten jedoch Dezimalgrad. Zum Umrechnen nimmst du beim Breitengrad die ersten zwei, beim Längengrad die ersten drei Ziffern als Grad und addierst die restlichen Minuten geteilt durch 60: 4100.82500 → 41 + 0,825 / 60 = 41,013750; 02858.74000 → 28 + 58,74 / 60 = 28,979000. Süd- (S) und West-Werte (W) werden negativ geschrieben. Die sechste Nachkommastelle entspricht etwa 11 cm, die fünfte 1,1 m; bei 2,5 m Genauigkeit des NEO-6M reichen sechs Stellen völlig aus.
Schritt für Schritt: GPS-Rohdaten mit dem Arduino Uno anzeigen
- Schließe den NEO-6M wie in der Tabelle an: VCC → 5V, GND → GND, GPS TX → D4, GPS RX → über den Teiler an D3.
- Lade den folgenden Code hoch; eine zusätzliche Bibliothek ist nicht nötig, SoftwareSerial ist in der Arduino IDE enthalten.
- Öffne den seriellen Monitor und stelle 115200 Baud ein.
- Bring das Modul ins Freie oder ans Fenster und beobachte die Zeilen, die mit $GP beginnen.
- Wechselt das zweite Feld der $GPRMC-Zeile von V auf A und beginnt die LED zu blinken, hat das Modul seine Position gefunden.
1#include <SoftwareSerial.h>
2
3SoftwareSerial gpsSerial(4, 3); // RX, TX → GPS TX D4'e, GPS RX D3'e / GPS TX to D4, GPS RX to D3
4
5void setup() {
6 Serial.begin(115200); // Seri Monitör hızı / Serial Monitor speed
7 gpsSerial.begin(9600); // NEO-6M varsayılan hızı / NEO-6M default baud rate
8 Serial.println(F("NEO-6M ham NMEA / raw NMEA"));
9}
10
11void loop() {
12 while (gpsSerial.available()) {
13 Serial.write(gpsSerial.read()); // gelen her baytı aynen aktar / pass every byte through
14 }
15}Im seriellen Monitor erscheint jede Sekunde ein Block aus sechs bis neun Zeilen (je mehr Satelliten sichtbar sind, desto mehr Zeilen umfasst der GSV-Satz). Hat das Modul noch keine Satelliten gefunden, sind die Zeilen voller leerer Kommas, etwa $GPRMC,,V,,,,,,,,,,N*53 und $GPGGA,,,,,,0,00,99.99,,,,,,*48; das ist kein Fehler, sondern zeigt, dass das Modul arbeitet, aber noch keine Position berechnen kann. In den $GPGSV-Zeilen siehst du die Zahl der sichtbaren Satelliten und die Signalstärke (dB-Hz) jedes einzelnen; Werte über 30 dB-Hz bedeuten guten Empfang. Kommen gar keine Zeilen, prüfe die Verkabelung; erscheinen wirre Zeichen, prüfe die Baudrate.
Breitengrad, Längengrad, Geschwindigkeit und Uhrzeit mit TinyGPSPlus
Statt die NMEA-Zeilen von Hand zu zerlegen, ist die Bibliothek TinyGPSPlus von Mikal Hart viel praktischer. Suche im Bibliotheksverwalter nach "TinyGPSPlus" und installiere sie; die Schritte erklären wir im Artikel Arduino-Bibliothek hinzufügen. Achtung: Die Beispiele der Bibliothek nutzen 4800 Baud, der NEO-6M aber 9600 Baud. Startest du ein Beispiel ohne die Geschwindigkeit anzupassen, steht bei der Position immer INVALID, weil die Bibliothek aus den verstümmelten Zeichen keinen einzigen Satz entschlüsseln kann. Der folgende Code gibt einmal pro Sekunde Position, Geschwindigkeit, Höhe, Satellitenzahl, Datum und Uhrzeit aus und macht aus der Position einen Google-Maps-Link, den du im Browser öffnen kannst:
1#include <TinyGPSPlus.h>
2#include <SoftwareSerial.h>
3
4const int RX_PIN = 4; // GPS TX → D4
5const int TX_PIN = 3; // GPS RX ← D3 (bölücü üzerinden / through a divider)
6const uint32_t GPS_BAUD = 9600; // NEO-6M varsayılanı / NEO-6M default
7
8TinyGPSPlus gps;
9SoftwareSerial gpsSerial(RX_PIN, TX_PIN);
10unsigned long lastPrint = 0;
11
12void setup() {
13 Serial.begin(115200);
14 gpsSerial.begin(GPS_BAUD);
15 Serial.println(F("NEO-6M + TinyGPSPlus"));
16}
17
18void loop() {
19 while (gpsSerial.available()) {
20 gps.encode(gpsSerial.read()); // her baytı ayrıştırıcıya ver / feed every byte to the parser
21 }
22 if (millis() - lastPrint >= 1000) { // delay() yok, saniyede bir yaz / no delay(), print once per second
23 lastPrint = millis();
24 printInfo();
25 }
26}
27
28void printInfo() {
29 if (gps.charsProcessed() < 10) {
30 Serial.println(F("GPS verisi yok: kablolari ve baud hizini kontrol et / No GPS data: check wiring and baud"));
31 return;
32 }
33 Serial.print(F("Uydu / Sats: "));
34 Serial.println(gps.satellites.value());
35
36 if (gps.location.isValid()) {
37 Serial.print(F("Enlem / Lat: "));
38 Serial.println(gps.location.lat(), 6);
39 Serial.print(F("Boylam / Lng: "));
40 Serial.println(gps.location.lng(), 6);
41 Serial.print(F("Hiz / Speed: "));
42 Serial.print(gps.speed.kmph(), 1);
43 Serial.println(F(" km/h"));
44 Serial.print(F("Yukseklik / Alt: "));
45 Serial.print(gps.altitude.meters(), 1);
46 Serial.println(F(" m"));
47 // Google Haritalar bağlantısı / Google Maps link
48 Serial.print(F("https://www.google.com/maps/search/?api=1&query="));
49 Serial.print(gps.location.lat(), 6);
50 Serial.print(',');
51 Serial.println(gps.location.lng(), 6);
52 } else {
53 Serial.println(F("Konum yok, uydu araniyor / No fix yet, searching"));
54 }
55
56 if (gps.date.isValid() && gps.time.isValid()) {
57 char buf[32];
58 snprintf(buf, sizeof(buf), "%02d.%02d.%04d %02d:%02d:%02d UTC",
59 gps.date.day(), gps.date.month(), (int)gps.date.year(),
60 gps.time.hour(), gps.time.minute(), gps.time.second());
61 Serial.println(buf); // saat UTC'dir / time is UTC
62 }
63 Serial.println();
64}| Funktion | Rückgabewert |
|---|---|
| gps.encode(c) | Wird mit jedem empfangenen Byte aufgerufen; true, sobald ein gültiger Satz vollständig ist |
| gps.location.lat() / lng() | Breiten- und Längengrad in Dezimalgrad |
| gps.location.isValid() / age() | Gibt es eine gültige Position / Millisekunden seit dem letzten Update |
| gps.speed.kmph() | Geschwindigkeit über Grund in km/h (auch mps() und knots()) |
| gps.course.deg() | Bewegungsrichtung in Grad (0 = Nord, 90 = Ost) |
| gps.altitude.meters() | Höhe über dem Meeresspiegel in Metern |
| gps.satellites.value() | Anzahl der für die Position genutzten Satelliten |
| gps.hdop.hdop() | Horizontale Präzisionsverringerung (kleiner = besser) |
| gps.date.day() / gps.time.hour() | Datums- und Zeitfelder in UTC |
| TinyGPSPlus::distanceBetween(...) | Entfernung zwischen zwei Koordinaten in Metern |
| gps.failedChecksum() | Anzahl fehlerhafter Sätze; steigt sie ständig, gehen Daten verloren |
Die wichtigste Regel in diesem Code lautet: Kein delay() in loop(). Das GPS sendet etwa 500 Bytes pro Sekunde, der Empfangspuffer von SoftwareSerial fasst aber nur 64 Bytes; während eines langen delay() läuft er über, Sätze werden abgeschnitten und TinyGPSPlus verwirft sie wegen falscher Prüfsumme. Deshalb geben wir die Werte mit millis() einmal pro Sekunde aus; Details findest du im Artikel millis() statt delay(). Die GPS-Zeit ist immer UTC; in Deutschland addierst du im Winter 1 Stunde (MEZ) und im Sommer 2 Stunden (MESZ). Auf dem Arduino Uno ist double in Wirklichkeit ein 32-Bit-float, daher wird die letzte Stelle von Breiten- und Längengrad auf etwa einen halben Meter gerundet; neben den 2,5 m Genauigkeit des Moduls spielt das keine Rolle.
ESP32 mit Serial2: Position auf einem OLED-Display anzeigen
Am ESP32 brauchst du kein SoftwareSerial: Der Chip hat drei Hardware-UARTs, und Serial2 lässt sich beliebigen Pins zuordnen. Im folgenden Beispiel hängt das GPS an GPIO 16 (RX2) und GPIO 17 (TX2); da der ESP32 mit 3,3 V arbeitet, entfällt auch der Spannungsteiler. Position, Geschwindigkeit und Ortszeit erscheinen auf einem 0,96-Zoll-SSD1306-OLED-Display, das per I2C an GPIO 21 (SDA) und GPIO 22 (SCL) angeschlossen ist. Neben TinyGPSPlus braucht der Code die Bibliotheken Adafruit SSD1306 und Adafruit GFX.
1#include <TinyGPSPlus.h>
2#include <Wire.h>
3#include <Adafruit_GFX.h>
4#include <Adafruit_SSD1306.h>
5
6#define GPS_RX 16 // ESP32 RX2 ← GPS TX
7#define GPS_TX 17 // ESP32 TX2 → GPS RX
8const int UTC_OFFSET = 3; // Türkiye UTC+3, kendi saat dilimini yaz / set your own time zone
9
10TinyGPSPlus gps;
11Adafruit_SSD1306 display(128, 64, &Wire, -1); // OLED: SDA 21, SCL 22
12unsigned long lastDraw = 0;
13
14String mapsLink() {
15 // Google Haritalar bağlantısı üret / build a Google Maps link
16 return "https://www.google.com/maps/search/?api=1&query=" +
17 String(gps.location.lat(), 6) + "," + String(gps.location.lng(), 6);
18}
19
20void drawScreen() {
21 display.clearDisplay();
22 display.setTextSize(1);
23 display.setCursor(0, 0);
24 display.print(F("Uydu/Sat: "));
25 display.print(gps.satellites.value());
26
27 if (gps.time.isValid()) {
28 int h = (gps.time.hour() + UTC_OFFSET + 24) % 24; // yerel saat / local time
29 char t[12];
30 snprintf(t, sizeof(t), "%02d:%02d:%02d", h, gps.time.minute(), gps.time.second());
31 display.setCursor(80, 0);
32 display.print(t);
33 }
34
35 if (gps.location.isValid()) {
36 display.setCursor(0, 16);
37 display.print(F("Lat: "));
38 display.println(gps.location.lat(), 6);
39 display.print(F("Lng: "));
40 display.println(gps.location.lng(), 6);
41 display.setTextSize(2); // hız büyük yazılsın / speed in large digits
42 display.setCursor(0, 44);
43 display.print(gps.speed.kmph(), 1);
44 display.print(F(" km/h"));
45 } else {
46 display.setCursor(0, 24);
47 display.println(F("Uydu araniyor..."));
48 display.println(F("Searching for fix"));
49 }
50 display.display();
51}
52
53void setup() {
54 Serial.begin(115200);
55 Serial2.begin(9600, SERIAL_8N1, GPS_RX, GPS_TX); // donanım UART2 / hardware UART2
56 if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
57 Serial.println(F("OLED bulunamadi / OLED not found"));
58 while (true) delay(10);
59 }
60 display.setTextColor(SSD1306_WHITE);
61}
62
63void loop() {
64 while (Serial2.available()) {
65 gps.encode(Serial2.read()); // NMEA baytlarını çöz / decode NMEA bytes
66 }
67 if (millis() - lastDraw >= 1000) { // saniyede bir güncelle / refresh once per second
68 lastDraw = millis();
69 drawScreen();
70 if (gps.location.isValid()) {
71 Serial.println(mapsLink()); // Telegram ya da SMS ile gönderilebilir / can be sent via Telegram or SMS
72 }
73 }
74}Die Variable UTC_OFFSET rechnet die GPS-Zeit in Ortszeit um; für Deutschland ist sie im Winter 1 und im Sommer 2. Die Funktion mapsLink() macht aus der Position eine Google-Maps-Adresse mit dem Parameter query=Breitengrad,Längengrad. Diesen Link kannst du aus dem seriellen Monitor kopieren und im Browser öffnen, mit einem Telegram-Bot aufs Handy schicken oder mit einem SIM800L-GSM-Modul per SMS versenden. Auf ESP32-WROVER-Boards mit PSRAM sind GPIO 16 und 17 für den Speicher belegt; schließe das GPS dort zum Beispiel an GPIO 26 und 27 an. Auf dem ESP32-C3, der nur zwei UARTs hat, nimmst du Serial1 statt Serial2.
GPS mit dem Raspberry Pi Pico und MicroPython auslesen
Am Raspberry Pi Pico hängt das GPS an UART0: TX des Moduls an GP1, RX an GP0. In MicroPython können wir die NMEA-Zeilen ohne zusätzliche Bibliothek selbst zerlegen, und das ist zugleich eine prima Übung, um den Aufbau der Sätze zu verstehen. Der Code prüft die Prüfsumme jeder Zeile, holt die Satellitenzahl aus GGA sowie Position, Geschwindigkeit und Uhrzeit aus RMC und rechnet Grad und Minuten in Dezimalgrad um. Die Einstellung timeout=200 sorgt dafür, dass readline() bis zu 200 ms auf das Zeilenende wartet; rutscht beim Start doch eine halbe Zeile durch, verwirft die Prüfsummenkontrolle sie. Weil der Satztyp mit f[0][3:] ermittelt wird, erkennt der Code auch die Zeilen $GNRMC und $GNGGA von Modulen, die mehrere Satellitensysteme nutzen. Wenn du noch nicht weißt, wie man Code mit Thonny startet, lies zuerst den Artikel MicroPython-Grundlagen.
1from machine import UART, Pin
2
3# GP0 (TX) → GPS RX, GP1 (RX) ← GPS TX
4gps = UART(0, baudrate=9600, tx=Pin(0), rx=Pin(1), timeout=200, rxbuf=1024)
5
6def checksum_ok(line):
7 # $ ile * arasındaki karakterlerin XOR'u / XOR of the characters between $ and *
8 try:
9 body, cs = line[1:].split('*')
10 x = 0
11 for ch in body:
12 x ^= ord(ch)
13 return x == int(cs[:2], 16)
14 except ValueError:
15 return False
16
17def to_deg(value, hemi):
18 # ddmm.mmmm → ondalık derece / decimal degrees
19 dot = value.index('.')
20 deg = int(value[:dot - 2]) + float(value[dot - 2:]) / 60
21 return -deg if hemi in ('S', 'W') else deg
22
23sats = '0'
24while True:
25 raw = gps.readline() # bir NMEA satırı / one NMEA line
26 if not raw:
27 continue
28 try:
29 line = raw.decode().strip()
30 except UnicodeError:
31 continue # bozuk bayt / corrupted byte
32 if not line.startswith('$') or not checksum_ok(line):
33 continue
34 f = line.split('*')[0].split(',')
35 kind = f[0][3:] # GPRMC ya da GNRMC → RMC / GPRMC or GNRMC → RMC
36 if kind == 'GGA':
37 sats = f[7] # kullanılan uydu sayısı / satellites in use
38 elif kind == 'RMC':
39 if f[2] != 'A':
40 print('Uydu araniyor / searching, uydu/sats:', sats)
41 continue
42 lat = to_deg(f[3], f[4])
43 lon = to_deg(f[5], f[6])
44 kmh = float(f[7] or 0) * 1.852 # knot → km/sa / knots → km/h
45 t = f[1]
46 print('UTC {}:{}:{} uydu/sats: {}'.format(t[0:2], t[2:4], t[4:6], sats))
47 print('Konum / position: {:.6f}, {:.6f} {:.1f} km/h'.format(lat, lon, kmh))
48 print('https://www.google.com/maps/search/?api=1&query={:.6f},{:.6f}'.format(lat, lon))Projektideen mit dem NEO-6M
- Tracker, der seine Position per SMS schickt: Mit NEO-6M und SIM800L baust du einen Auto- oder Fahrradtracker, der auf eine SMS mit "POSITION" mit einem Google-Maps-Link antwortet.
- GPS-Datenlogger: Speichere deine Route jede Sekunde als CSV auf einem SD-Kartenmodul und zeige sie später am Computer auf einer Karte an.
- Fahrradtacho: Zeige aktuelle und Höchstgeschwindigkeit sowie die Gesamtstrecke auf einem OLED-Display; die Strecke summierst du mit TinyGPSPlus::distanceBetween() zwischen aufeinanderfolgenden Punkten.
- Satellitengenaue Uhr: Hol dir die Zeit vom GPS und stelle ein RTC-Uhrmodul ohne Internet sekundengenau.
- Geofence-Alarm: Ein System, das einen Summer auslöst oder eine Nachricht schickt, wenn sich etwas mehr als 100 Meter von einem festgelegten Punkt entfernt.
- Tracking über große Entfernung: Sende die Position mit einem LoRa-Modul an einen kilometerweit entfernten Empfänger und spare im Akkubetrieb Energie mit ESP32 Deep Sleep.
Keine Daten oder kein Fix: häufige Fehler und Lösungen
| Symptom | Mögliche Ursache | Lösung |
|---|---|---|
| Serieller Monitor bleibt leer | TX und RX vertauscht, keine gemeinsame Masse oder Modul ohne Strom | GPS-TX an den RX-Pin des Boards (beim Uno D4), Massen verbinden, VCC messen |
| "No GPS detected: check wiring." | In 5 Sekunden kamen nicht einmal 10 Zeichen bei der Bibliothek an | Verkabelung und Pinnummern im Code prüfen; TX und RX testweise tauschen |
| Wirre Zeichen | Baudrate passt nicht | 9600 für das GPS und die Code-Geschwindigkeit im seriellen Monitor; sonst 4800 und 38400 testen |
| Zeilen kommen, aber Felder sind leer (,V,) | Das Modul arbeitet, hat aber keine Satelliten gefunden | Ins Freie gehen, Antenne zum Himmel richten, 5–15 Minuten warten |
| Satellitenzahl bleibt bei 0–3 | Schwaches Signal, Antenne verkehrt herum, lockere u.FL-Buchse oder Störquelle in der Nähe | Antenne prüfen, Stecker fest eindrücken, Antenne von ESP32 und Reglern fernhalten |
| Rohdaten zeigen eine Position, TinyGPSPlus meldet INVALID | delay() in loop() lässt den Puffer überlaufen; failedChecksum() steigt | delay() entfernen, millis() nutzen, encode() ständig aufrufen |
| Uhrzeit weicht um Stunden ab | GPS-Zeit ist UTC | Zeitzonenversatz addieren (MEZ +1, MESZ +2) |
| Position wandert im Stand einige Meter, Geschwindigkeit nicht 0 | Normales GPS-Rauschen und von Gebäuden reflektierte Signale | Geschwindigkeiten unter 2 km/h als 0 werten, Werte mit hohem HDOP verwerfen, mitteln |
| Wartet bei jedem Start wieder minutenlang | Pufferakku leer oder nicht vorhanden | Modul einige Stunden eingeschaltet lassen, damit der Akku lädt |
Der NEO-6M beantwortet in deinen Projekten für sehr wenig Geld die Fragen "Wo bin ich, wie schnell bin ich und wie spät ist es?"; das Geheimnis ist, der Antenne den Himmel zu zeigen und dem ersten Fix die nötige Geduld zu gönnen. Um die serielle Kommunikation besser zu verstehen, lies den Artikel zu UART. In der BlueGrays-App findest du Projekte, die dir auch bei GPS-Bauten helfen, etwa serielle Kommunikation zwischen zwei Arduinos, OLED-Displays, Datenlogging auf microSD, ESP32 Deep Sleep und einen Alarm mit Telegram-Benachrichtigung, jeweils mit Schaltplan und Schritt-für-Schritt-Code.
Häufige Fragen
Funktioniert das NEO-6M GPS-Modul in Innenräumen?
Meistens nicht. Die Satellitensignale kommen am Boden sehr schwach an, und Beton- oder Metalldächer schirmen sie weitgehend ab. Direkt an einem offenen Fenster empfängt das Modul manchmal ein paar Satelliten, für einen zuverlässigen Fix braucht die Antenne aber freie Sicht zum Himmel; drinnen hilft eine externe aktive Antenne auf dem Dach oder am Fenster.
Wie lange braucht der NEO-6M für den ersten Fix?
Laut Datenblatt dauert ein Kaltstart 27 Sekunden, ein Heißstart 1 Sekunde. In der Praxis braucht der erste Fix mit der kleinen Keramikantenne im Freien meist 1–5 Minuten, bei der ersten Nutzung oder leerem Pufferakku auch 10–15 Minuten. War das Modul nur kurz aus, rastet es in wenigen Sekunden wieder ein.
Wie genau ist das NEO-6M GPS-Modul?
Der Hersteller gibt bei freiem Himmel eine horizontale Genauigkeit von 2,5 m CEP an, mit SBAS-Korrektur 2,0 m; die Hälfte der Messungen liegt also näher als 2,5 m am wahren Punkt. In Städten können von Gebäuden reflektierte Signale den Fehler auf 5–10 Meter erhöhen. Die Höhe ist ungenauer als die horizontale Position.
Läuft der NEO-6M mit 5V und kann ich ihn direkt an den Arduino anschließen?
Verbreitete GY-NEO6MV2-Boards haben einen Spannungsregler, VCC darf also an 5 V. Der RX-Pin des Chips verträgt aber höchstens 3,6 V; teile das 5-V-TX-Signal des Arduino Uno mit einem Spannungsteiler aus 1 kΩ und 2 kΩ herunter. Der TX-Ausgang des Moduls liefert 3,3 V, die der Uno problemlos erkennt.
Braucht ein GPS-Modul Internet oder eine SIM-Karte?
Nein. Der NEO-6M berechnet seine Position direkt aus den Satellitensignalen, kostenlos und ohne Internet. Internet oder eine SIM-Karte brauchst du nur, wenn du die Position irgendwohin senden willst, etwa über das WLAN des ESP32 oder ein GSM-Modul wie den SIM800L.
Was ist der Unterschied zwischen NEO-6M und NEO-M8N?
Der NEO-6M nutzt nur GPS-Satelliten. Der neuere NEO-M8N kann zusätzlich zu GPS gleichzeitig GLONASS-, Galileo- oder BeiDou-Satelliten verwenden; weil er mehr Satelliten sieht, findet er in Städten schneller einen stabilen Fix. Seine Sätze beginnen meist mit $GN, TinyGPSPlus liest aber beide mit demselben Code.
Projekte, die du danach bauen kannst
Alle Projekte ansehen
Einweg-Kommunikation zwischen 2 Arduinos
Ein Projekt zur einseitigen Datenübertragung zwischen zwei Arduinos über serielle Kommunikation. Es erkennt den Tastendruck auf der Senderseite und lernt die Steuerung der LED auf der Empfängerseite.

Bidirektionale Kommunikation zwischen 2 Arduinos
Ein Projekt, das bidirektionale Daten zwischen zwei Arduinos über serielle Kommunikation überträgt. Beide Boards lesen die Taste und senden Daten und empfangen Daten und steuern die LED.

ESP32 Temperatur-Datenlogger (DHT22 + DS1307 RTC + microSD + OLED)
Baue einen zeitgestempelten Temperaturlogger mit ESP32! Lese Temperatur/Feuchtigkeit vom DHT22 alle 10 Sekunden, hole die aktuelle Zeit vom DS1307 RTC und protokolliere auf microSD-Karte als CSV. Das OLED zeigt live Temperatur (große Schrift), Luftfeuchtigkeit, Zeitstempel und Logzähler. Die `/temp_log.csv`-Datei auf der SD-Karte öffnet sich in Excel, Google Sheets oder Python pandas zur Analyse — perfekt für Gewächshausüberwachung, Raumtemperaturverfolgung, Laboraufzeichnung, Lebensmittellageru

ESP32 HTTPClient + Wetter-API (mit SSD1306-OLED-Display)
In diesem Projekt führen wir mit dem ESP32 über das Internet mithilfe von `HTTPClient.h` einen REST-API-Aufruf an die Wetter-API (wttr.in) durch. Im Gegensatz zur vorherigen I2C-LCD-Version verwenden wir hier ein SSD1306-OLED-Display (128×64) – dies ermöglicht große Schriftarten, Vektor-Symbole und eine reichhaltige visuelle Darstellung auf einem einzigen Bildschirm. Für die Wetteranzeige werden 7 verschiedene Vektor-Symbole (sonnig, teilweise bewölkt, bewölkt, regnerisch, schneereich, stürmisch

ESP32 Deep Sleep – Batteriesparmodus (OLED + RTC-RAM-Zähler)
Der Deep-Sleep-Modus des ESP32 senkt den Stromverbrauch auf etwa 10 µA, indem er die CPU und die meisten Peripheriegeräte abschaltet, und ist für batteriebetriebene IoT-Geräte von entscheidender Bedeutung. In diesem Projekt verwenden wir drei verschiedene Weckquellen: den Timer (15 s), einen externen Pin (EXT0 – Taste GPIO 33) und die Berührungserkennung (T0/GPIO 4). Mit `RTC_DATA_ATTR` markierte Variablen bleiben während des Deep-Sleep-Modus erhalten – der Boot-Zähler, der Timer-Wake-Zähler und

ESP32: Echtzeit aus dem Internet per NTP
Der ESP32 verbindet sich mit dem WLAN und ruft die Echtzeit mit Millisekunden-Genauigkeit von NTP-Servern (Network Time Protocol) ab. Dank `configTzTime()` wird die türkische Zeitzone (TRT, UTC+3) automatisch angewendet, und der DST-Wechsel wird per POSIX-TZ-String verwaltet. Die Uhrzeit wird auf dem Serial Monitor und einem optionalen I2C-LCD ausgegeben. `configTzTime()` startet den SNTP-Dienst; bei verfügbarem Netzwerkzugang erfolgt regelmäßig eine erneute Synchronisierung, und zwischen den Sy

ESP32 Bewegungsalarmsystem (PIR + Buzzer + LED + Telegram)
Ein intelligentes Sicherheitsalarmsystem, das Buzzer und LED aktiviert, sobald der PIR-Sensor Bewegung erkennt, und gleichzeitig eine sofortige Benachrichtigung per Telegram an den Besitzer sendet. Ein 30-sekündiger Cooldown begrenzt die Häufigkeit wiederholter Alarme; dieser Mechanismus überprüft weder die Gültigkeit der PIR-Erkennungen noch verhindert er Fehlauslösungen. Geeignet für Heimsicherheit, Garagenüberwachung, Lagerräume oder Arbeitszimmer. Mit ESP32-CAM sind Foto-Benachrichtigungen m

Digitale Uhr mit ESP32 und RTC DS1307 (I2C + LCD)
In diesem Projekt zeigen wir Uhrzeit und Datum auf einem 16x2-I2C-LCD-Display mithilfe des DS1307-Echtzeituhrmoduls (RTC) an. Das DS1307 ist ein batteriegestütztes RTC, das die Uhrzeit auch dann beibehält, wenn das ESP32 ausgeschaltet ist. Beide Module teilen sich denselben I2C-Bus (SDA/SCL), sodass wir mit nur zwei Signalkabeln die Steuerung mehrerer Geräte erlernen. So lernen Sie das I2C-Protokoll und die Funktionsweise von RTC-Modulen in der Praxis kennen.

