GPS w/ uBlox neo6mv2

English version.

Zu wissen, wie man GPS Rohdaten von einem entsprechenden Modul ausliest, und diese dann auch verarbeiten kann, kann in vielen Situationen von Vorteil sein. Verwendung findet ein GPS Modul in Multicoptern, Tracker oder um Daten an bestimmten Orten zu sammeln, um nur ein paar Beispiele zu nennen. Interessant wird es, wenn man GPS Daten im Zusammenhang mit anderen Sensordaten verwertet. Etwa die Beschleunigungswerte, gemessen durch eine entsprechende Sensorik, eines Kraftfahrzeuges.

setup

Die Funktionsweise

GPS ist ein Akronym für Global Positioning System. Um Weltweit die Position eines Gerätes bestimmen zu können, benötigt man nicht nur eben dieses Gerät, sondern auch Satelliten.

Entwickelt wurde das GPS vom US-Militär, bevor es seit den 1990er Jahren auch für zivile Zwecke eingesetzt wird. Der Vorteil dieser Positionsbestimmung ist, dass GPS Signal nur empfangen werden können, jedoch nicht gesendet werden. So kann man navigieren, ohne dass es Gegenspieler mitbekommen.

Die Satelliten, welche sich mit einer Relativgeschwindigkeit von etwa 3.9km/s zur Erde bewegen senden ein codiertes Radiosignal aus, welches ihre Umlaufbahnparameter und die Sendezeit beinhält. Dieses wird vom Empfänger verarbeitet, woraus dann die Position auf der Erde errechnet wird. Für eine genaue Bestimmung der Position benötigt man mindestens drei Satelliten (3 Punkte im Raum bestimmen die Position theoretisch exakt). Da die Empfängergeräte jedoch keine hochgenaue Uhr verbaut haben, wird mindestens ein weiterer Satellit benötigt, um die Uhrzeit genau bestimmen zu können.

Weitere Daten, etwa Richtungsangaben (Kompass) oder die Geschwindigkeit können über den Dopplereffekt bestimmt werden. Dabei ist die Signalverzerrung die ausschlaggebende Größe, welche ein Maß für die Daten ist.

Für mehr Informationen zum GPS: Wikipedia.

uBlox Neo6m v2

Die Überschrift lässt erahnen, welches Modul ich nutze. Es ist im Vergleich zu anderen GPS Receivern eines der günstigsten, lässt dennoch in den unterschiedlichen GPS-Modes eine Genauigkeit von bis zu 2.5 Meter laut Hersteller zu. Die GPS-Daten habe ich mit einem professionellem GPS-Gerät bei schönem Wetter auf einer Wiese abgeglichen, und bin zu dem Ergebnis gekommen, dass der eine Meter nicht unbedingt eingehaten wird. Maximal ergab sich eine Abweichung von etwa 6 Metern. Für den Preis von unter 10€ eine beträchtliche Leistung.

module

Die eigentliche Bezeichnung des Moduls lautet GY-GPS6MV2, NEO-6M bezieht sich lediglich auf den Chip, und nicht auf die gesamte Platine. Der NEO-6M Chip arbeitet mit einer maximalen Spannung von 3.6V, da sich auf der Platine aber ein Spannungswandler befindet, darf man den VCC-Pin mit 5V versorgen. Wichtig ist, dass die Signal-Pins (UART) auf keinen Fall mit mehr als 3.6V in Berührung kommen dürfen, denn es befindet sich kein Levelshifterauf dem Board.

Um das Modul dennoch mit einem 5V-Arduino nutzen zu können bedarf es entweder einem Levelshifter-Modul oder man stellt diesen durch einen einfachen Widerstands-Spannungsteiler her. Wie man das macht folgt etwas weiter unten. Laut Datenblatt sollte das GPS-Modul auch funktionieren, wenn man an VCC nur 3.3V (3.6V) anlegt, doch in diesem Fall habe ich nie verwertbare Daten vom Modul erhalten.

Der Aufbau

Wie bereits erwähnt, benötigt man für den Aufbau neben dem Controller und dem GPS Modul einen 2.2kΩ Widerstand und einen 1.0kΩ Widerstand.

shematic

Die Verkabelung erfolgt nach folgender Tabelle:

Arduino GPS LCD
+5V Vcc Vcc
GND GND GND
A4 SDA
A5 SCL
3 RX (mit Levelshifter)
4 TX

Der Grund, warum der TX-Pin (Transmit) keinen Widerstand benötigt ist, weil dieser das Signal an das Arduino sendet. Gegensätzlich dazu gibt das Arduino +5V an Pin 3 aus. Diese Spannung würde dem GPS nicht sonderlich gut tun, deshalb muss sie auf das logische Level des Moduls herabgesetzt werden.

Liquid Crystal Display via I2C

Bei dem Display handelt es sich um das sehr weit verbreitete HD44780 Liquid Crystal Display. Ihm wird lediglich ein Rucksack-Modul verpasst, welches die I2C-Befehle in HD44780er-Befehle umwandelt. Optional kann man das Display auch weglassen, das Programm muss man dafür nicht verändern. Wer will, kann die überflüssigen Zeilen aber auch löschen.

Display

Das Display-Modul nutzt wie bereits erwähnt den I2C-Bus. Er wird genau wie der letzte von mir vorgestellte Display angeschlossen:

  • SDA: A4
  • SCL: A5
  • Vcc: +5V
  • GND: Ground

Backpack

Der Code

Das Programm befindet sich auf GitHub.

Im Verzeichnis gps_basic findet man das Programm, welches die Grundidee beinhaltet. Das zweite, gps_tracker, behandle ich etwas später. Um die Vorgänge im Programm zu verstehen, muss man zuerst den Aufbau des Protokolls kennen, das vom GPS an das Arduino seriell gesendet wird. Im Ordner lib findet man die von mir verwendeten und funktionierenden Programmbibliotheken.

Zur Bestimmung der Position nutze ich die Daten des $GPGLL-Protokolls, und um zu erfahren, mit wie vielen Satelliten das GPS im Moment verbunden ist lese ich die Daten des $GPGSA-Protokolls.

$GPGLL

Dieses Protokoll sendet die geografische Position (Längen- und Breitengrade) und die Zeit. Der Aufbau sieht mit Beispielswerten wie folgt aus:

$GPGLL,4704.46496,N,01241.63682,E,110152.00,A,D*29

Man erkennt, dass die Daten mit einem Komma getrennt sind, was der Idee des csv-Formatsentspricht. Die Rohdaten ergeben nach der Verarbeitung folgende Nutzdaten:

  • 4704.46496,N: 47° 04.46496′ Nord
  • 01241.63682,E: 12° 24.63682′ Ost
  • 110152.00: Uhrzeit nach UTC+00
  • A: Daten validiert.
  • D*29: Checksumme

Die Koordinaten werden im Format Grad & Dezimalminuten ausgegeben. Wem geografische Kooridnaten nichts oder nur wenig sagen: Wikipedia. Grundsätzlich gilt aber, dass die Erde in Kugelkooridinaten mit Längengrade (Longitude) und Breitengrade (Latitude) unterteilt wird. Die geografische Länge hat eine Spannweite von -180° (Westen) bis + 180° (Osten), ausgehend von Greenwich in Großbritanien. Die geografische Breite reicht von -90° (Süden) bis +90° (Norden). Die Hauptachse ist in diesem Fall der Äquator.

$GPGSA

Dieses Protokoll enthält Daten über den GPS-Mode, die Anzahl der aktiv verbundenen Satelliten und über die Verringerung der Genauigkeit (Dilution of Precision [DOP]).

$GPGSA,A,3,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,1.7,1.1,1.3*55

  • A,3: Automatische Wahl, 3D
  • ID: ID des Satelliten (11 Satelliten maximal)
  • 1.7: PDOP
  • 1.1: HDOP
  • 1.3: VDOP
  • *55: Checksumme

Eine Liste aller GPS-NMEA Sätze gibt es hier.

Data Parser

Will man die Daten vom GPS einfach nur über das Arduino zum seriellen Monitor durchschleusen, so genügt es am Beginn des Programms die Kommentar-Slashes der Zeile 13 zu entfernen.

#define DATA_PARSER

Da dieser Task aber sehr langweilig ist, gehen wir gleich weiter zum eigentlichen Code.

Serielle Daten aufnehmen

In der loop() wird gewartet, bis serielle Daten vom GPS (gps ist hier eine Instanz von SoftwareSerial) verfügbar sind. Sobald das Dollarzeichen auftaucht werden die Daten in einen Buffer geschrieben. Taucht das Sternsymbol auf, welches Teil der Checksumme ist, wird das Lesen beendet und die Daten werden zur Weiterverabeitung – processRawData() – frei gegeben.

while (gps.available())
{
	GPSRX = gps.read();

	if (GPSRX == '$')
	{
		RXbuffer = F("$");
		enableRead = true;
	}
	else if (GPSRX == '*')
	{
		processRawData(RXbuffer);
		enableRead = false;
	}
	else if (enableRead)
	{
		RXbuffer += GPSRX;
	}
}
Datenverarbeitung

In der Funktion processRawData() wird zuerst geprüft, ob die Daten des $GPGLL-Protokolls validiert sind. Ist dies der Fall, so wird der Inhalt über splitString() aufgeteilt. Da die Grade jedoch in einem Strang mit den Minuten kommen muss man eine kleine Division einfügen. Hier nutze ich die Eigenschaften von Integer- und Floatvariablen (Gleitkommazahlen löschen).

buffer = (splitString(splitString(data, ',', 1), '.', 0)).toInt();
latitude.degrees = buffer / 100;
latitude.minutes = (buffer - latitude.degrees * 100) + splitString(splitString(data, ',', 1), '.', 1).toFloat() / 100000;

Die selbe Vorgehensweise habe ich auch bei den Breitengraden, der Zeit und dem anderen Protokoll, allerdings mit den angepassten Positionen im Protokoll.

Das war bereits alles, was es zu verarbeiten gibt. So einfach kann man GPS-Daten für sich nutzen.

User Interface

Die Aktualisierungsgeschwindigkeit der Daten sowohl am Display als auch am seriellen Monitor wird vom GPS vorgegeben. Das Modul hat eine maximale Aktualisierungsrate von 1Hz, und diese Zeit nutze ich auch.

In der setUI()-Funktion werden die Daten auf ein einheitliches Format gebracht, sodass sie immer gleich am Display und im seriellen Monitor dargestellt werden. Zusätzlich hat man am Beginn des Programms die Wahl, ob man die Daten seriell im csv-Format ausgeben will. Dazu genügt es die Definitionen entsprechend auszukommentieren.

//#define CSV
//#define CSV_MS_EXCEL
#define NO_CSV

Der Unterschied zwischen ’normalen‘ csv und MS Excel csv ist, dass Excel die Daten mit Strichpunkten anstatt einem Beistrich trennt, und der Dezimalpunkt kein Punkt, sondern ein Komma ist. Das folgende Bild zeigt die drei möglichen Ausgaben.

ui_modes

Die Anzahl der Satelliten und die Warnung der nicht-validierten Daten wird nur im NO_CSV Modus ausgegeben.

GPS Tracker

Da jetzt klar ist was dahinter steckt, kann man einen Schritt weiter gehen und sich mit Hilfe eines SD-Kartenmoduls einen GPS-Tracker erstellen. Den Display habe ich komplett weggelassen, da es mir in erster Linie darum geht, Geodaten während dem Gehen zu sammeln. Der Display würde hier nur unnötig Energie verbrauchen.

gps_tracker

Als SD-Kartenleser kommt das Modul von Catalex zum Einsatz, welches ich bereits hierbeschrieben habe, allerdings nutze ich es in diesem Tutorial mit dem ’normalen‘ SPI, und nicht mit SoftSPI. Der Grund ist, dass ich kein weiteres SPI-Gerät nutze, das durch das SD-Modul gestört werden könnte. Für mehr Infos dazu: Einfach den zugehörigen Beitrag lesen.

sd_module

Der elektrische Aufbau

Im Grunde sieht der Aufbau aus wie oben, lediglich mit LCD– und Card Reader++. Die Verbindung der Pins folgt der Tabelle:

Arduino GPS Card Reader
+5V Vcc Vcc
GND GND GND
3 RX (mit Levelshifter)
4 TX
10 CS
11 MOSI
12 MISO
13 SCK

shematic_tracker

Der Code

Das Programm liegt im Verzeichnis gps_tracker auf GitHub. Die Grundbausteine sind gleich geblieben, ich habe es lediglich um die Funktionen der SD Karte erweitert. Das arduino schreibt nun immer wenn das GPS Daten schreibt diese auf die Karte und zeigt sie auch, optional, am seriellen Monitor an.

File csvFile = SD.open(F("log.csv"), FILE_WRITE);
csvFile.println(csvData);
csvFile.close();

Sind die Daten fehlerhaft oder ist keine Satellitenverbindung vorhanden, so werden keine Daten geschrieben. Dies ist etwas nachteilig, da man nicht weis, ob das Programm auch ordnungsgemäß ausgeführt wird. Man könnte auch hier eine LED verbauen, die anzeigt, ob die Daten validiert wurden, oder ob eine Verbindung zu den Satelliten besteht. Aber mein Tutorial soll ja auch nur als Denkanstoß dienen. Ich würde mich freuen, wenn coole Lösungen für diverse Probleme auftauchen.

Nur noch eine kleine Anmerkung: Wenn man zusätzlich Sensordaten senden will, dann erkennt man schnell die Vorteile des csv-Dateiformats. Man hängt diese einfach hinten an.

Falls sonst noch Fragen aufgetaucht sind, der Code ist gut auskommentiert und ein Kommentar ist immer erwünscht.

 

Advertisements

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s