Connect a GPS to the Raspberry PI

Connect a GPS to the Raspberry PI

After seeing an article about the Raspberry PI in the atmosphere with the PI in the Sky Project, I’ve decided why not try it ? Since I don’t have access to a telemetry board, I’ve decided to go ahead with off the shelf components. Well, this is the first step

Portuguese version

First, how to track the Raspberry PI with the GPS


Raspberry PI B/B+ (I’ve used both)

1 GPS (I’ve tried with two GPS – both working perfectly):


To connect the GPS to the Raspberry PI we’re going to use the GPIO. The following table shows the GPIO PINs for RPI version B where to connect the GPS Pins.

Raspberry PIN GPS PIN
2 – 5v VIN/VCC
8 – TX RX
10 – RX TX

Note: The  TX and RX switch when connecting to GPS:: RX -> TX e TX -> RX

Here’s RPI B pinout





  GPS GY-NEO6Mv2 to PI wiring


Some images of the GPS wiring to  Raspberry PI version B



To connect the GPS EM-406A I had to buy a  JST SH Jumper 6  cable – with 6 pins to fit in the GPS  – although we only need 4 pins.


GPS EM-406A wiring



I’ve used the RPI version B+ for this GPS. No explanation – just because at this time the B+ was the only one I had available.  Both PINs in RPI B or B+ are the same and the wiring is also the same. The only thing changing is the GPIO  of RPI  B+.


Power on the PI

As soon you have a prompt available, it is necessary to change some configurations.

The UART port, by default, is used for logins. We need to free it for the GPS.

Edit the file /boot/cmdline.txt and change:

dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait


dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait

After that, change the /etc/inittab file and comment a line so it do not spawn a login console:

Comment the following line (It should be the last one):

#T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100

After this changes, reboot the PI

sudo reboot

After the reboot, install the GPS applications

sudo apt-get install gpsd gpsd-clients

Execute gpsd (The GPS daemon)

sudo gpsd /dev/ttyAMA0 -F /var/run/gpsd.sock

Now, let’s try the GPS (place it outside so it can work better)

cgps -s

And after some seconds you should get some signal

Now you should have GPS in your PI. But lets not stop here and create a map of the RPI locations.

Update a map with the current RPi location

It wont do us any good if the have a GPS in the RPI and not create some fancy map with it.

Create a map with the GPS coordinates

By installing the GPS applications, we also get some python modules. Let’s use those to get some info from the GPS.

My solution was with a Web server, the python app reporting the coordinates to a text file and a Web application in another computer (or in the PI – more on that later) getting them and creating a map with PHP and Ajax.

In the PI, install a Web server. I’m going for nginx

sudo apt-get install nginx

Configure nginx

This is the first time I’m working with nginx. I decided to use it because is much less resource hungry than apache.

For security concerns, lets change nginx listening port. Instead of 80, lets use 2121 (for example).

sudo vi /etc/nginx/sites-available/default

Change the line

#listen 80;


listen 2121;

Change document_root

In the line that says root, change to

root /home/pi/gps/www;

Note: Don’t forget to create the directories gps/www

mkdir -p gps/www

Since nginx runs with the  www-data group, lets add the PI (or your user) to the group because of permissions – we want nginx to be able to read and create files.

sudo gpasswd -a pi www-data

Note: You need to logout and login again

Change the permissions so that any file created by nginx can be read by the group – any created file by nginx will belong to the www-data group – (setgid)

chmod g+s www

Restart nginx

sudo /etc/init.d/nginx restart

Note: Do not forget that, as configured, to connect to nginx, you must use the 2121 port:




Install Python module gpxpy

git clone
cd gpxpy
sudo python build
sudo python install

All the code is in my  bitbucket account (with Portuguese comments).

The directory contains a file named .This file is to keep in the RPI, wherever you want, but you must later create a www directory (accessible by nginx) – where the this script will put the file coords.txt that will contain the current coordinates.

To run it, just:

sudo python

Before running it, please make sure the GPS is connected and working. You can use the above commands to test it: cgps -s

For informations about gpsd Python modules, visit the page.

# Feiticeir0 - Bruno Santos (
# date: 10.12.2014
# Python script store the current coordinates
# so they can be read by a remote PHP script

from sys import argv
import gps
import gpxpy
import gpxpy.gpx

#Listen on port 2947 of gpsd
session = gps.gps("localhost", "2947") | gps.WATCH_NEWSTYLE)

while True:
		report =
			# wait for a 'TPV' report and display the current time
			# to see all report data, uncomment the line below
			#print report
		if report['class'] == 'TPV':
			# Open a file to store the coordinates
			coords = open ("www/coords.txt","w+")
	except KeyError:
	except KeyboardInterrupt:
	except StopIteration:
		session = None
		print "GPSD has terminated"

Computer (the one that’s going to display the map)

In this computer is necessary to install a Web server (with PHP support) and Internet access so it can display the maps.

In the bitbuck account you can find all the necessary files.

It’s only necessary to change 2 lines, one on each of the following files::

– getcoords.php : change the line $rpi_host to your RPI IP

– pingPHP.php :  change the line $host again, to match your RPI IP

Update: With my last version, there’s no need to change any file. Just put your RPI IP in the input box and press “Track”

<!DOCTYPE html>
		<title>RPI Tracking</title>
		<meta charset="utf-8">
		<link rel="stylesheet" href=""/>
			#map {
				margin-left: auto;
				margin-right: auto;
				width: 1500px;
				height: 900px;
				float: right;
			input[type="button"] {
				border: 1px solid #b5c1d5;
				background-color: #94aecf;
				color: white;
				height: 28px;
				border-radius: 3px;
				width: 100px;
		<script src=""></script>
		<div id="map"></div>
		<script src=""></script>
			var map ='map').setView([39.823006667, -7.490308333], 14);
			mapLink = '<a href="">OpenStreetMap</a>';
			L.tileLayer ('http://{s}{z}/{x}/{y}.png', {
				attribution: '&copy; ' + mapLink + ' Contributors',
				maxZoom: 18,
			var ongoing = 1;
			$(document).ready(function() {
				$('#startTrack').click(function() {
					if (ongoing == 1) {
						ongoing = 0;
					else {
						ongoing = 1;
				function startTrackingRPI() {
					var oldlon = 0.00;	//define old coords
					var oldlat = 0.00;	//define old coords
					//get status from robot
					//get IP Address
					var ip = $('#ip').val();
					// red offline - green online
					function getStatus() {
						//new image
						if (!ip.length == 0) {
							//alert (ip);
							var online = 'images/online.png';
							var offline = 'images/offline.png';
							//gerar url
							$.post ('pingPHP.php',{ip:ip},processaDados);
							function processaDados (data) {
								//alert ('data ' + data);
								if (data == 1)
					// 3s em 3s verifica

					//colocar marcador
					function getCoords() {
						function processCoords(data) {
							//TODO: Verificar se dados devolvidos sao validos
							//TODO: Verificar se nao houver conectividade, nao tentar inserir marcador
							var coords = data.split(",");
							//verificar se sao iguais as que ja temos
							//para nao colocar marcadores no mesmo local
							if ((coords[0] != oldlon) && (coords[1] != oldlat)) {
								//se sao diferentes, inserir marcador
								// insert a new marker
								var marker = L.marker([coords[0],coords[1]]).addTo(map);
								//atribuir estas coordenadas antigas
								oldlon = coords[0];
								oldlat = coords[1];
					// 4s em 4s verifica coordenadas - diminir para aumentar detalhe do mapa
					var newCoord = getCoords();
					//var marker = L.marker([39.823366667, -7.490128333]).addTo(map);
		<!-- <textarea id="coordstoput" rows="2" cols="30"></textarea> -->
		<img src="images/offline.png" id="status" style="vertical-align:middle;">&nbsp;<input type="text" size="15" maxlenght="15" placeholder="RPI Endereço IP" name="ip" id="ip">
		<input type="button" value="Track" id="startTrack">

Auxiliary files:


	$host = $_POST['ip'];
	if (!$socket = @fsockopen($host,2121))
		echo 0;
		echo 1;


	$rpi_host = $_POST['ip'];
	$port = ":2121";
	$url = $rpi_host.$port.'/coords.txt';

	$ch = curl_init();
	$timeout = 5;
	curl_setopt($ch, CURLOPT_URL, $url);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
	curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
	$data = curl_exec($ch);
	//return preg_replace("/r|n/", "", $data);
	echo preg_replace("/r|n/", "", $data);

Everything is configured now.

IMPORTANT NOTE: It may seem that the map is not updating, but it is. Just zoom out with the mouse and center the map at your location. Since it is necessary to put some coordinates when creating the map, I’ve placed the map at my home town (Castelo Branco – Portugal). I will update this in a new version. (Thank you Nuno Oliveira)

In a browser, execute the file RPITracking.html and wait for the markers to start appearing with your RPI position.

In this version I used markers instead of a line. I get it that after a while it gets messy and confused… In a newer version I’ll use a line.

Here’s the result I’ve tried this morning (Image from the previous version)

GPS Track

Use the RPI to show the map (in update)

Instead of using another computer to get the RPI coordinates and show them on the map, we can use the RPI to do this job – and access it with a browser –

Change nginx

Install  PHP
sudo apt-get install php5-fpm

Next, edit the ficheiro /etc/nginx/sites-available/default

sudo vi /etc/nginx/sites-available/default

and uncomment the following lines:

location ~ .php$ {
       fastcgi_split_path_info ^(.+.php)(/.+)$;
       # # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
       # fastcgi_pass;
       fastcgi_pass unix:/var/run/php5-fpm.sock;
       fastcgi_index index.php;
       include fastcgi_params;

Save and restart nginx

sudo /etc/init.d/nginx reload

To work, the files you would put in the computer, put them in the RPI and you should get the map working.  As you have configured the nginx document_root, that’s were you need  to put the files. A side note – and since everything is in the same place, there was no need to use CURL – on PHP – to get the coordinates, but it will do no warm and it will work.

PI Mobility

For all this to work, the RPI is needed to work on batteries.

In my case, I’m using LIPO batteries  – with 2h and 30m duration – which is not bad…for now is enough .

My material was (Portuguese stores):

Lithium Ion Polymer Battery – 3.7v 1200mAh

– PowerBoost 500 Basic – 5V USB Boost @ 500mA from 1.8V+ (increasing 3.7v from the battery to 5v for the PI)

– USB/DC Lithium Polymer battery charger 5-12V (3.7/4.2v cells) (to recharge the batteries)

With the mini-usb cable, you connect all to the RPI. I believe is not the most efficient way to power the RPI, but after a few days reading, it’s all I came up. I’m not an electronics expert and if there’s some one out there with a better idea, please come forward !


Before I’ve settled with this solution, I’ve tried with AA batteries – 1.5v – a 6 AA batteries adapter and a Pololu 5v Step-up/Step-down voltage regulator 5v to control the voltage (6 * 1.5v = 9v). But, don’t know what went wrong, and only got 40m…

RPI alimentado com pilhas

Saving power

We can save about 20mA (more or less) turning off the PAL/HDMI output (assuming we’re not going to use it) .

To do so, just add the following line to the RPI boot (Usually, adding the following line to  /etc/rc.local)

/opt/vc/bin/tvservice -off

tip via


This project (for now) as the downside that, in the computer used to view the maps, an Internet connection is necessary – because of the maps. There’s another reason that, both computers must be in the same network. I’m exploring XBees. The models I’ve purchased have 1.5km range – updates after some testing.

Hope you like it. Errors or mistakes, please advise !