Why is Serial.Write that slower when writing x+1 characters than when it is writing x characters? Using Serial.Write() in a time sensitive application. I realize that the number of characters being written not only had an impact on the time spent writing in the buffer, but actually had a bigger impact than expected.

Consider the following sketch, which measures the time it takes to write NB_CHARS characters, using Serial.Write(). I sampled 1000 times in order to get a more reliable measure.

#define NB_CHARS 100

void setup()
{
  Serial.begin(115200);

  uint8_t chars[NB_CHARS];
  for (int i=0; i&lt;NB_CHARS; i++)
  {
    chars[i] = 66;
  }

  unsigned long time1, time2;
  unsigned long totalTime = 0;

  delay(100);

  for (int i=0; i&lt;1000; i++)
  {
    time1 = micros();
    Serial.write(chars, NB_CHARS);
    time2 = micros();
    totalTime += time2 - time1;

    delay(10);
    Serial.println("");
    delay(10);
  }

  float meanTime = (float)totalTime / 1000.0f;
  Serial.print("meanTime = ");
  Serial.println(meanTime);
}

void loop()
{

}


Here are some results for different NB_CHARS values:

NB_CHARS: Time (microseconds)
1: 12
2: 18
3: 24
[...]
99: 2912
100: 2997
101: 3082
[...]
199: 11412
200: 11497
201: 11582


It seems that at first, each new character adds around 6 microseconds of delay, but afterward it becomes 85 microseconds. I tested every values from 1 to 100 to find where it changes and it seems to be right after 70:



It seems weird to me.

A quick Google search gets me to this 2013 post by Tom Carpenter. I am not sure how true this is or if it is still relevant.


  Part of the trouble is that the Hardware Serial library is so
  incredibly inefficient (I don't think they could have made it less
  efficient if they tried!). After each byte is sent, there is an
  interrupt called which spends a lifetime loading the next byte into
  the buffer to send. The write function also wastes lots of time doing
  calculations as to where to put a character in a ring buffer.
  
  [...]


Why is there such a "long" delay for each character and is there a way to make it faster?

What happens after 70 characters that slows it down even further?
The Arduino core has a 64 byte transmission buffer.  Characters are sent out of that buffer by the hardware.

When you blast lots of characters out of serial the first 64 just get put into that buffer - almost instantly.

Once that buffer is full your sketch blocks until the hardware has sent a character to make room.

Since it's sending right from the moment you place the first character into the buffer you get a little more than 64 bytes worth of buffering time (64 + the number that have been sent by the time the buffer fills).

From that point on you are entirely at the mercy of the baud rate you have chosen.

To get more predictable throughput (and maximise the speed) you should bypass the Ardiuno core and manipulate the UART registers directly.