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<NB_CHARS; i++)
{
chars[i] = 66;
}
unsigned long time1, time2;
unsigned long totalTime = 0;
delay(100);
for (int i=0; i<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?