nmea checksum in c# .net cf

6.7k views Asked by At

I'm trying to write my own nmea parser,since i only need some info from the gps, and don't need to interpret all messages. The problem that i have is that my nmea message validator gives me an wrong checksum. Can someone see what i'm droing wrong?

I'm using the idea from Codepedia - Calculating and Validating nmea sentences.

    // Returns True if a sentence's checksum matches the 
    // calculated checksum
    // Calculates the checksum for a sentence
    private static bool IsValid(string sentence)
    {
        if (sentence == "")
            return false;
        if (sentence.Length < 14)
            return false;
        try
        {
            string[] Words = GetWords(sentence);
            Log.writeToLog(Words);
            int checksum = 0;
            string CheckToCompare = Words[Words.Length - 1];
            StringBuilder sb = new StringBuilder();
            for (int i = 1; i < (Words.Length - 2); i++)
            {
                sb.Append(Words[i]);
            }
            string sentecenToParse = sb.ToString();

            foreach (char charY in sentecenToParse)
            {
                checksum ^= Convert.ToByte(charY);
            }


            Log.writeToLog("Checksum: " + checksum.ToString("X2"));
            Log.writeToLog("Obtained CheckSum: " + CheckToCompare);
            return String.Equals(checksum.ToString("X2"), CheckToCompare, StringComparison.OrdinalIgnoreCase);
        }
        catch (Exception exc)
        {
            Log.writeToLog("Exception caused by sentence:" + sentence);
            Log.writeToLog("Exception error message: " + exc.Message);
            return false;
        }


    }

    // Divides a sentence into individual Words
    public static string[] GetWords(string sentence)
    {
        char[] separator = { ',', '*' };
        return sentence.Split(separator);
    }

Run LOG

10:30:07 23-02-2011 Opening Port
10:30:08 23-02-2011 Opened Port
10:30:10 23-02-2011 Processing Data
10:30:12 23-02-2011 $GPGGA
10:30:12 23-02-2011 102957.92
10:30:12 23-02-2011 4104.8569
10:30:12 23-02-2011 N
10:30:12 23-02-2011 00836.4700
10:30:12 23-02-2011 W
10:30:12 23-02-2011 1
10:30:12 23-02-2011 4
10:30:12 23-02-2011 15.100
10:30:12 23-02-2011 157.133
10:30:12 23-02-2011 M
10:30:12 23-02-2011 52.386
10:30:12 23-02-2011 M
10:30:12 23-02-2011 0
10:30:12 23-02-2011 0
10:30:13 23-02-2011 79

10:30:13 23-02-2011 Checksum: 6D
10:30:13 23-02-2011 Obtained CheckSum: 79

10:30:13 23-02-2011 Invalid sentence
10:30:13 23-02-2011 $GPRMC
10:30:13 23-02-2011 102957.92
10:30:13 23-02-2011 A
10:30:13 23-02-2011 4104.8569
10:30:13 23-02-2011 N
10:30:13 23-02-2011 00836.4700
10:30:13 23-02-2011 W
10:30:13 23-02-2011 0.000
10:30:13 23-02-2011 5.822
10:30:13 23-02-2011 230211
10:30:13 23-02-2011 0
10:30:13 23-02-2011 W
10:30:14 23-02-2011 A
10:30:14 23-02-2011 2B

10:30:14 23-02-2011 Checksum: 4E
10:30:15 23-02-2011 Obtained CheckSum: 2B
10:30:15 23-02-2011 Invalid sentence
3

There are 3 answers

0
Carson63000 On BEST ANSWER

If you use this function from the page you linked:

private static string getChecksum(string sentence)
{
  //Start with first Item
  int checksum= Convert.ToByte(sentence[sentence.IndexOf('$')+1]);
  // Loop through all chars to get a checksum
  for (int i=sentence.IndexOf('$')+2 ; i<sentence.IndexOf('*') ; i++)
  {
    // No. XOR the checksum with this character's value
    checksum^=Convert.ToByte(sentence[i]);              
  }
  // Return the checksum formatted as a two-character hexadecimal
  return checksum.ToString("X2");
}

And pass in your string, with $ a the start and * at the end (before the checksum), and commas between words, it works.

string s1 = getChecksum("$GPGGA,102957.92,4104.8569,N,00836.4700,W,1,4,15.100,157.133,M,52.386,M,0,0*79");
string s2 = getChecksum("$GPRMC,102957.92,A,4104.8569,N,00836.4700,W,0.000,5.822,230211,0,W,A*2B");

s1 = 79 and s2 = 2B as you would hope.

0
Anders Zommarin On

Isn't the problem that you are discarding all the ',' characters when you calculate the checksum. They should be included as far as I can see. So calculate the checksum on the original string which you have not removed the commas from and it might work better...

0
WaywiserTundish On

For many cases making sure the checksum matches is just a waste of time. It's really only (marginally) useful when the source and sink of the NMEA sentences are separated by a serial cable which may be noisy. If the source and sink are within the same device, communicating via shared memory, the checksum will always be correct.