Friday, July 19, 2013

NMEA checksum calculator



Understanding NMEA Checksum

 
The checksum (CS) is generated by X-OR’ing all the data characters together in sequence, starting with the first ‘data’ character and XOR it with the next one. Then take that result and XOR it with the next, and so on.
Note: The ‘$’ and ‘*’ characters are excluded from calculation.
The example below show how to calculate the CS for the word “test”.


Note: You can use the windows or ubuntu calculator in advance mode to perform this operation.
Step1:
t XOR e


 
Result1 = 0010001 = 11 HEX

Step2:
Result1 XOR s

Result2 = 1100010 = 62 HEX
 
Step3:
Result2 XOR t


 
CS = 0010110 = 16 HEX
 External links

Enough talking, now it's fun time!

Arduino code

// Sample sentences to XOR
//$test*16
//$GPRMC,023405.00,A,1827.23072,N,06958.07877,W,1.631,33.83,230613,,,A*42

const byte buff_size = 80; // buffer size must be a constant variable
char buffer[buff_size];
byte index = 0;   // declare all variables that will hold numbers less than '255' as 'byte' data type, because they require only '1-byte' of memory ('int' uses 2-bytes).
byte start_with = 0;
byte end_with = 0;
byte CRC = 0;
boolean data_end = false; // Here we will keep track of EOT (End Of Transmission).

void setup(){

  Serial.begin(9600);
  Serial.println("Serial communication initialized"); // Print to serial port so we know its working.

}


void loop(){

  while (Serial.available() > 0){
    char inchar = Serial.read();
    buffer[index]  = inchar;

    if( inchar == '$'){
      start_with = index;
    }

    if(inchar == '*'){
      end_with = index;
    }

    index++;

    if(inchar == '\n' || inchar == '\r'){ // if 'new line' or 'carriage return' is received then EOT.
      index = 0;
      data_end = true;
    }
  } 


  if (data_end == true){
    for (byte x = start_with+1; x<end_with; x++){ // XOR every character in between '$' and '*'
      CRC = CRC ^ buffer[x] ;
    }
  }

  if(CRC > 0){
    Serial.println(CRC,HEX); // print calculated CS in HEX format.
    CRC = 0; // reset CRC variable
    data_end = false; // Reset EOF so we can process more incoming data.
  }


}

//Elimeléc López - July-19th-2013