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â€;