Serial messaging between Arduino and PC
Serial messaging between Arduino and PC

Arduino to PC messaging – improved speed, compatibility and testing

| 4 Comments

Introduction

In my ongoing quest to make CmdMessenger the best PC to Arduino communication library, I have released a new version with some significant updates. This article will give an overview of these changes: the speed optimization for the fast ARM based boards, better compatibility in data formats between the PC and Arduino, and a unit testing framework.

trans Arduino to PC messaging    improved speed, compatibility and testing image

The library, along with many examples and documentation can be downloaded here:

Or at the Github repository:
https://github.com/thijse/Arduino-Libraries/tree/master/CmdMessenger

An overview of all articles on CmdMessenger can be found here:

http://thijs.elenbaas.net/tag/CmdMessenger/

Teensy benchmarks

Paul Stoffregen graciously sent me two of his Teensy 3.0 boards, and I bought a Teensy 3.1 as soon as it came out, which has rapidly become my favorite prototyping board.
One of the main reasons for this is the niceUSB performance. I started with seeing if I could reproduce Paul’s benchmarks. Indeed, my Teensy 3 (the starred entry) performed similarly:USB send speed Arduino Teensy Arduino to PC messaging    improved speed, compatibility and testing image

Benchmarks sending data over USB Arduino & Teensy

Paul did not benchmark the Arduino Uno or Arduino Nano. On Both boards the serial baudrate is limited to 115200 baud, but I was still curious to see how that translates out in the benchmarks. I added them because, while they are architecturally very different to the Teensy, they are similar in price. As expected, the transfer speeds are quite different: both 16 bit boards are capable of receiving +/-11500 bytes/sec, which is reasonably close to 115200 bits/sec / (8 bits + 1 stopbit), whereas the Teensy comes close to 1 MB/sec.

An interesting find by Paul was that Windows 7 performs much worse than Linux and OS-X for small data-blocks. I was curious to see if that had changed with Windows 7.1 and Windows 8. As you can see in the chart below, indeed it has, but not all for the better:

e612ff1b5bbfafa0757ac7574224a415 Arduino to PC messaging    improved speed, compatibility and testing image

Send speed by Operating System

The Windows 7.1 results are slightly different, but that can be due to the hardware (HP 8560w: i7 2820QM, 2.3 GHz ) or compilers (PC: gcc-4.7.1, Arduino: Arduino 1.0.5) used. Under the same conditions Windows 8 performs better than Windows 7 for smaller data-blocks, although still not nearly as good as Linux and Mac. Strangely enough, though, for larger data-chunks, Windows 8 performs significantly worse than Windows 7.1!

Speed improvements and benchmarks

This served as a prelude to measuring the speed of CmdMessenger. Per Paul’s suggestion I had already implemented a serial read buffer using readBytes() on the Arduino using to improve performance. Looking at the raw receive benchmarks, I was expecting pretty solid results. This made my first measurements a bit disappointing: the receiving speed was only twice that of an the Arduino Uno.

It occurred to me that while the Teensy was now able to receive and process many bytes at once, the PC side of CmdMessenger still send only very small messages, typically around 10 bytes. which

This means that we might improve performance by sending longer messages. Because the PC CmdMessenger has a nice send queue for asynchronously sending commands, I could combine multiple messages on the queue. This results in a single long string of multiple commands, which makes sending it much more efficient. As it turns out, this makes a world of difference, as you can see in the chart below. Compare the buffered and unbuffered send benchmark:

 

CmdMessenger send and receive Arduino to PC messaging    improved speed, compatibility and testing image

CmdMessenger Send & Receive benchmarks

 

Obviously, it is still not as fast as sending raw data, but it is now 30 times faster than the Arduino Uno / Nano. I think that is a pretty excellent result!  Note that sending & receiving commands is more that just sending out bytes: it is packing commands, queuing and combining them, sending them, and unpacking and parsing them.

If you want to reproduce these, go right ahead. They are part of the unit testing project. You can play adjust the buffer size, by adding it to the PC based CmdMessenger constructor.

Be careful, though: the Arduino serial buffer size is 64 bytes. For my 16 bit boards I’ve seen that sending command strings larger than 64 bytes will sometimes choke the board.

Compatibility

An issue I had with sending commands from .Net to my Arduino is that the definitions of some basic variables differ. This grew further with the advent of the ARM based Arduino boards. Consider the following variables and their size on the different platforms.

692c42c2c96367b38cfe80b34607cc48 Arduino to PC messaging    improved speed, compatibility and testing image

It is very important to use the same data formats on both side of the line. If we use the different formats , this can result in different problems: for text based variables truncation and loss of accuracy may occur, and for binary variables a mismatch will almost certainly result in completely wrong values.

This has been solved by doing two things:
1.In the library as well as the examples I switched from Int, Long & Short to the unambiguous Int16 and Int32 descriptions.
2. For floating point values the library uses the Float and Double description, but I removed all Single references. Float was already unambiguously 32 bits on all platforms, but in order to process Doubles correctly on all platforms, I modified the library: you can now set on the PC side whether the receiving embedded board is 32 bits or 16 bits:

In the former case, unaltered 64 bit values are sent and received, but In the latter case the CmdMessenger library will automatically convert values. That is, double variables are automatically converted from 32 bit to 16 when being sent to the board, and converted from 16 bit to 32 bit when being send to the PC. While this may result in reduced accuracy and truncation of values, both text based and binary transfers will be compatible and sending variables will be straight forward :

9f1cd9f3a41a4439fbd7e06b74e16e4a Arduino to PC messaging    improved speed, compatibility and testing image

Please look at the examples to see how these data formats are being used

Unit tests

When I started with CmdMessenger 3.0 It was still a quite  straight-forward library, but it has grown, both on Arduino and PC side to include new features such as: binary sending of data, asynchronous send and receive queues, adaptive throttling, Queue strategies and much more. As a result, the code has become more complex, and requires a lot of testing with every release. Because of this I started to add unit tests, to perform the test I would normally do by hand.  At this point they do not test every scenario I can think of, but they cover all mayor functionality. It runs the following sets of tests:

  • Test all plain text formats
  • Test all binary formats
  • Test sending multiple arguments
  • Test send and receive speed

As a matter of fact, making and running these tests revealed multiple bugs and shortcomings, ranging from small inconveniences to hidden and serious bugs. These have been fixed in this release, and I believe this CmdMessenger 3.6 is the most robust release so far!

The tests have not been written to function as examples, so they are not as extensively documented, but they may be interesting nonetheless. For example, it performs send- and receive benchmarks that you might like to run. Please try it for your own boards, but be sure to create your own board description. I supplied one for my Arduino Mini and Teens 3.1. Below is the definition of the latter

Scientific Format

Using the testing framework, I learned that the Arduino is only capable of printing clear-text floats(and doubles) in the range of from -2,147,483,648 to 2,147,483,647. This is strange because the internal representation of a float value has a range of -3.4028235E+38 to -3.4028235E+38. We can solve this by sending floats and doubles in binary format. However, some users prefer clear-text values, so I’ve added a print function that will send clear-text values in scientific format that span the full range:

cmdMessenger.printSci (arg, n)

Bugfixes

This release features many fixes, some came from the unit tests, but also came from users of the library. Thanks for that!

  • [Arduino] Bugfix: approx 1 in 1000 commands failed, when multiple binary parameters are sent over
  • [Arduino] Bugfix: Binary sending of non-number would give compile time error
  • [Arduino] feature: Posibility to send command without argument
  • [Arduino] feature: Posibility to send floats with scientific notation, to get full float range
  • [.Net/.Mono] Added more multi-threading robustness, this fixes, amongst others, that the receive thread is starved while the main program is waiting for a receive acknowledgement

4 Comments

  1. You have benchmarks for Maple here, so I assume you were able to port the library somewhat to maple?

    I tried this, but got some errors.

    Thanks

    • Ah, no. This benchmark came from the Teensy manufacturer. I understand from the maple website that it is only somewhat Arduino compatible, so I’m not surprised that it fails to build. That said, the core of the library is plain c++, so it will be relatively easy to port it. However, since I don’t have a Maple board, I cannot do it.

  2. Are you aware if anyone has ported the PC side from C# to a processing library?

    • No, as far as I’m aware not. As I understand, Processing is kind of gentle Java environment. One way to tackle this is by using a C# to Java converter on CmdMessenger and go from there. Note that this will still take a considerable amount of work and knowledge to get it working.

Leave a Reply to Joe Cancel reply

Required fields are marked *.