MAVlink frustrations--how do I calculate a crc16 checksum in VB.net?

My most recent challenge has been adding the MAVlink protocol to my GCS project. So far, it has been my experience that one of the most difficult parts of pulling protocol messages apart is cracking the Checksum formula. A quick Google search will return hundreds of examples in C or assembler...but try finding one in Visual Basic. They mostly don't exist. uBlox and MediaTek have one method, SiRF has another, NMEA has it's own....

Then there's MAVlink. Their Comm Protocol page http://pixhawk.ethz.ch/wiki/mavlink/#mavlink_packet_documentation shows a link to a SAE AS5669A document found here: http://www.sae.org/servlets/productDetail?PROD_TYP=STD&PROD_CD=... in which they want $63 to purchase a standards PDF which still won't tell me what I need to know to decode their checksum. Apparently, they're using a crc16 checksum which includes bit shifting. A task not easily handled by .NET. So I've downloaded an converted 4 different checksum functions (1 in C, 2 in C# and 1 in VB6) to VB.NET. None of which will successfully generate the checksums I'm getting from the latest MAVlink APM output.

So I refer back to the MAVlink Comm Protocol document. Perhaps I'm looking at the wrong data. In the case of NMEA, they don't include $ or * in the checksum calculation. In uBlox, they don't include the leading uB in the checksum... but what do you know. They make no mention in the specification as to what they don't include. Is it everything? Do they leave off the "U"... no way to tell so I guess we assume everything is included. But so far, no luck in cracking this nut.... I've got about 8 hours in it so far.

So some might say, skip the Checksum for now. Just read the "U" as the header and the next byte is the payload length...and go from there. Well this is an EPIC FAIL of the MAVlink specification. In a purely homogenous environment where ONLY MAVlink messages exist, worst case (assuming no transmission fails) you'll only loose the first message by false positive on the header. Then it gets pitched on the next pass and you're off and running. "U" is recognized, length of message, checksum matches, all is good. Decode, discard, on to the next. Trouble is if you're not in a 100% MAVlink environment or you have to be ready to handle other protocols, then a "U" has a 1 in 255 change of occurring in a non MAVlink sentence. By having a 2 character header (like SiRF, MediaTek and uBlox), there is a 1 in 65,025 chance of having a false positive. By having a 3 character header (like ArduPilot, NMEA and UDB) there's a 1 in 16,581,375 chance of a false positive.

Does anyone have any clue how to correctly calculate a crc16 checksum in VB.NET? There are lots of "lightening fast" crc16 routines out these that make use of external C DLL's or some assembler code. I'm not interested in lightening fast... I just need it to work.

Views: 2549

Comment by Dean Lamborn on December 2, 2010 at 11:16am
Unmanned Systems and Robotics Interoperability Center
Under software you can download:
JAUS++ is an open source C++ implementation of both the JAUS Reference Architecture and SAE standard (AS5669A, AS5710, and AS6009) available under the BSD license.

I also found this:
SAE AS5669A
Comment by Paul Mather on December 2, 2010 at 11:32am
Thanks Dean, but I downloaded both...but they didn't seem to help..
Comment by Paul Mather on December 2, 2010 at 11:34am
Here's a VB6 version which didn't generate matching checksums with the MAVlink APM output.

http://www.di-mgt.com.au/src/basCRC16.txt
Comment by MechatronicsLLC on December 2, 2010 at 1:16pm
Happy -

We use the below for CRC32 in VB.net. You might be able to adapt it for CRC16. It is a function call that is called per the following:

Dim CRC32 As Integer
CRC32 = XsumCRC32(&HFFFFFFFF, doitbyte)

where doitbyte is a byte array with the data youwant to checksum, and the first variable is the starting value for the CRC...



Public Function XsumCRC32(ByVal CRC_acc As Integer, ByVal CRC_input As Byte()) As Integer

Dim j As Integer
Dim i As Byte
Dim POLY As Integer = &HEDB88320

Try

For j = 0 To (CRC_input.GetUpperBound(0))
CRC_acc = CRC_acc Xor CRC_input(j)
For i = 0 To 7
If ((CRC_acc And &H1) = &H1) Then

CRC_acc = Convert.ToInt32(((CRC_acc And &HFFFFFFFE) \ 2&) And &H7FFFFFFF)
CRC_acc = CRC_acc Xor POLY
Else
CRC_acc = Convert.ToInt32(((CRC_acc And &HFFFFFFFE) \ 2&) And &H7FFFFFFF)
End If
Next i
Next j
XsumCRC32 = CInt(CRC_acc)
Catch ex As Exception

Debug.Print(ex.Message)

End Try
End Function
Comment by pixhawk on December 2, 2010 at 2:46pm
nice to see that you're adding support. The code portion above is a good start. Did you see that the CRC is also part of the open source code? Just translate the C commands to VB. If it helps, the checksum is the same polynomial as in the X.25 ITU standard. And yes, the start sign is not part of the checksum, so anything after the U should be included. Hope this helps, let me know if you have additional questions on the protocol.

Developer
Comment by Michael Oborne on December 2, 2010 at 6:21pm
Im already doing it in C# .net, have a look at the APM planner, im sending raw GPS and IMU messages.

Comment

You need to be a member of DIY Drones to add comments!

Join DIY Drones

Groups

Season Two of the Trust Time Trial (T3) Contest 
A list of all T3 contests is here. The current round, the Vertical Horizontal one, is here

© 2020   Created by Chris Anderson.   Powered by

Badges  |  Report an Issue  |  Terms of Service