Saturday, July 16, 2016

Faster serial port communication from .NET to Arduino

Overview

I was for a long time thinking that serial port communication on Windows and/or .NET was limited to 115 200 bauds, which translate to 11Kb/s at the most ( 115200 / 10 (8 bit-data + 2 (1-start-bit 1-stop-bit )) ).

In reality it is possible to use faster transfer rate, but there are a few things to know and it can be a little bit convoluted.

I am currently working on my "device" NusbioMCU, which use an Arduino Nano compatible (ATmega328),
so I will focus in this post on communication from Windows+.NET to different Arduino and compatibles.
But this can be applied to any serial communication from Windows and .NET.

This post should be taken with some grains of salt, because I am not an expert. I am just a guy that would like to do faster serial communication from Windows and .NET. This post is the fruit of my research and experimentation.


What do you need to know?

  • Hardware: You must know what UART chip is used in your MCU board. Different chip will support different baud rates, and the values may not be as expected.

    Popular UART chip:

    The Windows Device Manager program can help you figure this out. Below is the list of baud rate supported by the FT231X UART.

As shown in the image above, the FT231X UART which comes with the Adafruit Metro (a compatible Arduino UNO) support the 460 800 and  921 600 baud rates (Same for the FT232RL).


The Atmega16U2 UART which comes with a real Arduino UNO R3, will only display up to 128 000,
but multiplying this value by 2, 4 or 8 works.


Regarding the CH340, Chinese Arduino UNO or Nano compatibles comes with a CH340 UART which is limited to 115 200 bauds. That said based on information from RyanteckLTD and their device the RTK.Gpio, it could be possible that if the CH340 has its own 12 Mhz clock, it then can support faster transfer rates.

  • USB 2.0 Full Speed. The FTDI FT232RL or FT231X UART chips implement serial communication over USB 2.0 Full Speed. In USB 2.0 Full Speed there is a 1 ms latency to access the USB and transfer data. So if we transfer data in a 64 byte or less buffer, we cannot expect a transfer rate greater then 64 x 1000 == 53K b/s. 
    There are 2 transfer phases:
    1. From the PC to the UART at USB 2.0 Full Speed, dependent on the data buffer size
    2. From the UART to the MCU based on the baud rate. UART generally have an output buffer that allow to receive byte faster that they can sent according to the baud rate, but they are limted to 128 or 512 bytes
For example if we transfer data in buffer of 256 bytes at the USB level we can reach 212 Kb/s (256 * 1000 / 1024), that said since the max baud rate is 921 600 or 90 Kb/s I think the FTDI driver will stop the communication until the UART buffer is empty.
So for now I am only focusing on reaching 64 Kb/s.

  • Sofware:
    • The SerialPort class available in .NET does not support transfer speed greater than 115 200 bauds. The Windows low level API does support it, but the .NET implementation does not.
      See blog post If you *must* use .NET System.IO.Ports.SerialPort.
      Though is his blog post Ben Voigt gave some code small snippet that could work.
    • I did not find another open source and/or free library on the internet
    • With the Windows Serial Communication Component Library from Marshallsoft, I was able to achieve greater transfer speed.

 

Transfer Test

To test the transfer speed I am sending from the PC to the MCU 640 times, 4 buffers containing 33 bytes of data (82.5 Kb). Each buffer is processed by the MCU and the data is sent to a 32x8 LED matrix driven by 4 MAX7219 chips chained using the SPI protocol at 10Mhz (about 1 Mb/s).

There is no acknowledgment from MCU to the PC. I am visually testing the result for now, when there are issues the expected images is not display correctly on the matrix. When there is no issue I see a slight flickering of the expected images (see picture below).

The processing time by the MCU of one buffer takes less than 1 ms, and since there is a know 1 ms overhead when using USB 2.0 full speed, the PC is always working on sending the next buffer while the MCU is processing the current one. That said this will be an issue when the MCU take more than 1 ms to process the data. I did verified that the processing by the MCU does not affect the transfer in my case.

With that configuration I reached 33 Kb/s at 500 000 bauds. At  1 000 000 bauds no improvement.

Realizing that to get more transfer speed I needed to send more data I changed buffer size to 41 bytes of data (for total of 102.5 Kb) and reached 41Kb/s.

RTS/CTS
According to the schematic of the Arduino Uno R2 or Adafruit Arduino Metro, it looks like the RST/CTS pin are not wired to the MCU. So I guess there is no hardware control flow.

Summary

Here are my results using the Marshallsoft WSC library called from a C# program.

MCU UART Max Baud Rate Expected Kb/S Measured Kb/S
Arduino UNO R3 Atmega16U2 512 000 50 Kb/s 41 Kb/s
Adafruit Arduino Metro FT231X 500 000 48 Kb/s 41 Kb/s
Adafruit Trinket Pro + FTDI Cable FT232RL 500 000 48 Kb/s 41 Kb/s
Arduino Nano Compatible Chinese CH340 115 200 11 Kb/s 11 Kb/s

Note that the baud rates for the Atmega16U2 and FT231X are different, this is not a typo.

I do see a transfer speed increase from 115200 to 230400 and from 230400  to 460800.
But at 460800 or 500000 I do measure a transfer rate lower than expected.
And at 1 024 000 baud there is no improvement so far, with the FT231X, FT232RL and the Atmega16U2.

I think the issue here is that I need be able to send bigger buffer, but for that the Arduino need to be able to handle it, up to 41 Kb/s it is ok, after that it does not work (yet). The Arduino serial library only use a 64 bytes buffer and I think this is my problem. I would need to increase this buffer to 128 bytes and and send 64 bytes buffer to achieve 64 Kb/s. Well at least that is my expectation.


To-Do

  • Optimize processing and serial communication on the Arduino side to support buffer of 64 bytes
  • Test CH340 with its own 12 Mhz clock 
  • Test Cypress CP2130
To be continued.

Contact



To contact me see my web site MadeInTheUSB.net.










No comments:

Post a Comment