Go Down

Topic: 2Mbaud hack, but i dont get more than ~300Kbaud... (Read 3051 times) previous topic - next topic


Oct 01, 2009, 09:20 pm Last Edit: Oct 01, 2009, 09:45 pm by RIDDICK Reason: 1

i use this test program on the arduino (taken from here):
Code: [Select]
UCSR0A |= 1 << U2X0;
UBRR0H = 0; UBRR0L = 0;
UCSR0B |= (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0);
for (byte i=0; ; i++) Serial.write(i);

and get just about 300Kbaud and most (~99%) characters r wrong... with a C program and fedora core 11 linux...

The arduino is connected via USB as a "full speed" device according to linux...

Just with UBRR0L=8 i get reliably about 174Kbaud with a 0-error-rate (tested for some minutes), which is not enough (i expected 234Kbaud), too...

i found this thread:
but it doesnt work better (170Kbaud max.)...

What can i do in order to decrease wait time?
async would be the 2nd best choice, because i like to do handshaking (1-2 times per milli second: sending 5-10 bytes and then receiving 5-10 bytes)...




Hm, i might be totally wrong here, but if i understand the 168 datasheet well enough then the 168/328.. is 'only' supposed to run up to 230.4k. Everything above this baud rate seems to invoke errors. (168 datasheet Table 19-12 (see linked image).

Then again - i might be totally wrong ;0)


With the most recent version of Arduino (0017) there is actually no need for a"hack". You can call Serial.begin(2000000) to setup serial communication at 2MBaud. The 2MBaud speed requires an ATmega with a 16MHz clock.

I have this working reliably (no errors) with a Duemilianove on one end and Windows on the other. Sustained throughput is very close to 200kB/s (198+). I've also seen posts suggesting that it works on Mac (some lost characters). For a solution I think you need to focus on the other side (e.g. is baud rate set correctly, use buffered reads - not single byte, large buffer size).


Hm, i might be totally wrong here, ..

The ATmega USART serial clock is derived from the system clock (e.g. 16MHz) and integer math does not allow for all combinations of system clock and baudrates. The table you linked shows common baudrates, the best match possible and deviation as a percentage error from the baudrate requested. The bottom of the chart shows that for 2MB and 16MHz there is no deviation (0% error).

A small percentage of deviation is still acceptable as the USARTS in common use are quite tolerant (also the ATMega). Every bit (1 start, 8 data and 1 stop per byte sent/received) is actually sampled 16 times (or 8 times depending on configuration). This means that a singe bit can be as much as 50% off its mark and still be read correctly. This gives a frequency tolerance of approximately 5%. If the error is higher than 5%, communication will be unreliable/impossible.


Oct 02, 2009, 12:29 am Last Edit: Oct 02, 2009, 12:32 am by mlundin Reason: 1
Yes the FTDI chip has a full speed USB connection to the Linux host, but is has a standard serial connection to the Atmega chip.

The Atmega on the Arduino board can generate some very high baud rates, but the receiver on the FTDI chip must be able to generate the same baudrates and the two must match !

For slow, standard rates, up to 115kb or 230kb this is usually possible.
For higher bitrates it depends a lot on if the sender and receiver bitrates are derived from a similar clock rate.

For instance, the FTDI chips use a base communications bitrate of 6MHz, if the Arduino bitrates are derived from a 8 or 16  MHz clock this makes matching difficult. Then the Linux driver must be able to tell the FTDI-USB serial driver about the bitrate to use, and the driver does not support all bitrates that the Atmega chip can generate.

So, expecting higher bitrates than 230kb to "just work" is VERY optimistic. It is probably possible but not witout a lot of tweaking.

Also serial over USB has typical latencies of the order of a millisecond or two, and for very short messages the FTDI chip can introduce longer latencies up to 16 ms.


Oct 02, 2009, 01:10 am Last Edit: Oct 02, 2009, 10:56 am by RIDDICK Reason: 1
thx for the cool table...  8-)
i always used a formula: (F_CPU/4/rate-1)/2  ::)

with cu (a unix tool) i get 194KiB/sec or above...   :)
now i try to find out, how they configure the device, so that i can look for communication errors...


Oct 02, 2009, 02:08 am Last Edit: Oct 02, 2009, 10:58 am by RIDDICK Reason: 1
yahoo!  [smiley=happy.gif] [smiley=vrolijk_26.gif]

with "tcflush()" and some "c_cc[...]=1" (both taken from the above mentioned uucp package) and with a nice level of -20 it works now:
bytes received: 10200000 errors:0 (0.0%) rate:195.3KiB/sec 1562.5Kib/sec

it seems to be important, that the bytes r read fast enough, because the buffer seems to be too small, so that such log messages show up:
Oct  1 23:52:37 vaako kernel: ttyUSB0: 258 input overrun(s)

hm... doing a blocking read() ensures a low error rate, too (without nice -20)... that will be a multithreaded program...   :-?


ohoh  :-?

indeed (like M Lundin wrote) the round trip time is about 0.015 seconds...
so i will not use handshaking for time-critical things, but stronger error correction capabilities...


I have worked with a guy with a "USB sniffer". We inserted it into the USB connection from the host to an Arduino (Diecimila).

It looked like the FTDI buffer might be 16 bytes; we never saw packets larger than that.

(When the data rate was low, we saw smaller packets were used after a few milliseconds - I think, about 6, but I may be wrong, and it was quicker) .

So, if your Arduino behaves in the same way, and I have understood it correctly :-/, it needs to read the USART quickly enough to empty a 16 byte buffer faster than it can be filled. This sets a limit of your latency.



interesting hint...

when i keep the serial interface busy with many requests (without waiting for a response), i get a data rate of 2.6kByte/sec per direction...


Go Up