GPS Tracking mit dem Raspberry Pi

Erstellt am 25. Juli 2015 von At2oo1

raspberry.tips
raspberry.tips - Raspberry.Tips - Projekte, Tutorials und News rund um den Mini-Computer Raspberry Pi

Bereits vor einiger Zeit hatte ich mit GPS Modulen für den Raspberry Pi experimentiert, heute wollte ich die verschiedenen Projekte mal zusammenbringen und einen echten Raspberry Pi GPS-Tracker mit Akku Betrieb bauen. Als kleines Addon soll alle paar Minuten ein Bild erzeugt werden welches mit den jeweils aktuellen GPS Daten versehen wird. Dieses Raspberry Pi GPS Projekt kann entweder im Auto als GPS-Tracker mit Bild Funktion oder auch auf Wanderungen oder Fahrradtouren zur Dokumentation der Tour mit einem Akku verwendet werden.

Material

Folgendes Material habe ich verwendet

Verkabelung des GPS Modul

Die Pin Nummern und Bezeichnungen der GPIO-Leiste des Raspberry Pi 2 findet ihr in der GPIO PIN Übersicht.

Verkabelung des Moduls

  • VCC wird mit 3,3V versorgt und kommt daher beim RasPi an PIN1 (+ 3,3 V)
  • GND ist natürlich auch beim RasPi GND und kommt daher an PIN6 (GND)
  • RX ist da wir Seriell verwenden beim  RasPi TX PIN8 (TX)
  • TX ist da wir Seriell verwenden beim RasPi RX PIN10  (RX)

PPS verkabeln

  • PPS Signal für die aktuelle Uhrzeit an PIN12 (GPIO18)

Das PPS-Signal müsst ihr am PIN3 des GPS-Chip oder am markierten Widerstand durch anlöten eines kleinen Kabels abholen

Meine Verkabelung / Aufbau

Einrichtung GPS Tracker auf dem Raspberry Pi

Uhrzeit via GPS beziehen

Da wir beim mobilen Einsatz unsers RasPi keine Internetverbindung zum beziehen der aktuellen Uhrzeit haben und ich in diesem Fall auch keine RTC-Modul für den Bezug der Zeit via Funk habe setzen wir die Uhrzeit via GPS. Dafür ist es notwendig das PPS Signal eures Moduls an den GPIO Pin Nr. 12 (GPIO18) weiterzureichen.

Sobald das PPS Signal anliegt können wir den PPS Treiber, welcher das Signal verarbeiten kann, aktivieren. Das erledigen wir via Device Tree Overlay in der Datei config.txt mit dem Editor Nano.

sudo nano /boot/config.txt

Fügt ans Ende folgende Zeile an und speichert mit STRG+X, Y und Enter.

dtoverlay=pps-gpio,gpiopin=18

Zum Testen des PPS Signals (euer PI braucht dafür eine Sichtverbindung zu mindestens zwei GPS Satelliten) installieren wir noch die PPS Tools.

sudo apt-get -y install pps-tools
sudo reboot

Nach einem Reboot solltet ihr nach folgendem Befehl eine Ausgabe erhalten

sudo ppstest /dev/pps0

Das ist das PPS Signal welches der Pi vom GPS Modul bekommt.

trying PPS source "/dev/pps0"
found PPS source "/dev/pps0"
ok, found 1 source(s), now start fetching data...
source 0 - assert 1437308973.404467560, sequence: 454 - clear  0.000000000, sequence: 0
source 0 - assert 1437308974.404486750, sequence: 455 - clear  0.000000000, sequence: 0
source 0 - assert 1437308975.404505732, sequence: 456 - clear  0.000000000, sequence: 0

Beendet die Ausgabe mit STRG+C.

Da wir nun die Zeit vom GPS via PPS Signal am Raspberry Pi haben müssen wir noch eine Angepasste Version des Zeitdienstes NTP installieren. Falls ihr eure Zeitzone noch nicht eingestellt habt erledigt das über folgenden Befehl (vermutlich befindet ihr euch wie ich in UTC +1 Europe/Berlin).

sudo dpkg-reconfigure tzdata

Um an die Sourcen des NTP Dienstes zu kommen fügen wir das passende Repository zu unserer sources.list hinzu und aktualisieren die Paket Liste. Das ist notwendig da das normale NTP Paket keine PPS Zeitquellen unterstützt.

sudo sh -c 'echo "deb-src http://mirrordirector.raspbian.org/raspbian/ wheezy main contrib non-free rpi" >> /etc/apt/sources.list'
sudo apt-get update

Dann holen wir uns die Build Dependencies und den Quellcode des NTP Dienstes

cd ~
sudo apt-get -y build-dep ntp ntpdate
sudo apt-get -y source ntp

Der Source Code wurde in das Home des Benutzers pi abgelegt, bei mir ist das momentan ntp-4.2.6.p5+dfsg. Ich wechsle in das erstellte Quellcode Verzeichnis nach debian.

cd ntp-4.2.6.p5+dfsg/debian/

Hier finden wir eine Datei rules welche wir bearbeiten um die fehlende Funktion für PPS zu aktivieren

sudo nano rules

Wir müssen in der Datei den configure Aufruf mit –enable-ATOM ergänzen, sucht am Besten mit STRG+W nach configure und fügt am Ende des Aufrufs –enable-ATOM hinzu, die Zeile davor müsst ihr noch mit einem ” \”ergänzen. Bei mir sieht das Ergebnis wie folgt aus. Speichern mit STRG+X, Y und Enter.

        ./configure CFLAGS='$(CFLAGS)' CPPFLAGS='$(CPPFLAGS)' LDFLAGS='$(LDFLAGS)' \
                --prefix=/usr \
                --enable-all-clocks --enable-parse-clocks --enable-SHM \
                --disable-debugging --sysconfdir=/var/lib/ntp \
                --with-sntp=no \
                --with-lineeditlibs=edit \
                --without-ntpsnmpd \
                --disable-local-libopts \
                --enable-ntp-signd \
                --disable-dependency-tracking \
                --with-openssl-libdir=/usr/lib/$(DEB_HOST_MULTIARCH) \
                --enable-ATOM

Um kompilieren zu können müssen wir in der Datei changelog noch die Version von NTP um eine Nummer erhöhen. Wir verwenden wieder nano

sudo nano changelog

und ändern in der Ersten Zeile 4.2.6.p5+dfsg-2 zu 4.2.6.p5+dfsg-3 und speichern mit STRG+X, Y und Enter.

Jetzt kompilieren wir den NTP Dienst mit, das dauert eine Weile (ca. 30 Minuten),  nach Abschluss des Vorgangs müssen wir nur noch das neu erstellte NTP-Paket installieren

cd ..
sudo dpkg-buildpackage -b

cd /home/pi
sudo dpkg -i ntp_4.2.6.p5+dfsg-3+deb7u4_armhf.deb

Nun haben wir auf unserem System den NTP Dienst mit aktivierter ATOM Funktion um via PPS gelieferte Daten verarbeiten zu können.

Die Konfiguration von NTP folgt als nächstes, diese wird in einer zentralen Konfigurationsdatei vorgenommen. Ihr findet die Datei in /etc/ntp.conf, ich verwende zum Bearbeiten der Datei wieder den Editor Nano.

sudo nano /etc/ntp.conf

Wir möchten nun dem NTP Dienst sagen das zwei zusätzliche Zeitquellen vorhanden sind, zum einen die via PPS angebundene und zum anderen die Ausgabe des GPSD. Hierzu fügen wir der Konfiguration folgende Zeilen hinzu.

# pps-gpio /dev/pps0
server 127.127.22.0 minpoll 3 maxpoll 3 prefer
fudge 127.127.22.0 refid PPS
fudge 127.127.22.0 flag3 1  # enable kernel PLL/FLL clock

# gpsd clock
server 127.127.28.0 minpoll 3 maxpoll 3 prefer
fudge 127.127.28.0 refid GPS
fudge 127.127.28.0 time1 +0.130

Die anderen eingetragen NTP Server habe ich durch voranstellen einer Raute (#) entfernt da ich im offline Betrieb GPS als Zeitquelle verwenden will und für den online betrieb die UK Pool Server

#server 0.debian.pool.ntp.org iburst
#server 1.debian.pool.ntp.org iburst
#server 2.debian.pool.ntp.org iburst
#server 3.debian.pool.ntp.org iburst

pool uk.pool.ntp.org minpoll 5 maxpoll 5 iburst

Speichert wieder mit STRG+X, Y und Enter.

Zum testen ob alles geklappt hat müsst ihr einmal den Dienst, folgender Befehl gibt uns dann die konfigurierten Zeitquellen aus.

sudo service ntp restart
ntpq -p

Falls euer Raspberry Pi eine IP-Adresse via DHCP erhält und euer DHCP Server zusätzlich auch ein NTP-Server ist (wie meine FritzBox) müsst ihr die automatische Konfiguration via DHCP abschalten.

sudo nano /etc/dhcp/dhclient.conf

Innerhalb der Datei entfernt ihr hinter request folgenden Inhalt: ntp-servers

Zusätzlich lösche ich noch die folgenden Dateien um zu verhindern das noch eine alte Konfiguration angezogen wird und starte meinen Pi neu.

sudo rm -rf /etc/dhcp/dhclient-exit-hooks.d/ntp
sudo rm -f /var/lib/ntp/ntp.conf.dhcp
sudo reboot

GPS Einrichten

Wichtig ist das wir als erstes die Serial Funktion aktivieren, öffnet hierzu raspi-config

sudo raspi-config

Navigiert in die “Advanced Options” auf “Serial” und beantwortet die Frage “Would you like a login shell to be accessible over serial? ” mit No. Nun können wir den GPS Dienst, welcher für uns die Kommunikation mit dem Modul übernimmt, installieren

sudo apt-get -y install gpsd gpsd-clients python-gps gpsbabel
sudo reboot

Wir konfigurieren den Dienst nun direkt, hierzu rufen wir den Konfigurationsdialog auf

sudo dpkg-reconfigure gpsd
  • Die erste Frage nach dem Automatischen Start bestätigen wir mit NO
  • Die zweite Frage ob USB-Geräte verwenden werden soll beantworten wir wieder mit NO
  • Die Frage nach dem GPS Device beantworten wir durch Eingabe des Geräts  /dev/ttyAMA0
  • Die Rückfrage nach den Parametern tragen wir folgendes ein -n 
  • Den gpsd control socket belassen wir so wie er vorgeschlagen wird

Zum aufzeichnen der Daten verwende ich ein Python Script welches via gpspipe die GPS Daten jede Sekunde speichert. Das ist notwendig um den GPS-Dienst und das Tracking nach start des Raspberry Pi jeweils verzögert zu starten, das vermeidet Probleme.

sudo nano /home/pi/gps-tracker.py

Die Datei bekommt folgenden Inhalt (das Script ist einfach gestaltet und hat noch keine Fehlerbehandlung).

#!/usr/bin/env python
import subprocess
import time
from datetime import datetime as dt

# Terminate existing gpsd instances, start gpsd and sleep a few seconds
subprocess.call('sudo killall gpsd', shell=True)
subprocess.call('sudo /usr/sbin/gpsd /dev/ttyAMA0 -F /var/run/gpsd.sock', shell=True)
time.sleep(30)

# Refresh the local time
subprocess.call('sudo service ntp restart', shell=True)
time.sleep(3)

#output file name with actual date
filename = "/home/pi/gpstrack-" + dt.now().strftime("%Y%m%d-%H%M%S") + ".txt"

# start gpspipe and output the GPS Data as NMEA to file
subprocess.call('gpspipe -d -l -r -o '+ filename +' ', shell=True)

Nach dem Speichern wird diese ausführbar gemacht.

sudo chmod +x /home/pi/gps-tracker.py

Dann fügen wir einen Autostart für das Script hinzu.

sudo nano /etc/rc.local

Am Ender der Datei, vor exittragen wir folgenden Befehl ein

/bin/sleep 15  & /home/pi/gps-tracker.py &

Nach einem Reboot wird nun mit etwas Verzögerung unter /home/pi/ eine Datei mit dem Namen gpstrack-<zeitstempel>.txt geschrieben.

GPS Daten in Google Maps anzeigen

Wir haben nun fleißig Daten gesammelt, diese liegen uns im im Roh-Format als NMEA Daten vor. Um diese zb. in Google Maps importieren und anzuzeigen müssen wir diese in das KML Format umwandeln. Das erledigt das Tool gpsbabel für uns.

gpsbabel -i nmea -f /home/pi/<eure datei> -o kml -F /home/pi/gpstrack.kml

Die Datei könnt ihr dann z.B. via WinSCP von eurem Raspberry Pi holen, geht eure IP-Adresse und die Logindaten ein und klickt auf Login

Kopiert die Datei durch Drag and Drop auf euren Rechner. Die KML Dateien könnt ihr dann zum Beispiel mit Google Earth oder in My Google Maps importieren, bearbeiten und abspeichern.

Für den KML Import für Google Maps

  1. Öffnet hierzu https://www.google.com/mymaps
  2. Ihr müsst euch ggf Anmelden, sagt dann “Neue Karte erstellen
  3. Ihr erhaltet eine Leere Karte mit einer leeren Ebene, bennent die Ebene nach euren Wünschen um
  4. Klickt dann für die Ebene auf Import und wählt die KML File von eurem Rechner
  5. Die Karte könnt ihr dann mit euren Freunden und bekannten teilen

Für den KML Import für Google Earth

  1. Die Datei kann einfach via Drag&Drop hinzugefügt werden

Bilder

Die Bilder via Raspberry Pi CAM erstellen wir wie üblich via “raspistill”, vorab müsst ihr eure Kamera allerdings via “sudo raspi-config” mit “5 Enable Camera” aktivieren. Zusätzlich installiere ich die Software Imagemagick welche es mir erlaubt in das aufgenommene Bild die aktuellen GPS Daten als Text zu integrieren.

sudo apt-get install imagemagick

Zusätzlich installieren wir das Tool “exiftool”, anhand dessen fügen wir dem aufgenommenen Bild Meta-Informationen im JPEG Header hinzu, das ganze nennt sich auch Geotagging und macht es uns später einfacher die Bilder in einem Map Anwendung dem Aufnahmeort zuzuordnen.

wget http://www.sno.phy.queensu.ca/~phil/exiftool/Image-ExifTool-9.99.tar.gz
gzip -dc Image-ExifTool-9.99.tar.gz | tar -xf -

cd Image-ExifTool-9.99/

perl Makefile.PL
make -j4 test
sudo make -j4 install

Ein kleine Script nimmt nun alle paar Minuten ein Bild auf, dabei werden vorher kurz die aktuellen Koordinaten, die Höhe und die Geschwindigkeit abgefragt und dann via convert als Text ins Bild geschrieben. Zusätzlich erhält das aktuelle Bild den Aufnahmeort und weitere Informationen via EXIF in den JPEG Header.

nano /home/pi/Bild.sh

Das Script erhält folgenden Inhalt (hat noch Experimentier-Status, das werde ich bei Gelegenheit noch verbessern).

#!/bin/bash
while true; do

  sleep 1m

  tpv=$(gpspipe -w -n 10 | grep -m 1 TPV)
  latitude=$(echo $tpv | python -c 'import sys, json; print json.load(sys.stdin)["lat"]')
  longitude=$(echo $tpv | python -c 'import sys, json; print json.load(sys.stdin)["lon"]')
  altitude=$(echo $tpv | python -c 'import sys, json; print json.load(sys.stdin)["alt"]')
  speed=$(echo $tpv | python -c 'import sys, json; print json.load(sys.stdin)["speed"]')
  time=$(echo $tpv | python -c 'import sys, json; print json.load(sys.stdin)["time"]')

  FILE="/home/pi/bild_$(date +%Y%m%d_%H%M%S).jpg"

  sudo rm -f /var/tmp/bild.jpg

  sudo raspistill -o /var/tmp/bild.jpg -w 1280 -h 720 -q 7 -ex auto

  cmd="sudo convert /var/tmp/bild.jpg -gravity SouthEast -stroke '#000C' -pointsize 24 -strokewidth 2 -annotate 0 'Lat: $latitude Lon: $longitude Alt: $altitude Speed: $speed' -stroke none -fill white -annotate 0 'Lat: $latitude Lon: $longitude Alt: $altitude Speed: $speed' $FILE"

  eval $cmd

  sudo exiftool -overwrite_original_in_place '-gpstimestamp<${DateTimeOriginal}+1:00' '-gpsdatestamp<${DateTimeOriginal}+1:00' -GPSLongitudeRef="E" -GPSLongitude="$longitude" -GPSLatitudeRef="S" -GPSLatitude="$latitude" -gps:GPSAltitudeRef=0 -GPSAltitude="$altitude" "$FILE"

done

Speichert mit STRG+X, Y und Enter. Jetzt machen wir das Script noch ausführbar.

sudo chmod +x Bild.sh

Ans Ende eurer GPS Start-Datei  für den GPS Dienst könnt ihr nun noch folgenden Befehl anhängen, dieser sorgt dafür das die Bild-Aufnahme mit gestartet wird (sudo nano /home/pi/gps-tracker.py)

#start shell script for create pictures every 2 min
subprocess.call('sh Bild.sh', shell=True)

Bei mir wurden auf einer Testfahrt folgende Bilder aufgezeichnet, diese müsstet ihr natürlich wieder mit WinSCP auf euren Rechner holen (wundert euch nicht das die Schrift auf dem Kopf steht, ich hatte einen Parameter der Cam falsch gesetzt).