GPS & NMEA Protocol

EM406 GPS Module
EM406 GPS Module

A wide array of devices and sensors make use RS-232 (Serial Data Protocol), and the most common configuration to be found is 9600 baud, 8 data bits, 1 Stop Bit and No Parity – as we have experienced in previous examples (RFID & Bluetooth). At a minimum, serial communication requires at least the following connections TX, RX, VCC and GND between your sensor and microcontroller – GPS Receivers are no different.

GPS is a system that can determine your latitude, longitude and altitude. The GPS Receiver listens for radio signals from an array of satellites in orbit. The receiver can then determine how long it took to receive the initial signals, and by analysing the received signal strength – it can compute (triangulate) how far it is from the relative satellites in orbit. This is possible as the satellites are in geostationary orbit i.e. their locations are always the same in relation to the surface of the earth.

The quality and accuracy of information delivered or computed by the GPS Receiver is dependent on how many satellite signals it can lock onto – simultaneously. For instance, triangulation of ones position requires a minimum of three satellites, and to compute altitude above sea level requires a lock on at least six satellites signals at one given time.

As a result of this “open sky dependency”, the accuracy of your GPS receiver is dependent on your surroundings (i.e. in doors), the quality of the receiver and the strength of the signals it receives.

The GPS module, EM406, uses the open protocol NMEA – National Marine Electronics Association and SIRF Binary for all communication. In the example below, we will look at the NMEA 0183 protocol. As NMEA 0183 is an open protocol – it means that the code you write for one GPS module will work for other GPS receivers. The EM406 module is configured by default to use the NMEA Protocol – 4800 baud, 8 data bits, 1 Stop Bit and No Parity. The NMEA protocol is ASCII based and works in continuous mode.

GPS Datastream
GPS Sentences

The data the GPS Receiver provides is contained in several different types of sentences. The simplest of these sentences give you latitude, longitude, altitude, time and a checksum. Every NMEA sentence starts with ‘$’, two letters that identify the device and then three letters to identify the type of sentence i.e. $GPRMC. After which, each data item is separated by a comma, and the 2 byte checksum denoted by ‘*’. Every sentence ends with a carriage return (ASCII 13) and linefeed (ASCII 10).

Every GPS Receiver is capable of transmitting several NMEA sentences i.e. $GPRMC, $GPGLL, $GPGSV etc. The simplest sentence to provide latitude, longitude and time of reading is $GPGLL. As every parameter is separated with the ‘,’ (ASCII 44) – parsing the NMEA sentence is quite easy.

GPS, XBee & Arduino
GPS, XBee & Arduino

GPS XBee Transmitter:

/* 
 * SoftwareSerial Library provides Arduino an additional
 * "Software" Serial Port
*/
#include 

// SoftwareSerial TX & RX Pins
#define SoftrxPin 3
#define SofttxPin 2

/* Declare and Initialise SoftwareSerial Object 
 * - Setup the Software Serial Port
*/
SoftwareSerial mySerial = SoftwareSerial(SoftrxPin, SofttxPin);

// GPRMC byte variable from the GPS
byte GPRMC = 0;

// MessageLine - The Entire GPS Message Received
byte messageLine[128];

void setup() 
{
  // Set the XBee BAUD RATE
  Serial.begin(9600);
  
  // Set the GPS BAUD RATE
  mySerial.begin(4800); 
  
  // Receive GPS Serial Data on Digital Pin 2
  pinMode(SoftrxPin, INPUT);
}


void loop() 
{
  GPRMC = mySerial.read();

  if(GPRMC == '$')
  {
    // Clear out the previous GPS Message
    for(int i =0; i< 128; i++) { messageLine[i] = '1'; }
    
    // Message Length Counter
    int index = 2;
  
    while(GPRMC != '\n')
    {
      /* 
      * Insert '$' at position 1 in MessageLine, as position 0 is reserved
      * for the total number of chars contained in GPS Message.
      */
      messageLine[index] = GPRMC;
      index++;
      GPRMC = mySerial.read();
    }
  
    // Insert the GPS Message Length at position 0 in messageLine Array
    messageLine[0] = '!';
    // Insert total length of Message 
    messageLine[1] = index;
    // Add '\n'
    messageLine[index] = 10;
    index++;
    
    // Send the GPS Data to a Wireless Client
    for(int i = 0; i < index; i++) { Serial.print(messageLine[i]); }
   delay(100);
  }
}

GPS XBee Receiver:

byte mLength = 0;
byte GPSRMC = 0;

void setup()
{
  // Set the XBee BAUD RATE
  Serial.begin(9600);
}

void loop()
{
    GPSRMC = Serial.read();
    
    if (GPSRMC == '!')
    {
     // Get Length of NMEA Sentence
      mLength = Serial.read();
     // Initialise Array
      byte messageIn[mLength];
      int cnt = 0;
      
     // Get NMEA Sentence 
      while ((GPSRMC != 10) && (cnt <= (mLength - 2)))
      {
        GPSRMC = Serial.read();
        messageIn[cnt] = GPSRMC;
      // Display NMEA Sentence 
        Serial.print(messageIn[cnt]);
        cnt++;
      }
  }
  delay(100);
}