|
|
| Author |
Message |
mdown
Joined: 03 Feb 2006
Posts: 62
Location: Dallas, Texas
|
|
Posted: 09 October 2006, 18:13 PM Post subject: NMEA Checksum Code |
|
|
The NMEA checksum is the 8-bit exclusive OR (no start or stop bits) of all characters in the sentence, including the "," delimiters, between -- but not including -- the "$" and "*" delimiters.
The hexadecimal value of the most significant and least significant 4 bits of the result are converted to two ASCII characters (0-9, A-F) for transmission. The most significant character is transmitted first.
| Code: |
Function NMEA_Checksum(sentence as String) As String
Dim i as integer
dim sum as integer
sum=0
For i = 2 To Len(trim(sentence)) - 2
sum = sum Xor cint(Asc(Mid(sentence, i, 1)))
Next i
NMEA_Checksum = mid(cstrHex(sum),3,2)
End Function |
This seems to be correct, am I missing anything?
-Mike |
|
| Back to top |
|
 |
stevech
Joined: 23 Feb 2006
Posts: 656
|
|
Posted: 09 October 2006, 18:33 PM Post subject: |
|
|
| You might want to use a byte for the checksum since the standard specifies this. I don't think it would change your results, just the efficiency |
|
| Back to top |
|
 |
dkinzer Site Admin
Joined: 03 Sep 2005
Posts: 2493
Location: Portland, OR
|
|
Posted: 09 October 2006, 20:09 PM Post subject: |
|
|
The code below incorporates Steve's suggestion and additional changes.
Firstly, since sentence is passed by reference in your code that precludes calling the function with a constant string parameter. That may or may not be an important limitation.
Secondly, the upper limit of the For loop was computed as the length of the trimmed input string but the bytes being added to the checksum were being retrieved from the untrimmed input string. This would only be important if the input string had leading space characters.
Thirdly, the optional second parameter to the Asc() function can be used to eliminate the need to generate intermediate 1-byte strings.
Another issue that is not addressed is the assumption that the input string has the correct format. If the caller checks the format before calling this function then that is not an issue.
| Code: | Function NMEA_Checksum(ByVal sentence as String) As String
Dim s as String
Dim i as Integer
Dim sum as Byte
s = Trim(sentence)
sum=0
For i = 2 To Len(s) - 2
sum = sum Xor Asc(s, i)
Next i
NMEA_Checksum = CStrHex(sum)
End Function |
As a side note, one characteristic of the Xor function is that performing the operation a second time with the same value reverses the effect of the initial operation, i.e. A Xor B Xor A equals B. The operation is commutative so the order of operations is unimportant. The upshot of this is that you needn't skip the first and last characters if you initialize the checksum to the Xor of those two characters. The inner code block would then be:
| Code: | sum = Asc("$") Xor Asc("*") ' negate the effect of the first and last characters
For i = 1 To Len(s)
sum = sum Xor Asc(s, i)
Next i |
|
|
| Back to top |
|
 |
FFMan
Joined: 09 Jan 2010
Posts: 217
|
|
Posted: 27 February 2010, 20:46 PM Post subject: |
|
|
I've used the code in this post to check my nmea checksum and the received checksum and the calculated one agree when the checksum does ot include letters. When it does, the received one is uppercase, the calculated on lower case - can anyone suggest a reason why ?
$GPGLL,5153.4516,N,00111.4612,W,204149.400,A,A*41
Calc=41
Mine=41
Valid
Count=51
$GPGLL,5153.4520,N,00111.4609,W,204149.600,A,A*4C
Calc=4c
Mine=4C
Bad Checksum |
|
| Back to top |
|
 |
spamiam
Joined: 13 Nov 2005
Posts: 661
|
|
Posted: 27 February 2010, 21:47 PM Post subject: |
|
|
you are returning a STRING that has the characters "4" and "C". It is being compared to the characters "4" and "c". Since the "C" characters are not identical, the comparison is untrue.
You can convert the case of one all upper or the other to all lower, them make the comparison.
Alternatively, you can return the actual numerical value of the checksum as a byte, and compare that to the the value of the checksum in the sentence.
-Tony |
|
| Back to top |
|
 |
dkinzer Site Admin
Joined: 03 Sep 2005
Posts: 2493
Location: Portland, OR
|
|
Posted: 27 February 2010, 22:02 PM Post subject: |
|
|
| FFMan wrote: | | [T]he calculated on lower case - can anyone suggest a reason why ? | Both A-F and a-f are valid hexadecimal characters in most contexts; alphabetic case is usually a matter of preference. The function CStrHex() happens to produce lower case characters. If you need upper case, use this modified version of the checksum function: | Code: | Function NMEA_Checksum(ByVal sentence as String, ByVal upper as Boolean = True) As String
Dim s as String
Dim i as Integer
Dim sum as Byte
s = Trim(sentence)
sum=0
For i = 2 To Len(s) - 2
sum = sum Xor Asc(s, i)
Next i
NMEA_Checksum = CStrHex(sum)
If (upper) Then
NMEA_Checksum = UCase(NMEA_Checksum)
End If
End Function |
|
|
| Back to top |
|
 |
FFMan
Joined: 09 Jan 2010
Posts: 217
|
|
Posted: 27 February 2010, 22:52 PM Post subject: |
|
|
ok - i thought the print of the checksum was the actual checksum but you're saying its the value printed as hex and therefore 4c=4C naturally.
It all working now thanks |
|
| Back to top |
|
 |
|