Thursday, October 20, 2011

Serial Protocol Testing

I love metrics. Real data that demonstrates the truth (or falsity) of a claim. Try to convince me of something using "anecdotal evidence" and I'll call you out for it.

My new robust serial communications protocol is coming along. In my day job I write "high-level" code working with models of business concepts and logic. It's been a long time since I've gotten down and dirty and worked directly with bits and bytes.

I hinted in my last post that I was going to use a MIDI-like protocol. The first byte has the left-most (MSB) bit raised. This marks the start of the frame/packet. All other bytes in the packet have the MSB cleared. This means each byte holds a "value" in 7 bits. The other 7 bits of the first byte carry the command. I clear the high bit to extract the command, then the next 5 bytes have to be bit-shifted into a 32-bit variable.

All this is pretty easy, really, I just haven't done much of it in Java. I got tripped up for a while because Java datatypes are all signed. Funny things happen when you shift bits left and right in signed datatypes. I learned about two's complement in college but never used it after that. The solution was to work with integers instead of bytes and just waste the extra bytes.

The last 2 bytes in the packet hold a checksum. I implemented a "Fletcher 14" checksum algorithm. I made that up. There's a 16 and 32 bit Fletcher checksum. Since all my data bytes have 7 bits, I can't do a 16 bit Fletcher without spreading it out over 3 bytes and having to do more fancy bit shifting. Probably wouldn't have been a big deal.

So back to the metrics thing. I've never written a checksum before, so I need to know if it works. I wrote a test program to randomly inject errors into the packet. I flipped 1 to 3 bits and swapped bytes in the packet. I ran 1.2 billion iterations with 1/4 billion errors. The checksum missed 47K errors. That's 1 in 5000 errors missed. That's pretty good for a checksum. The computational cost if this algorithm is low so I'm pretty happy with this outcome.

Then I wrote the code to handle the serial transmission of the packets for the Java client (the Arduino code is in C). It's much easier to debug in Java, so I connected 2 Java serial drivers together with a "ManglingInputStream" between them. This randomly injects dropped bytes and flipped bits. This demonstrated that error handling was sound. It would have been pretty hard to write it for the Arduino and throw it into the shop and wait for errors to happen. I'll collect error reports later so I know what the real-world error rate of the system is.

No comments:

Post a Comment