I'm trying to test the maximum speed at which I can send data to an Arduino based on the ATMega328p, using a USB to Serial converter like the FT232RL or the ATMega16u2 that is used on the Uno.

I've borrowed some code from here: https://www.pjrc.com/teensy/benchmark_usb_serial_receive.html

I'm using his receive_test code on Windows, to test what I can achieve in terms of sending data to the Arduino, for the sake of using it to control LED strips.

On the Arduino side, I'm testing with the following:

static int count = 0;
unsigned char data = 0;
int led = 13;
// the setup routine runs once when you press reset:
void setup() {
  //UART Initialisation
  UCSR0A |= (1<<U2X0);                                
  UCSR0B |= (1<<RXEN0)  | (1<<TXEN0) | (1<<RXCIE0);   
  UCSR0C |= (1<<UCSZ01) | (1<<UCSZ00)             ; 
  UBRR0H = 0;
  UBRR0L = 3; //Baud Rate 0.5 MBit   --> 0% Error at 16MHz :-)


  static unsigned char b;

  data = b;

byte pinstate = LOW;

void loop() {
  while (count < 500);
  count = 0;
  // toggle pin 2, so the frequency is kbytes/sec
  if (pinstate == LOW) {
    digitalWrite(led, HIGH);
    pinstate = HIGH;
  else {
    digitalWrite(led, LOW);
    pinstate = LOW;

  // Delay for 500 microseconds, to simulate doing
  // something useful with the received data
  //unsigned long beginMicros = micros();
  //while (micros() - beginMicros <= 500); // wait 500 us

In theory it should run at 0.5Mbps (460800 baud). However, on Windows I can only seem to transfer data at up to 12KBps (96Kbps). It transfers at this speed regardless of what the baud rate is set to on the arduino or PC side. Which is weird because if I set it to 9600 baud it should run at 1/10th the speed, but it ALWAYS runs at that speed. The only difference I ever see is that on Linux/Mac it runs at closer to 40KBps.

So, it seems like there is a bottleneck somewhere, but I can't seem to figure out where. Everything I read says it SHOULD be able to run faster than this.

Any thoughts?

  • How do you measure the transfer rate? – jfpoilpret Jul 6 '14 at 5:10
  • 1
    If you want to use this code to measure throughput, at least make count and data volatile variables. – jippie Jul 6 '14 at 6:53
  • Changed it... made no difference. – Adam Haile Jul 6 '14 at 23:36
  • 1
    Do pay attention to the impact of the PC-side buffer size discussion at your link. If possible, try to use a 64 byte (or integral multiple thereof) buffer as that is the typically the native USB transfer size (or an integral multiple thereof). With the discrete FT232 try doing a loopback throughput test with only the USB-serial and PC, no Arduino involved. – Chris Stratton Jul 8 '14 at 19:29
  • I recently ran across a project that uses the FT232R and the ATmega328 with a 2Mbs rate. Both my PC (Windows) and the ATmega328 appear to handle it fine. I'm not sure what could be the cause of what you are seeing, do you have access to an oscilloscope? I'd connect the RX and TX channels and measure the period of the bits at RX and TX. – user3205 Jul 17 '14 at 6:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.