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 *:
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 + "\r\n"; // print it for debugging: println("\r\n\r\n"); println(cmd); println("\r\n\r\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; }
Note: The carriage return and line feed need to be denoted as: “\r\nâ€;