0

Case specifications:

  • PC OS: Debian 9, x64 arch
  • Starting time point: i have a 1kb buffer on arduino that i want to send to host PC
  • Ending time point: i have recieved the buffer in a custom written C\C++ app running on a host PC
  • I want to send such a buffer once a second

What is the minimal possible latency - time passed between starting and ending points? and with what communication type? (serial?)

8
  • 1
    Depends on what Arduino.
    – Majenko
    May 9, 2018 at 23:18
  • Best chance would be via Serial (i.e. USB-UART bridge) and the highest possible baud-rate (about 1 Megabit). If your MCU has WiFi or LAN maybe that's even faster, but we can't tell because you didn't tell us what MCU you are running on. May 9, 2018 at 23:34
  • We would also need to know exactly what you mean by serial. USB->USB? TTL->RS232?
    – RubberDuck
    May 10, 2018 at 0:45
  • i have none by hand, otherwise i could write simple ping test and measure it by myself
    – xakepp35
    May 10, 2018 at 7:07
  • 1
    Isochronous USB transfers have the lowest latency. I don't, though, think latency is the term you are after.
    – Majenko
    May 10, 2018 at 8:58

2 Answers 2

4

There is more to low-latency communication than just squirting data as fast as you can (though that is an important part of it).

One thing people often forget is that the Arduino can only (easily) do one thing at a time. While you're sending your buffer to the PC it can't be sampling and filling your buffer. If you have a buffer which fills up over the period of 1 second and you want to send that buffer to the PC when full, what happens during the subsequent second while you're sending the buffer? The buffer can't be being filled while it's being sent.

Using a normal UART to USB connection as most of the normal Arduino boards (Uno, Mega, etc) use the fastest you can reasonably expect is around 1MBaud. That's about 100kB/s. Less if you use a cheap Chinese clone with a CH340G. Even at 100kB/s your 1kB buffer, if sent completely raw and in binary, would take around 10ms to transfer. But getting the computer to make any sense of that raw data would be hard. So you'd need to wrap it in some form of protocol (up to you to design that...) so you may get half that speed (or worse depending on your protocol design).

And during that time not much else can happen.

For smooth low-latency communication of data it is much more preferable to use "ping-pong" buffers and interrupt- or DMA-driven sampling of your data. That means that one buffer is receiving your data from whatever source, and the other is being sent to the PC. Once the first buffer is filled up they reverse roles. However, the little 8-bit Arduinos aren't really suited for that kind of thing:

  • They don't have much RAM to waste on two buffers
  • They don't have interrupts with priorities to allow samples to occur while sending
  • They don't have DMA to do background transfers of data to/from peripherals

If latency is really that critical you would be better using one of the ARM-based Arduinos, such as the Due, where you can also then take advantage of a high-speed native USB interface which can give much higher throughput than a UART connection. Your choice of USB endpoint can also influence the latency of your design:

  • Isochronous - Lowest latency, small packets, not guaranteed to be delivered
  • Interrupt - Medium latency, small packets, delivery guaranteed
  • Bulk - High latency, large packets, delivery guaranteed

Isochronous is used mainly for audio where you would notice the slightest delay in sound, but wouldn't necessarily notice or worry about a slight glitch in the quality. Interrupt is used for things like HID where you need it to respond to you pressing the keys on your keyboard nice and fast, but you're never sending much data (64 byte packet limit on interrupt transfers). Bulk is used for things like CDC/ACM (Serial over USB) where you may want to tranfer lots of data but wouldn't notice if it's pausing for a few ms every now and then (HS USB has a 512 byte packet limit on bulk transfers, FS USB has a 64 byte limit).

One of the great things with a direct USB connection is that underneath it is all packet-based, so you can use that as your transfer protocol if you know what you're doing. Don't just rely on the CDC/ACM "pipe", but instead make use of the underlying USB protocol to send individual packets which the receiving program can then understand and break apart into the right data without adding any extra protocol overheads.

For more advanced USB programming the Teensy and chipKIT cores have far more sophisticated USB support than the Arduino core, so you may fancy taking a look at their offerings in the way of boards that may suit your needs better.

1
  • Thanks for such a great academic answer. Now i can formulate thing in a correct terms. I am interested in measuring USB RTT (or ping time) when operating with bidirectional Isochronous design in mind. For example, i can send like 8-byte packets with timestamp inside from host pc, and recieve it back to measure RTT, just like in ICMP echo. I bought MEGA 2560 board yesterday for that purpose. I was quite interested - what numbers could i see and is it suitable for realtime operations where decision logic is offloaded from arduino to more powerful PCs\GPUs?
    – xakepp35
    May 11, 2018 at 7:17
0

it is not exactly what you ask, but yesterday I tested the speed with this sketch:

void setup() {
  Serial.begin(460800);
  delay(5000);
}

void loop() {
  Serial.println();
  unsigned long start = millis();
  for (unsigned long i = 0; i < 1000000L; i++) {
    Serial.write('A');
  }
  Serial.flush();
  Serial.println();
  Serial.println(millis() - start);
  while(true);
}

to receive on linux to file:

stty -F /dev/ttyACM0 460800
(stty raw; cat > received.txt) < /dev/ttyACM0

the sketch measured 20000 ms to push that 1MB over Serial. the Arduino is Mega 2560. at 921600 baud not all data were transfered.

EDIT: Nano 328p clone with CH340 complete only at 230400 baud in 45000 ms

2
  • could you run some simple ping (RTT) test for me please? i have no platform by hands. test is the following: 1) arduino must send back just what it recieves, and 2) host runs clock_gettime() to get its current 64-bit timestamp and sends it to arduino, and 3) when it recieves timestamp difference (RTT) and displays it.
    – xakepp35
    May 10, 2018 at 7:14
  • clock_gettime() has near microseconds precision so its would be good estimate of RTT for realtime application
    – xakepp35
    May 10, 2018 at 7:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.