The Lab Book Pages

An online collection of electronics information

http://www.labbookpages.co.uk

Dr. Andrew Greensted
Last modified: 18th November 2009

Hide Menu


Valid XHTML Valid CSS
Valid RSS VIM Powered
RSS Feed Icon

This site uses Google Analytics to track visits. Privacy Statement

Page Icon

GPS Module

Gumstix make a GPS enabled add-on board, this page give some details in using it.


The GPS Module

The GPSStix expansion includes a GPS module.

Gumstix GPS and Audio Module

Gumstix GPS and Audio Module

The GPS Module uses the Standard UART (STUART). This can be accessed via /dev/ttyS2.

> stty -F /dev/ttyS0 9600 -icrnl
> cat /dev/ttyS2
$GPZDA,140123.00,17,02,2009,00,00*6C
$GPRMC,140124.00,A,5356.73777,N,00103.23273,W,0.567,92.13,170209,,,A*4D
$GPVTG,92.13,T,,M,0.567,N,1.052,K,A*06
$GPGGA,140124.00,5356.73777,N,00103.23273,W,1,06,1.43,22.3,M,47.4,M,,*7B
$GPGSA,A,3,13,32,23,12,11,31,,,,,,,2.87,1.43,2.48*04
$GPGSV,2,1,08,20,79,083,13,13,23,193,28,17,45,250,25,32,51,074,28*7E
$GPGSV,2,2,08,23,49,175,30,12,07,344,27,11,33,146,29,31,22,059,31*7B
$GPGLL,5356.73777,N,00103.23273,W,140124.00,A,A*7A
$GPZDA,140124.00,17,02,2009,00,00*6B
$GPRMC,140110.00,A,5356.73782,N,00103.23277,W,0.39

GPS Codes

The data output from the GPS modules is tagged with codes defined by the NMEA standard. The table below gives a description of some of these. There is a lot more information available from http://home.mira.net/~gnb/gps/nmea.html.

Code Description
GPGGA Global Positioning System Fix Data (This is probably the most interesting)
GPGLL Geographic Position, Latitude / Longitude and time
GPGSA GPS DOP (Dilution of Precision) and active satellites
GPGSV GPS Satellites in view
GPRMC Recommended minimum specific GPS/TRANSIT data
GPVTG Track Made Good and Ground Speed
GPZDA UTC Date / Time and Local Time Zone Offset

GPS Data Reading Program

The data sent by the GPS module has a well defined structure so reading it in isn't too complicated. Below are three c files to demonstrate one approach. gps.h and gps.c give a set of handy functions for parsing the GPGGA data. gpsTest.c shows how to read from the GPS data from the serial port.

A simple make file is included to help you get the code compiled.

File: gps.h
typedef struct {
   int degrees;
   int mins;
   int minFrac;
   char quadrasphere;
} DMData;

typedef struct {
   DMData latDM;
   DMData longDM;
   int quality;
   int numSats;
   int checkSum;
} GPSData;

void printGPSData(GPSData *gpsData);
int hexStr2Int(char* str, int sPos, int numChars);
int extractNum(char* str, int sPos, int ePos, int *valPtr);
int decodeGPSString(char *str, GPSData *gpsData);
File: gps.c
#include <stdio.h>
#include "gps.h"

// $GPGGA,hhmmss.ss,ddmm.mmm,a,dddmm.mmm,b,q,xx,p.p,a.b,M,c.d,M,x.x,nnnn

// hhmmss.ss   UTC of position
// ddmm.mmm    Latitude of position
// a           N or S, latitutde hemisphere
// dddmm.mmm   Longitude of position
// b           E or W, longitude hemisphere
// q           GPS Quality indicator (0=No fix, 1=Non-differential GPS fix, 2=Differential GPS fix, 6=Estimated fix)
// xx          Number of satellites in use
// p.p         Horizontal dilution of precision
// a.b         Antenna altitude above mean-sea-level
// M           Units of antenna altitude, meters
// c.d         Geoidal height
// M           Units of geoidal height, meters
// x.x         Age of Differential GPS data (seconds since last valid RTCM transmission)
// nnnn        Differential reference station ID, 0000 to 1023

void printGPSData(GPSData *gpsData)
{
   printf("Lat: %dd %d.%d' %c, Long: %dd %d.%d' %c, Sats: %d, Checksum: %02X\n",
      gpsData->latDM.degrees, gpsData->latDM.mins, gpsData->latDM.minFrac, gpsData->latDM.quadrasphere,
      gpsData->longDM.degrees, gpsData->longDM.mins, gpsData->longDM.minFrac, gpsData->longDM.quadrasphere,
      gpsData->numSats, gpsData->checkSum);
}

int hexStr2Int(char* str, int sPos, int numChars)
{
   int val = 0;
   while (numChars > 0)   {
      int d = str[sPos] - 48;
      if (d>9) d -= 7;
      val = (val << 4) + (d & 0xF);
      sPos++;
      numChars--;
   }

   return val;
}

int extractNum(char* str, int sPos, int ePos, int *valPtr)
{
   int val = 0;
   for ( ; sPos<=ePos ; sPos++)
   {
      if (str[sPos] > 57 || str[sPos] < 48) return 1;

      val = (val*10) + str[sPos] - 48;
   }

   *valPtr = val;
   return 0;
}

int decodeGPSString(char *str, GPSData *gpsData)
{
   const char *code = "$GPGGA";
   int i;

   // Check for the correct code
   for (i=0 ; i<6 ; i++) if (str[i] != code[i]) return 1;

   int pos = 1;
   int commaPos[14];
   int commaCount = 0;
   int starPos = 0;
   int nlPos = 0;
   char checkSum = 0;

   // Iterate through string characters
   while (pos < 100) {

      // Check for end of line
      if (str[pos] == '\n') {
         nlPos = pos;
         break;
      }

      // Check for star and update checksum
      if (starPos == 0) {
         if (str[pos] == '*') starPos = pos;
         else checkSum ^= str[pos];
      }

      // Check for comma
      if (str[pos] == ',') {
         if (commaCount < 14) commaPos[commaCount] = pos;
         commaCount ++;
      }

      pos ++;
   }

   // Check for sensible format
   if (starPos==0 || nlPos==0 || commaCount!=14 || (nlPos-starPos)!=4) return 2;

   // Compare Checksums
   gpsData->checkSum = hexStr2Int(str, starPos+1, 2);
   if (checkSum != gpsData->checkSum) return 3;

   // Extract Latitude
   int err = 0;
   err |= extractNum(str, commaPos[1]+1, commaPos[1]+2, &gpsData->latDM.degrees);
   err |= extractNum(str, commaPos[1]+3, commaPos[1]+4, &gpsData->latDM.mins);
   err |= extractNum(str, commaPos[1]+6, commaPos[1]+10, &gpsData->latDM.minFrac);
   gpsData->latDM.quadrasphere = str[commaPos[2]+1];
   if (err) return 3;

   // Extract Longtude
   err = 0;
   err |= extractNum(str, commaPos[3]+1, commaPos[3]+3, &gpsData->longDM.degrees);
   err |= extractNum(str, commaPos[3]+4, commaPos[3]+5, &gpsData->longDM.mins);
   err |= extractNum(str, commaPos[3]+7, commaPos[3]+11, &gpsData->longDM.minFrac);
   gpsData->longDM.quadrasphere = str[commaPos[4]+1];
   if (err) return 4;

   // Extract Quality
   err = extractNum(str, commaPos[6]+1, commaPos[7]-1, &gpsData->quality);
   if (err) return 5;

   // Extract Number of Satelites
   err = extractNum(str, commaPos[6]+1, commaPos[7]-1, &gpsData->numSats);
   if (err) return 6;

   return 0;
}
File: gpsTest.c
#include <stdio.h>
#include "gps.h"

int main(void)
{
   char buffer[200];
   GPSData gpsData;

   FILE *fp;
   fp = fopen("/dev/ttyS2", "r");

   while (1)
   {
      if (fgets(buffer, 100, fp) == NULL) {
         printf("Got NULL\n");
         break;
      }

      if (ferror(fp)) {
         printf ("Error Reading\n");
         break;
      }

      int result = decodeString(buffer, &gpsData);
      if (result == 0) printGPSData(&gpsData);
   }

   fclose(fp);

   return 0;
}
File: Makefile
# Gumstix GPS Makefile

CC       = /files/gumstix/gumstix-oe/tmp/cross/bin/arm-angstrom-linux-gnueabi-gcc
CFLAGS   += -Wall

OBJS     = gps.o

gpsTest: gpsTest.c $(OBJS)
   $(CC) $(CFLAGS) $(INCLUDE) $(OBJS) -o gpsTest gpsTest.c

gps.o: gps.c gps.h
   $(CC) $(CFLAGS) $(INCLUDE) -c gps.c

Book Logo