Raspberry Pi: Connecting a GPS

Tuesday 1st August 2017 2:23am

GPS or Global Positioning System is a network of orbiting satellites that send precise details of their position in space back to earth. The signals are picked up by GPS receivers, such as navigation devices and are used to calculate the exact location.

Wiring the GPS device to the Raspberrry Pi:

When you take delivery of your Adafruit Ultimate GPS Breakout you will need to solder the pins onto the PCB and optionally the battery holder used for the real-time clock. Adafruit’s Ultimate GPS Breakout requires between 3-5 volts, this can be connected to the Raspberry Pi either using a USB to TTY cable or using the UART (Universal Asynchronous Receiver/Transmitter) serial connections of the GPIO (General Purpose Input Output) pins. I didn’t want to sacrifice one of the USB ports so I decided to go with the latter.

Using a CD ROM audio cable we can remove each cable using a dress making pin to push back the tabs and re-arrange the cable colours to correspond with the pin lay-out of both the Raspberry Pi and Adafruit’s Ultimate GPS Breakout board.

Adafruit GPS

Adafruit GPS

Next we need to hook-up the GPS device to the Raspberry Pi; for this we will need a 5 volt power supply and ground along with both the transmit (TXD) and receive (RXD) pins (please see Connecting Hardware ). Connect to Board pins 4, 6, 8 and 10 (BCM pins 5V, GND, GPIO 14 (UART_TXD) and GPIO 15 (UART_RXD)) we also need to flip the white and the green cables so that the Transmit from the GPS becomes the Receive of the Raspberry Pi and vice-versa the Receive from the GPS becomes the Transmit on the Raspberry Pi:

GPS Wiring

GPS Wiring

Now that we have everything wired together we need to setup the software. By default the UART is enabled to allow you to connect a terminal window and login, this needs to be disabled to free it up for the GPS module. Type the following into SSH shell command prompt:

sudo nano /etc/init/ttyAMA0.conf

Once the file has opened we need to edit each command line with # symbols which notifies the operating system to treat these lines as human comments and ignores them.

Before:

# ttyAMA0 - getty
#
# This service maintains a getty on tty2 from the point the system is
# started until it is shut down again.

description     "Start getty on ttyAMA0"
author          "Scott James Remnant <scott@netsplit.com>"

start on ((xbmc-started FIRST_RUN!=no or started delay-start-20) and runlevel [23])

stop on runlevel [01456]

respawn
exec /sbin/getty -L ttyAMA0 115200 vt100

After:

# ttyAMA0 - getty
#
# This service maintains a getty on tty2 from the point the system is
# started until it is shut down again.

#description     "Start getty on ttyAMA0"
#author          "Scott James Remnant <scott@netsplit.com>"

#start on ((xbmc-started FIRST_RUN!=no or started delay-start-20) and runlevel [23])

#stop on runlevel [01456]

#respawn
#exec /sbin/getty -L ttyAMA0 115200 vt100

Once you have made these changes press CTRL+X and select Y to save the changes.

Install GPSD

GPSD is an open source project which provides a daemon which streams GPS data via a TCP socket, allowing you to communicate with a whole host of different GPS devices (not just this one):

sudo apt-get install gpsd gpsd-clients python-gps

Run gpsd

GPSD needs to be started up, using the following command:

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

Test gpsd

There is a simple GPS client which you can run to test everything is working:

cgps -s

It may take a few seconds for data to come through, but you should see a screen like this:

GPSD

GPSD

Now we can put it all together to create an application to collect the above information using Python. Copy the code below and save as ‘gps_controller.py’:

Python Code:

# GPS script to work with Adafruit Ultimate GPS Breakout component
# connected to Raspberry Pi using GPIO serial connection ttyAMA0
# Requires gpsd socket to be running in the background
# i.e 'gpsd /dev/ttyAMA0 -F /var/run/gpsd.sock'
# Date: 03 March 2015
# written by: Phantom Raspberry Blower

import os

from gps import *
import time
import threading
import math


class GpsController(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.gpsd = gps(mode=WATCH_ENABLE)  # starting the stream of info
        self.running = False

    def run(self):
        self.running = True
        while self.running:
            # grab EACH set of gpsd info to clear the buffer
            self.gpsd.next()

    def stopController(self):
        self.running = False

    @property
    def fix(self):
        return self.gpsd.fix

    @property
    def utc(self):
        return self.gpsd.utc

    @property
    def satellites(self):
        return self.gpsd.satellites


class GpsClass():
    def __init__(self):
        gpsc = GpsController()
        try:
            gpsc.start()
            time.sleep(3)
            self.current_time = str(gpsc.utc)
            self.latitude = str(gpsc.fix.latitude)
            self.longitude = str(gpsc.fix.longitude)
            self.altitude = str(round(gpsc.fix.altitude * FEET_PER_METER,
                                      1)) + 'ft'
            self.speed = str(gpsc.fix.speed) + 'mph'
            self.heading = str(gpsc.fix.track) + 'deg (true)'
            self.climb = str(gpsc.fix.climb) + 'ft/min'
        except:
            self.message('Something wicked happened :(', 'Error!')
            raise
        finally:
            gpsc.stopController()
            gpsc.join()

    def get_location(self):
        try:
            gpsc.start()
            time.sleep(3)
            dict = {'utc': str(gpsc.utc),
                    'latitude': gpsc.fix.latitide,
                    'longitude': gpsc.fix.longitude,
                    'altitude': gpsc.fix.altitude,
                    'speed': gpsc.fix.speed,
                    'heading': gpsc.fix.track,
                    'climb': gpsc.fix.climb}
            gpsc.stopController()
            gpsc.join()
            return dict
        except:
            return 'Error getting location'

if (__name__ == "__main__"):
    dict = GpsClass.get_location()
    FEET_PER_METER = 3.2808399

    current_time = dict['utc']
    latitude = dict['latitude'],
    longitude = dict['longitude']
    altitude = dict['altitude']
    speed = dict['speed']
    heading = dict['heading']
    climb = dict['climbing']

    print 'GPS Details:\n'
    print '\tCurrent Time: %s' % str(current_time)
    print '\tLatitude:     %s' % str(latitude)
    print '\tLongitude:    %s' % str(longitude)
    print '\tAltitude:     %s ft.' % str(round(altitude * FEET_PER_METER,
                                               1))
    print '\tSpeed:        %s mph.' % str(speed)
    print '\tHeading:      %s deg (true)' % str(heading)
    print '\tClimb:        %s ft./min.' % str(climb)

Using the above code you can either run as a stand-alone application:

sudo python gps_controller.py

Or you can import this module into another Python project:

from gps_controller import GpsClass
dict = GpsClass.get_location()
print "Latitude: %s, Longitude: %s" % (str(dict['latitude']), str(dict['longitude']))

That’s all Folks!!!

FB Like & Share