GPS mit dem Arduino oder mit dem Raspberry Pi
Vor einem Jahrzehnt noch undenkbar in der Zwischenzeit für um die 10€ Euro erhältlich. Ein komplettes GPS Modul das sogar in Räumen funktioniert und mit dem der Standort bis auf wenige Meter genau ermittelt werden kann.
GPS klingt zunächst unheimlich kompliziert. Die Mathematik dahinter ist es auch, nachzulesen unter https://de.wikipedia.org/wiki/Global_Positioning_System.
In der Zwischenzeit gibt es aber GPS-Module die die Komplexität komplett kapseln.
Die GPS-Module die in der Bauteileliste stehen kommunizieren alle über eine einfache Serielle Schnittstelle, daher ist es recht einfach an die GPS-Daten zu kommen. Man muss nur einen Code schreiben, der eine Serielle Schnittstelle mit 9600 Baud öffnet und kontinuierlich ausliest. Und das ist in jeder Programmiersprache und auf jedem Rechner egal ob Embedded, Microcomputer, Arduino, Raspberry Pi oder PC oder kein Hexenwerk, weil es Bibliotheken für Serielle Schnittstellen überall gibt.
Das GPS Modul holt man sich am Besten von ebay. Im Prinzip geht jedes Modul, das VCC, GND, RX , TX bietet. Tipp zum Suchen: Nach „NEO-6M“ „GPS Modul Arduino“ „GY-GPS6MV2“ „NEO-6M Flight Controller“, „SkyNav SKM53“ immer in Verbindung mit „Arduino“ suchen
Also legen wir auf dem Arduino mal los:
Bauteile:
- Arduino (Uno, Nano …) oder Raspberry Pi (1,2,3)
- GPS Modul von ebay
- Steckbrett
- Kabel
- Lego
Schaltplan
Der Arduino Code:
Im Prinzip ist es der Sketch-Code des SoftwareSerial Beispiels.
#includeSoftwareSerial mySerial(10, 11); // RX, TX void setup() { // Open serial communications and wait for port to open: Serial.begin(9600); while (!Serial) { ; // wait for serial port to connect. Needed for native USB port only } Serial.println("Goodnight moon!"); // set the data rate for the SoftwareSerial port mySerial.begin(9600); // mySerial.println("Hello, world?"); } void loop() { // run over and over if (mySerial.available()) { Serial.write(mySerial.read()); } if (Serial.available()) { mySerial.write(Serial.read()); } }
Der Raspberry Pi / Linux Code:
in Perl, aber wie gesagt es geht mit jeder Programmiersprache.
#!/usr/bin/perl use strict; use Device::SerialPort; my $seriel = Device::SerialPort->new('/dev/ttyS0') || die "Kann /dev/ttyS0 nicht öffnen! ($!)n"; # halt prüfen an welcher tty das GPS-Modul hängt $seriel->baudrate(9600); $seriel->parity("none"); $seriel->databits(8); $seriel->stopbits(1); $|=1; my $exit=0; while($exit < 100000) { my ($cin, $sin) = $seriel->read(1); if($cin) { print $sin; $exit=0; } else {$exit++} } print "n"; exit(0);
Steckplatine
Der NMEA 0183 Standard
Die Ausgabe, die man dann angezeigt bekommt sieht im ersten Moment ziemlich verwirrend um mich zu sagen kaputt aus. Es handelt sich dabei aber um die Ausgabe der Koordinaten nach dem NMEA 0183 Standard, nachzulesen in der Wikipedia: „NMEA 0183 ist ein Standard…, der von der National Marine Electronics Association (NMEA) definiert wurde und auch für die Kommunikation zwischen GPS-Empfänger und PCs sowie mobilen Endgeräten genutzt wird. Er besteht aus einer RS422-Schnittstelle und einer Definition von Datensätzen.“ Aha, und jetzt?
Syntax des NMEA 0183 Datenformats:
- Bei den NMEA-Daten handelt es sich um ASCII-basierte Datensätze.
- Jeder Datensatz beginnt mit einem „$“
- Jeder Datensatz wird durch ein (
) abgeschlossen. - Jedes Datum in einem Datensatz wird durch ein „,“ getrennt.
- Dezimaltrennzeichen ist der Punkt („.“)
- Uhrzeiten werden in UTC angegeben
Der fertige Aufbau
Dekodieren der GPS-Daten:
Daten meines Empfängers: | $GPGGA,223758.00,4848.02931,N,00859.93258,E,1,03,3.14,426.4,M,47.6,M,,*59 |
Format: | $GPGGA,HHMMSS.ss,BBBB.BBBB,b,LLLLL.LLLL,l,Q,NN,D.D,H.H,h,G.G,g,A.A,RRRR*PP |
Dekodieren des GPGGA-Datensatzes:
Global Positioning System Fix Data (GPGGA)
Dieses Format enthält die wichtigsten Angaben zur Position und deren Genauigkeit, Anzahl der Satelliten, Höhe über Meeresoberfläche und andere Informationen.
Meine Daten | Format | Bedeutung |
223758.00 | HHMMSS.ss | aktuelle Uhrzeit (UTC) |
484802931 | BBBB.BBBB | Breitengrad in Grad und Minuten (ddmm.mmmmmm) |
N | b | Ausrichtung des Breitengrades (Nord oder Süd) |
85993258 | LLLLL.LLLL | Längengrad in Grad und Minuten (dddmm.mmmmmm) |
E | l | Ausrichtung des Längengrades (East oder West) |
1 | Q | GPS-Qualität: 0 für ungültig 1 für GPS fix 2 für DGPS fix 6 für geschätzt |
3 | NN | Anzahl der benutzten Satelliten (00 − 12) |
41699 | D.D | horizontale Abweichung (dilution of precision) |
426.4 | H.H | Höhe der Antenne über der Meeresoberfläche |
M | h | Einheit der Antennenhöhe (Meter) |
47.6 | G.G | geoidal separation |
M | g | Einheit der geoidal separation (Meter) |
A.A | Alter des DGPS-Datensatzes | |
RRRR | DGPS-Referenzstation (0000 bis 1023) | |
*59 | PP | Prüfsumme |
Die Ausgabe des GPS-Moduls nach dem NMEA 0183-Standard:
Direkt nach dem Start sehen die Daten so aus. Das ist normal!
$GPGSV,1,1,00*79 $GPGLL,,,,,,V,N*64 $GPRMC,,V,,,,,,,,,,N*53 $GPVTG,,,,,,,,,N*30 $GPGGA,,,,,,0,00,99.99,,,,,,*48 $GPGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*30 $GPGSV,1,1,00*79 $GPGLL,,,,,,V,N*64 $GPRMC,,V,,,,,,,,,,N*53 $GPVTG,,,,,,,,,N*30 $GPGGA,,,,,,0,00,99.99,,,,,,*48 $GPGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*30
Die serielle Ausgabe
Hintergrund warum das so langsam geht:
Die GPS-Satelliten senden nur mit der heute lächerlichen Übertragungsrate von 50 Bit pro Sekunde. Bis ein Satellit den kompletten Datensatz übertragen hat vergehen dadurch rund 30-40 Sekunden. Nach dem ersten Start, dem sog. Cold Start dauert es um die 15 Minuten, bis die vollständigen Bahndaten der zur Berechnung nötigen Satelliten vorliegen.
15 Minuten für einen Datensatz ist heute ein Unding, aber man muss dabei bedenken, wann das System erdacht und gebaut wurde. Der erste GPS-Satellit wurde 1978 gestartet. Damals waren Computer noch etwas größer und langsamer.
Nach ein paar Minuten sieht es dann so aus:
$GPGGA,214750.00,,,,,0,04,11.58,,,,,,*6A $GPGSA,A,1,14,29,32,31,,,,,,,,,16.48,11.58,11.73*3F $GPGSV,4,1,13,02,30,053,21,04,26,289,29,05,02,092,20,06,02,027,*7D $GPGSV,4,2,13,12,30,096,,14,21,255,13,21,09,185,20,23,00,345,*73 $GPGSV,4,3,13,25,72,081,08,26,14,288,18,29,77,225,22,31,52,293,25*71 $GPGSV,4,4,13,32,10,231,28*41 $GPGLL,,,,,214750.00,V,N*4F $GPRMC,214751.00,V,,,,,,,190117,,,N*76 $GPVTG,,,,,,,,,N*30 $GPGGA,214751.00,,,,,0,04,11.58,,,,,,*6B $GPGSA,A,1,14,29,32,31,,,,,,,,,16.49,11.58,11.73*3E $GPGSV,4,1,13,02,30,053,21,04,26,289,29,05,02,092,,06,02,027,*7F $GPGSV,4,2,13,12,30,096,,14,21,255,13,21,09,185,20,23,00,345,*73 $GPGSV,4,3,13,25,72,081,08,26,14,288,18,29,77,225,22,31,52,293,25*71 $GPGSV,4,4,13,32,10,231,28*41 $GPGLL,,,,,214751.00,V,N*4E
Nach 15 Minuten haben wir den kompletten Datensatz:
$GPGSV,4,4,13,32,02,225,*4D $GPGLL,4848.02898,N,00859.93723,E,221204.00,A,A*6D $GPRMC,221205.00,A,4848.02796,N,00859.93615,E,1.118,,190117,,,A*76 $GPVTG,,T,,M,1.118,N,2.071,K,A*2E $GPGGA,221205.00,4848.02796,N,00859.93615,E,1,03,7.96,393.9,M,47.6,M,,*52 $GPGSA,A,2,26,29,31,,,,,,,,,,8.02,7.96,1.00*0D $GPGSV,4,1,13,02,23,045,,04,36,294,22,05,08,084,,12,21,104,*76 $GPGSV,4,2,13,14,14,247,,20,00,130,,21,20,183,,23,04,337,*75 $GPGSV,4,3,13,25,62,099,,26,24,293,25,29,89,271,19,31,57,277,22*76