Category Archives: BerryGPS

New Product: OzzMaker SARA-R5 LTE-M GPS + 10DOF

We have released a new product ; OzzMaker SARA-R5 LTE-M GPS + 10DOF

OzzMaker LTE-M GPS IMU 10DOF

This is an all in one module which can provide location tracking and LTE-M services such as data, text and SMS to your project. It comes in the same form factor as a Raspberry Pi Zero, which makes it nice and compact when used with a Raspberry Pi Zero.

It is a feature packed board, which includes the  following components;

  1. LTE-M cellular modem
  2. GPS  receiver (including assisted GPS)
  3. Accelerometer
  4. Gyroscope
  5. Magnetometer (Compass)
  6. Barometric/pressure sensor (altitude)
  7. Temperature sensor

 

This board includes a SARA-R510M8S  module from uBlox,  this module can be used for LTE-M connectivity and includes an integrated GPS receiver. Using both these features together results in obtaining a GPS fix in seconds, using Assisted GPS.

The below video shows a comparison between assisted and normal GPS.

  • Asisted GPS takes 19secs to get a fix
  • Normal GPS takes 8min 22Sec to get a fix


 

Typically, a GPS module can take a few minutes to get  Time To First Fix(TTFF), or even longer if you are in  built up areas.  This is because the Almanac needs to be downloaded from  satellites before a GPS fix can be acquired and only a small portion of the Almanac is sent in each GPS update.

Assisted GPS speeds this up significantly by  downloading  ephemeris, almanac, accurate time and satellite status over the network, resulting in faster TTTF, in a few seconds. This is very similar how to GPS works on a smartphone.

 

 

Accessing GPS via I2C on a BerryGPS-IMU

The BerryGPS-IMU uses a  CAM-M8C U-Blox GPS module, this GPS module includes a DDC interface which is fully I2C compatible.

This guide will show how to read NMEA sentences from the GPS module via I2C, using a Raspberry Pi. This leaves the serial interface on the Raspberry Pi free for other uses. You can also use a QWIIC connector to connect the BerryGPS-IMU to the Raspberry Pi

We will create a virtual node where we will send the NMEA sentences, we will then configure GPSD to read this virtual node.

 

Caveat: There is a well know I2C clock stretching bug on the Raspberry Pi which will be encountered when trying to communicate with the  uBlox module via native I2C.  This results with random characters appearing in the retrieved data.
We will cover two methods of how to get around this;

Method 1 – Include a lot of checks to ignore NMEA sentences with corrupt data.
The overall amount of NMEA sentences which will be corrupt is very small(20 out of 1,000), which still makes this method very usable.

Method 2 – Using bit banging to overcome the clock stretching bug. This will result in zero errors, but requires I2C to be disabled on the Raspberry Pi.

 

I2C Jumpers

By default, the GPS module on the BerryGPS-IMU is not connected to the I2C bus.  This can be fixed by placing a solder blob on the jumpers JP11 and JP10 on the back of the PCB.

BerryGPS-IMU I2C GPS

 

Method 1 – Using native I2C

Enable I2C on your Raspberry Pi and set the speed to 400Khz.

pi@raspberrypi ~ $ sudo nano /boot/config.txt

Near the bottom, add the following line

dtparam=i2c_arm=on,i2c_arm_baudrate=400000

Now reboot.

You can confirm if you see the GPS module by using the below command.

pi@raspberrypi ~ $ sudo i2cdetect -y 1

 

Here is the output when a BerryGPS-IMU is connected. 42 is the GPS module

pi@raspberrypi ~ $ sudo i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: — — — — — — — — — — — — —
10: — — — — — — — — — — — — 1c — — —
20: — — — — — — — — — — — — — — — —
30: — — — — — — — — — — — — — — — —
40: — — 42 — — — — — — — — — — — — —
50: — — — — — — — — — — — — — — — —
60: — — — — — — — — — — 6a — — — — —
70: — — — — — — — 77

 

Create the python script which will read the data via I2C from the GPS module

pi@raspberrypi ~ $ nano i2c-gps.py

Copy in the below code;

#! /usr/bin/python
import time
import smbus
import signal
import sys
BUS = None
address = 0x42
gpsReadInterval = 0.03
def connectBus():
    global BUS
    BUS = smbus.SMBus(1)
def parseResponse(gpsLine):
  if(gpsLine.count(36) == 1):                           # Check #1, make sure '$' doesnt appear twice
    if len(gpsLine) < 84:                               # Check #2, 83 is maximun NMEA sentenace length.
        CharError = 0;
        for c in gpsLine:                               # Check #3, Make sure that only readiable ASCII charaters and Carriage Return are seen.
            if (c < 32 or c > 122) and  c != 13:
                CharError+=1
        if (CharError == 0):#    Only proceed if there are no errors.
            gpsChars = ''.join(chr(c) for c in gpsLine)
            if (gpsChars.find('txbuf') == -1):          # Check #4, skip txbuff allocation error
                gpsStr, chkSum = gpsChars.split('*',2)  # Check #5 only split twice to avoid unpack error
                gpsComponents = gpsStr.split(',')
                chkVal = 0
                for ch in gpsStr[1:]: # Remove the $ and do a manual checksum on the rest of the NMEA sentence
                     chkVal ^= ord(ch)
                if (chkVal == int(chkSum, 16)): # Compare the calculated checksum with the one in the NMEA sentence
                     print gpsChars
def handle_ctrl_c(signal, frame):
        sys.exit(130)
#This will capture exit when using Ctrl-C
signal.signal(signal.SIGINT, handle_ctrl_c)
def readGPS():
    c = None
    response = []
    try:
        while True: # Newline, or bad char.
            c = BUS.read_byte(address)
            if c == 255:
                return False
            elif c == 10:
                break
            else:
                response.append(c)
        parseResponse(response)
    except IOError:
        connectBus()
    except Exception,e:
        print e
connectBus()
while True:
    readGPS()
    time.sleep(gpsReadInterval)

 

You can test the script with python i2c-gps.py. If you have a GPS fix, you will get output similar to below.

pi@raspberrypi ~ $ python i2c-gps.py
$GNRMC,071423.00,A,3254.18201,S,15243.27916,E,0.252,,110721,,,A*72
$GNVTG,,T,,M,0.252,N,0.466,K,A*3C
$GNGGA,071423.00,3254.18201,S,15243.27916,E,1,10,1.01,29.0,M,22.6,M,,*63
$GNGSA,A,3,30,14,07,17,13,19,15,,,,,,1.66,1.01,1.31*17
$GNGSA,A,3,73,74,72,,,,,,,,,,1.66,1.01,1.31*1C
$GPGSV,3,1,12,01,21,124,,06,13,009,20,07,11,048,21,13,47,286,34*70
$GPGSV,3,2,12,14,54,143,27,15,25,253,31,17,84,132,28,19,70,328,31*7D
$GPGSV,3,3,12,21,09,139,,24,08,225,18,28,,,29,30,49,052,26*45
$GLGSV,3,1,10,65,14,243,16,71,00,330,,72,15,287,21,73,39,099,22*65
$GLGSV,3,2,10,74,53,176,19,75,16,227,,80,00,070,,83,24,149,*64

 

Create a virtual node, this is where we will send the NMEA sentences from the GPS module to.

pi@raspberrypi ~ $ mknod /tmp/gps p

 

Now run the python script and redirect the output to the virtual node we just created.
We will also use stdbuf so the output from the script is sent to the virtual node one line at a time. Without this, the output is buffered and only sent to the virtual node when the buffer is full.

pi@raspberrypi ~ $ stdbuf -oL python i2c-gps.py > /tmp/gps
Configure GPSD to use the virtual buffer

No you can configure GPSD to point to the virtual buffer.

pi@raspberrypi ~ $ sudo nano /etc/default/gpsd

Look for
DEVICES=””
and change it to
DEVICES=”/tmp/gps”

Restart GPSD so the new settings take effect.

pi@raspberrypi ~ $ sudo systemctl restart gpsd.socket

 

You can now start using your GPS module with your Raspberry Pi

Method 2 – Bit Bang I2C

Confirm that you do not have I2C enabled. There should be no i2c devices under /dev/

pi@raspberrypi ~ $ ls /dev/i2c*
ls: cannot access ‘/dev/i2c*’: No such file or directory

 

If you do have I2C enabled, the above command will return a file under the /dev/ directory.
You can disable I2C in /boot/config.txt

pi@raspberrypi ~ $ sudo nano /boot/config.txt

 

Look for the below line and comment it out by adding a “#” in front.

dtparam=i2c_arm=on

Now reboot.

Create the python script which will read the data by bit banging I2C from the GPS module

pi@raspberrypi ~ $ nano i2c-gps.py

 

Copy in the below code;

import time
import signal
import sys
import pigpio
address = 0x42
gpsReadInterval = 0.03
SDA=2
SCL=3
pi = pigpio.pi()
pi.set_pull_up_down(SDA, pigpio.PUD_UP)
pi.set_pull_up_down(SCL, pigpio.PUD_UP)
pi.bb_i2c_open(SDA,SCL,100000)
def handle_ctrl_c(signal, frame):
        pi.bb_i2c_close(SDA)
        pi.stop()
        sys.exit(130)
#This will capture exit when using Ctrl-C
signal.signal(signal.SIGINT, handle_ctrl_c)
def readGPS():
    c = None
    response = []
    while True: # Newline, or bad char.
        a=pi.bb_i2c_zip(SDA, [4, address, 2, 6, 1])  # Bit bang I2C read. 2 = Start, 6 = read, 1= How many bytes to read
        c = ord(a[1])
        if c == 255:
            return False
        elif c == 10:
            break
        else:
            response.append(c)
    gpsChars = ''.join(chr(c) for c in response)  #Convert list to string
    print gpsChars
while True:
    readGPS()
    time.sleep(gpsReadInterval)

 

Create a virtual node, this is where we will send the NMEA sentences from the GPS module to

pi@raspberrypi ~ $ mknod /tmp/gps p

 

Now run the python script and redirect the output to the virtual node we just created.
We will also use stdbuf so the output from the script is sent to the virtual node one line at a time. Without this, the output is buffered and only sent to the virtual node when the buffer is full.

pi@raspberrypi ~ $ stdbuf -oL python i2c-gps.py > /tmp/gps
Configure GPSD to use the virtual buffer

No you can configure GPSD to point to the virtual buffer

pi@raspberrypi ~ $ sudo nano /etc/default/gpsd

Look for
DEVICES=””
and change it to
DEVICES=”/tmp/gps”

Restart GPSD so the new settings take effect.

pi@raspberrypi ~ $ sudo systemctl restart gpsd.socket

 

You can now start using your GPS module with your Raspberry Pi

GPS Position accuracy and how to tell if you have a good fix?

One of the main contributing factors to GPS position accuracy is the geometric configuration (the position in the sky) of the satellites used to obtain a position.
The best position fix is given when a satellite is directly overhead and another three are equally spaced around the horizon.

This aspect is called the ‘geometry’ of the system and is measured as DOP (Dilution of Precision).

The influence of satellite geometry on imprecision is demonstrated in the image below. When both satellites are widely separated (figure left) the position error (area in red) is smaller. If the satellites are close to one another (right figure), then the area of error is more spread out. This is valid when the uncertainty for determining the position,
known as the Range Error (R-E: yellow and blue areas), is the same for both satellites. R (R1 and R2) refers to the
measured distance of the satellites to the user (pseudorange).

HDOP overlap
Satellite precision error

 

There are a number of different DOP elements which can be used, we will focus on HDOP (Horizontal-DOP).

The HDOP can be seen when using gpsmon. The image below has HDOP highlighted;gpsmon HDOP

The HDOP can also be found in the GSA sentence.  Below it is shown as 1.3;

$GPGSA,A,3,04,05,,09,12,,,24,,,,,2.5,1.3,2.1*39

A HDOP value of 1 or below would give you an accuracy of about 2.5 meters.

When in mountainous areas, forests and urban canyons, you can experience high HDOP values as  some of the available satellites will be obstructed. The satellites used will be closer together creating a large area of error as the signal from each satellite have a larger intersect.

Low accuracy in a city
Low accuracy in a city

Out on the open sea, you should be able to see a low HDOP value as the satellites used would be spread out and has less area of a intersect.

HDOP
Good accuracy

Using u-Center to connect to the GPS on Raspberry Pi

u-Center from u-Blox is a graphical interface which can be used to monitor and configure all aspects of the GPS module on a BerryGPS-IMU or BerryGPS-GSM.

u-Center from uBlox
U-Center

 

u-Center only runs on Windows. It can connect over the network to a Raspberry Pi.  This will require us to redirect the serial interface on the Raspberry Pi to a network port using ser2net.

Pi Setup

Do an upt-get update and then install ser2net;

pi@raspberrypi ~ $ sudo apt-get update
pi@raspberrypi ~ $ sudo apt-get install ser2net

Edit the ser2net config file and add the serial port redirect to a network port. We will use network port 6000

pi@raspberrypi ~ $ sudo nano /etc/ser2net.conf

And add this line at the bottom;

6000:raw:600:/dev/serial0:9600 NONE 1STOPBIT 8DATABITS XONXOFF LOCAL -RTSCTS

This is a breakdown of the syntax for the line above;
TCP port : connection type : timeout : serial port : serial port speed : serial options

you can now start ser2net using;

pi@raspberrypi ~ $ sudo ser2net

And you can use the below command to check if it is running by seeing if the port is open and assigned to the ser2net process;

pi@raspberrypi ~ $sudo netstat -ltnp | grep 6000

If it is running, you should see something similar to the output below;

check result of ser2net

Windows PC Setup and Connecting to the GPS module

You can download u-Center from here.

Once installed, open u-Center. You will get the default view as shown below.  No data will be shown as we are not connected to a GPS.

u-Center default view

The next step, is to create a new network connection and connect to the GPS which is connected to our Raspberry Pi. You can create a new connection under the Receiver and then Network connection menus.

u-Center connect to Raspberry Pi
In the new window, enter the IP address of the Raspberry Pi and specify port 6000. This is the port we configured in ser2net on the Raspberry Pi.
u-Center Raspberry Pi Address

This is what the default view looks like when connected and the GPS has a fix.u-Center connected

 

u-Center

Below I will list of the more useful windows/tools within u-Center.
You can also click on the images below for a larger version.

Data View
This window will show you the longitude, latitude, altitude and fix mode. It will also show the HDOP, which is the Horizontal Dilution of Precision.  Lower is better, anything below 1.0 means you have a good signal.

u-Center Data View
u-Center Data View

Ground Track
This window will show you where the satellites are as well as what time.

u-Center Ground Track
u-Center Ground Track

Skye View
Sky view is an excellent tool for analyzing the performance of antennas as well as the conditions of the satellite observation environment.

u-Center Sky View
u-Center Sky View

Deviation Map
This map shows the average of all previously measured positions.

u-Center Deviation Map
u-Center Deviation Map

Continue reading Using u-Center to connect to the GPS on Raspberry Pi

Control the GPIO of a Raspberry Pi using SMS from a mobile phone

In this guide we will show you how to control the GPIO pins of a Raspberry pi by send a SMS to the Raspberry Pi from a mobile phone.

 

For this guide, the GSM modem we are using to receive the SMS is the  BerryGPS-GSM.

On the software side, we will be using Gammu, which is specifically designed to control  phones and GSM modules. It also has a daemon which will monitor the GSM modem for incoming SMSs.

We will configure Gammu to trigger a python script when a new SMS is received. We will use the contents of the SMS to control what happens in Python

LEDs are used here as an example, but you can do anything you like Eg. Open a garage door, turn on some lights, etc..

 

Wiring

Raspberry PI GPIO SMS

 

We will be using the three bottom right GPIO pins on the Raspberry Pi header. These are GPIO 16, 20 and 21.
Each is connected to a different color LED as shown above. The
The resistors used are 330 Ohm  and the GND pin (shorter pin) of the LEDs is connected to the GND power rail.

 

Setup

Install Gammu and python bindings;

pi@raspberrypi ~ $ sudo apt-get update
pi@raspberrypi ~ $ sudo apt-get install gammu-smsd python-gammu

Edit the config file;

pi@raspberrypi ~ $ sudo nano /etc/gammu-smsdrc

Find the below lines and add port and speed.
For the BerryGPS-GSM, use /dev/ttyACM1 for port and at115200 for speed

port = /dev/ttyACM1
connection = at115200

At the bottom of the file, add the line below. This is the python script which will run when a new SMS is received.

RunOnReceive = sudo python /home/pi/smsReceived.py

We will do a quick test. Restart the gammu service so the new config takes effect;

pi@raspberrypi ~ $ sudo /etc/init.d/gammu-smsd restart

Send a test SMS to a mobile number. The mobile number below is an example, you will need to update this;

pi@raspberrypi ~ $ echo “This is a test from a Raspberry Pi” | /usr/bin/gammu –sendsms TEXT +614123456789

 

Python Script

This python script will run every time a new SMS is received.

pi@raspberrypi ~ $ nano ~/smsReceived.py

Copy in the below code

import RPi.GPIO as GPIO
import time
import sys
import re

RED_LED =  21
GREEN_LED =  20
BLUE_LED =  16
GPIO.setmode(GPIO.BCM)
filename=str(sys.argv[1])                               #Gammu will pass the filename of the new SMS as an argument
complete_filename="/var/spool/gammu/inbox/"+filename    #we create the full path to the file here
GPIO.setup(RED_LED , GPIO.OUT)
GPIO.setup(GREEN_LED , GPIO.OUT)
GPIO.setup(BLUE_LED , GPIO.OUT)
sms_file=open(complete_filename,"r")
#read the contents of the SMS file
message=sms_file.read(160) #note that a not-parted SMS can be maximum 160 characters
#search the contents and perform an action. Rather than use 'find',
# we will use regular expression (re) so we can ignore case.
#Most smartphones will have the first letter capitalised
if re.search('red', message, re.IGNORECASE):
        GPIO.output(RED_LED , GPIO.HIGH)
        time.sleep(2)
        GPIO.output(RED_LED , GPIO.LOW)
elif re.search('green', message, re.IGNORECASE):
        GPIO.output(GREEN_LED , GPIO.HIGH)
        time.sleep(2)
        GPIO.output(GREEN_LED , GPIO.LOW)
elif re.search('blue', message, re.IGNORECASE):
        GPIO.output(BLUE_LED , GPIO.HIGH)
        time.sleep(2)
        GPIO.output(BLUE_LED , GPIO.LOW)

GPIO.cleanup()

To troubleshoot you can view the syslog

pi@raspberrypi ~ $ tail -f /var/log/syslog

Using a button and the GPIO on a Raspberry Pi to send a SMS

In this guide we will show you how to send a SMS using a button connected to the GPIO pins of a Rasberry Pi Zero.

 

For this guide, the GSM modem we are using to send the SMS is the  BerryGPS-GSM.

On the software side, we will be using Gammu, which is specifically designed to control  phones and GSM modules.

Python will be used to monitor some buttons connected to GPIO pins and Gammu python bindings will be used to send a SMS.

Buttons are used here as an example, but you can use anything to trigger the SMS, E.g. Temperature sensor, water level sensor, light sensor, etc..

We have includes some LEDs so we can see when the buttons are pressed.

Wiring

Raspberry Pi LED button

We will be using the three bottom right GPIO pins on the Raspberry Pi header. These are GPIO 16, 20 and 21.
Each is connected to a button and different color LED as shown above. The internal pull-down resisters will be used on these GPIO.
3.3v and GND are connect to the power rails on the breadboard.
The resistors used are 330 Ohm  and the GND pin (shorter pin) of the LEDs is connected to the GND power rail.

Continue reading Using a button and the GPIO on a Raspberry Pi to send a SMS

Real-time GPS tracking with a Raspberry Pi

In this guide, we will show how to do real time tracking, use a BerryGPS-GSM and initialstate.com 

Initialstate has some great tools to easily stream data from a Raspberry Pi to Initialstate.com and show this data within a dashboard using tiles.  We will send longitude,  latitude and  speed. And use a BerryGPS-GSM to get these values and upload them via 3G.

 

You will need to create an account on Initialstate.com and then grab your access key which can be found under “My Settings”

BerryGPS-GSM setup

If you are using a BerryGPS-GSM, you can follow this guide to get the GPS working and get your Pi to connect to via 3G using PPP.

The above guide also shows how to make your Pi connect to the carrier network automatically when booted. You will need this if you plan to perform remote tracking(E.g. Asset tracking).

Install required libraries

pi@raspberrypi ~ $ sudo apt-get install python-pip
pi@raspberrypi ~ $ sudo pip install pynmea2
pi@raspberrypi ~ $ sudo pip install ISStreamer

 

Main Python Script

Here we will create the main script which will stream the GPS data to Initialstate.com.
The code below creates a separate thread which is used to monitor the serial port. This is needed because we have a pause in the main loop. The pause is there to limit how much data we upload over 3G.
If we did everything in the same thread during the pause, the serial buffer would fill up (it is FIFO) and when we get the next value from the buffer, it will be old by a few seconds. This happens every loop and eventually the data will be minutes or hours behind.

The access key below is not a valid key, it is just an example. You will need to replace it with your own key.

pi@raspberrypi ~ $ nano ~/GPStracker.py

#! /usr/bin/python
from gps import *
from time import *
import threading
import datetime
from ISStreamer.Streamer import Streamer
gpsd = None  #Setup global variable 
#Setup the Initialstate stream, give it a bucket name and the access key
streamer = Streamer(bucket_name="GPS_Tracker20190713", bucket_key="GPS_Tracker20190713", access_key="ist_W4aHj0eCkMjCD8JVpp3AMsKomys8NaD")

class GPSDcollector(threading.Thread):
   def __init__(self, threadID):
      threading.Thread.__init__(self)
      self.threadID = threadID
      global gpsd #bring it in scope
      gpsd = gps(mode=WATCH_ENABLE) #Start GPSD
      self.running = True #Start running this thread
   def run(self):
      global gpsd
      while gpsdThread.running:
        gpsd.next() 
        
if __name__ == '__main__':
  gpsdThread = GPSDcollector(1) # create a thread to collect data
  try:
    gpsdThread.start() # start it up
    while True:
        print 'GPS ' , gpsd.utc,'--> CPU time->',datetime.datetime.now().time() ,
        if (gpsd.fix.longitude<>0) and (gpsd.fix.longitude<>'nan'): #Only upload data if it is valid
          streamer.log("Location", "{lat},{lon}".format(lat=gpsd.fix.latitude,lon=gpsd.fix.longitude))
          streamer.log("speed",gpsd.fix.speed)
        print '  lat    ' , gpsd.fix.latitude,
        print '  lon   ' , gpsd.fix.longitude,
        print '  speed ', gpsd.fix.speed
        sleep(5)
  except (KeyboardInterrupt, SystemExit): #when you press ctrl+c
    print "\nKilling Thread..."
    gpsdThread.running = False
    gpsdThread.join() # wait for the thread to finish what it's doing
  print "Done.\nExiting."
  

 

Start the script automatically on boot

If you are doing remote monitoring, you would want the script to run on boot. To do this, we will create a small script which will start the main python program.

pi@raspberrypi ~ $ nano ~/GPStrackerStart.sh

copy in the below lines;

#!/bin/bash
sleep 15
python /home/pi/GPStracker.py &

The pause above is there to give the Pi time to boot and connect via PPP.

Make the script executable;

pi@raspberrypi ~ $ chmod +x ~/GPStrackerStart.sh

We will use cron to start the script every time the Pi boots;

pi@raspberrypi ~ $ crontab -e

Add the below line to the bottom

@reboot /home/pi/GPStrackerStart.sh &

Other Guides and Tutorials for BerryGPS-GSM

New Product: BerryGPS-GSM – Global 3G/2G cellular modem with GPS + SIM

We have released a new product:

BerryGPS-GSM – Global 3G/2G cellular modem with GPS + SIM

This is an all in one module which can provide location tracking and GSM services such as data, text and SMS to your project. It comes in the same form factor as a Raspberry Pi Zero, which makes it nice and compact when used with a Raspberry Pi Zero.

 

 

The two main components that make this board great are;

  • uBlox CAM-M8 GPS module (Same GPS found on BerryGPS-IMU)
  • uBlox SARA-U201 GSM for GSM connectivity, which has global coverage.

Both of these modules working together results in obtaining a GPS fix in secs, using Assisted GPS.

 

BerryGPS-IMU used by Plastic Monkeys in CanSat competition

Along with other sponsors, we are happy to congratulate Plastic Monkeys team for placing 3rd  (out of over 70 teams taking part) in the CanSats in Europe Polish Competition.

A CanSat is a type of sounding rocket payload used to teach space technology. It is similar to the technology used in miniaturized satellites.

In CanSat competitions, the payload is required to fit inside the volume of a typical soda can (66mm diameter and 115mm height).

A BerryGPS-IMU was used to provide location tracking for this project.

 

 

How to save GPS data to a file using Python

Below is an example python script which will save GPS data (time, Lon, Lat, speed and sats in view) to a file.

The gpsd client libraries  will be used to get the data from GPSD. We will be using the TPV class to get time, latitude, longitude and speed.

We can get the number of satellites in view by getting the length of the satellites object.

This page shows how to get gpsd up an running on a Raspberry Pi

Every time the script is run, it will create a new file beginning with the current date and time.

In this example, I am writing in a csv format, where each GPS attribute is separated by a comma.

#! /usr/bin/python
from gps import *
import time, inspect

f = open(time.strftime("%Y%m%d-%H%M%S")+'_GSPData.csv','w')
gpsd = gps(mode=WATCH_ENABLE|WATCH_NEWSTYLE)
print 'GPStime utc\t\t\tlatitude\tlongitude\tspeed\tsats in view' # '\t' = TAB to try and output the data in columns.
f.write("GPStime utc,latitude,longitude,speed,sats in view\n")
try:
    while True:
        report = gpsd.next() #
        if report['class'] == 'TPV':
            GPStime =  str(getattr(report,'time',''))
            lat = str(getattr(report,'lat',0.0))
            lon = str(getattr(report,'lon',0.0))
            speed =  str(getattr(report,'speed','nan'))
            sats = str(len(gpsd.satellites))
            print  GPStime,"\t",
            print  lat,"\t",
            print  lon,"\t",
            print  speed,"\t",
            print  sats,"\t"
            f.write(GPStime + ',' + lat +',' + lon + ',' + speed + ',' + sats + '\n')
            time.sleep(1)
except (KeyboardInterrupt, SystemExit): #when you press ctrl+c
    print "Done.\nExiting."
    f.close()