XOR calculation for NMEA checksums (GPS protocol)

If you’ve ever seen the serial output of a GPS reader, you’ve seen a mystery string at the end like this:

That’s the checksum of the whole string. NMEA data structure for Global Positioning (GPS) readers has a checksum on the end of each sentence. The checksum is the XOR of all the bytes between the $ and the * in the sentence. For example, if the sentence is this:

$GPRMC,155123.000,A,4043.8432,N,07359.7653,W,0.15,83.25,200407,,*28

then you run a checksum on this:

GPRMC,155123.000,A,4043.8432,N,07359.7653,W,0.15,83.25,200407,,

Here’s a Processing method to calculate the checksum, given the string between the $ and the *:

Technorati Tags: ,


char checkSum(String theseChars) {
  char check = 0;
  // iterate over the string, XOR each byte with the total sum:
  for (int c = 0; c < theseChars.length(); c++) {
    check = char(check ^ theseChars.charAt(c));
  } 
  // return the result
  return check;
}

And here’s a whole program to use the checksum with an Etek EB-85A reader:

/*
  ETEK EB-85A GPS reader test.
 
 This program reads NMEA data in from a GPS reader at 4800 bps.
 The ETEK EB-85A reader has a proprietary command protocol that
 requires the calculation of the checksum of each command you send.  
 The checksum is the XOR of all the bytes between the $ 
 and the * in the command string. The checkSum() routine
 does that calculation.

 created 20 Nov. 2007
 by Tom Igoe and Kristin O'Friel
 
 */

import processing.serial.*;

Serial myPort;

void setup(){
  // get the serial list:
  String[] thisPort = Serial.list();
  println(thisPort);
  // open the port:
  myPort = new Serial(this,thisPort[0] , 4800);  
}

void draw() {

}

void keyReleased() {
  // command to turn on WAAS:
  String cmd = "PMTK501,2";
  // turn off all byt the RMC sentence:
  // String cmd = "PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0";
  // cold reset:
  //String cmd = "PMTK104";
  // test packet:
  //String cmd = "PMTK000";
  // calculate the checksum, convert it to a 2-byte hex string:
  String checkSum = hex(checkSum(cmd),2);
  // add the $, the *, the checksum, the CR and LF:
  cmd = "$" + cmd + "*" + checkSum + "&#92;r&#92;n";
  // print it for debugging:
  println("&#92;r&#92;n&#92;r&#92;n");
  println(cmd);
  println("&#92;r&#92;n&#92;r&#92;n");
  // send it out the serial port:
  myPort.write(cmd);
}
// print anything that comes in the serial port:
void serialEvent(Serial myPort) {
  char inByte = char(myPort.read());
  print (inByte);
}

// calculate the checksum:
char checkSum(String theseChars) {
  char check = 0;
  // iterate over the string, XOR each byte with the total sum:
  for (int c = 0; c < theseChars.length(); c++) {
    check = char(check ^ theseChars.charAt(c));
  } 
  // return the result
  return check;
}
This entry was posted in Processing. Bookmark the permalink.

One Response to XOR calculation for NMEA checksums (GPS protocol)

  1. Kristin O'Friel says:

    Note: The carriage return and line feed need to be denoted as: “\r\n”;