Why is Serial.Write that slower when writing x+1 characters than when it is writing x characters?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
4
down vote

favorite












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:



Serial.Write() delay as a function of number of chars



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?










share|improve this question























  • set higher baud rate. at least 460800 baud should go with good connections.
    – Juraj
    Sep 10 at 20:18










  • the quote is not true anymore. at bit rates over 500kbit/s the interrupt is not used if the buffer is empty. (bit rate, not baud rate)
    – Juraj
    Sep 10 at 20:21















up vote
4
down vote

favorite












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:



Serial.Write() delay as a function of number of chars



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?










share|improve this question























  • set higher baud rate. at least 460800 baud should go with good connections.
    – Juraj
    Sep 10 at 20:18










  • the quote is not true anymore. at bit rates over 500kbit/s the interrupt is not used if the buffer is empty. (bit rate, not baud rate)
    – Juraj
    Sep 10 at 20:21













up vote
4
down vote

favorite









up vote
4
down vote

favorite











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:



Serial.Write() delay as a function of number of chars



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?










share|improve this question















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:



Serial.Write() delay as a function of number of chars



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?







serial performance






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Sep 11 at 8:29









Peter Mortensen

288211




288211










asked Sep 10 at 18:45









Alex Millette

1264




1264











  • set higher baud rate. at least 460800 baud should go with good connections.
    – Juraj
    Sep 10 at 20:18










  • the quote is not true anymore. at bit rates over 500kbit/s the interrupt is not used if the buffer is empty. (bit rate, not baud rate)
    – Juraj
    Sep 10 at 20:21

















  • set higher baud rate. at least 460800 baud should go with good connections.
    – Juraj
    Sep 10 at 20:18










  • the quote is not true anymore. at bit rates over 500kbit/s the interrupt is not used if the buffer is empty. (bit rate, not baud rate)
    – Juraj
    Sep 10 at 20:21
















set higher baud rate. at least 460800 baud should go with good connections.
– Juraj
Sep 10 at 20:18




set higher baud rate. at least 460800 baud should go with good connections.
– Juraj
Sep 10 at 20:18












the quote is not true anymore. at bit rates over 500kbit/s the interrupt is not used if the buffer is empty. (bit rate, not baud rate)
– Juraj
Sep 10 at 20:21





the quote is not true anymore. at bit rates over 500kbit/s the interrupt is not used if the buffer is empty. (bit rate, not baud rate)
– Juraj
Sep 10 at 20:21











3 Answers
3






active

oldest

votes

















up vote
12
down vote



accepted










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.






share|improve this answer




















  • "you should bypass the Ardiuno core and manipulate the UART registers directly". Any good library for this?
    – Alex Millette
    Sep 10 at 18:59






  • 5




    @AlexMillette Ummm... no. That's the whole point. You will be avoiding any library / core functions and using the registers directly. Read the datasheet.
    – Majenko♦
    Sep 10 at 19:02






  • 2




    I think it would be handy @Majenko if you could point Alex at some example code....
    – boatcoder
    Sep 11 at 1:25






  • 3




    There is a fair chance that once you bypass the core, your code will run as slow as the right part, and not as fast as the left one.
    – IMil
    Sep 11 at 3:27






  • 1




    For smooth serial communication you really want an MCU with DMA to do the transfers for you...
    – Majenko♦
    Sep 11 at 9:21

















up vote
3
down vote













Majenko already gave the right answer: as soon as the buffer is full, everything falls apart (for a time sensitive application).



It is possible to enlarge the serial buffer for your project. However, in the future, with a new Arduino version, you might have forgotten that you have changed a library and the project does no longer work that well.



I want to point out that you can use the usb serial port that is inside some microcontrollers and processors. That is not a real serial uart with a baudrate and a clock, but a usb CDC device.

A atmega32u4 and the arm m0+ have such a usb CDC serial port.

The arduino leonardo, micro and pro micro use the atmega32u4.

The arduino zero, m0, mkr series use the arm m0+ processor.



What about these numbers:



NB_CHARS: Time (microsec)
1: 6.93
2: 7.60
3: 8.06
[...]
99: 153
100: 154
101: 152
[...]
199: 1685
200: 1624
201: 1705


That is with a arm m0+ processor. I used the same sketch as you, but I changed the Serial to SerialUSB.






share|improve this answer



























    up vote
    2
    down vote













    Your "long" delay is not too long at all.



    If you measure the throughput of the right part, you have about 30 characters sent in 2500 microseconds. This means the rate is roughly (30 * 8 * 1,000,000) / 2500, which is 96,000 bits/sec.



    It's a bit less than 115,200 you specified, but serial protocols use service bits, so in fact you'd have to replace 8 with 10. This gives 120,000 baud which is within measurement error.



    The left part is actually much faster than you required, but as @Majenko correctly noticed, this is thanks to buffering. Apparently, you can increase the buffer size up to 256 bytes. If you need consistency instead of maximum speed, you may decrease the buffer size instead.



    Finally, you should test performance in a realistic scenario. In your example you just keep sending data in a loop; obviously you soon fill up the buffer and run into port speed limit. However, in real life your loop would probably read some input, do some calculations, then send the result. In this case, you'd be using the buffer more effectively.






    share|improve this answer






















      Your Answer





      StackExchange.ifUsing("editor", function ()
      return StackExchange.using("schematics", function ()
      StackExchange.schematics.init();
      );
      , "cicuitlab");

      StackExchange.ready(function()
      var channelOptions =
      tags: "".split(" "),
      id: "540"
      ;
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function()
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled)
      StackExchange.using("snippets", function()
      createEditor();
      );

      else
      createEditor();

      );

      function createEditor()
      StackExchange.prepareEditor(
      heartbeatType: 'answer',
      convertImagesToLinks: false,
      noModals: false,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: null,
      bindNavPrevention: true,
      postfix: "",
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      );



      );













       

      draft saved


      draft discarded


















      StackExchange.ready(
      function ()
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2farduino.stackexchange.com%2fquestions%2f55993%2fwhy-is-serial-write-that-slower-when-writing-x1-characters-than-when-it-is-writ%23new-answer', 'question_page');

      );

      Post as a guest






























      3 Answers
      3






      active

      oldest

      votes








      3 Answers
      3






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes








      up vote
      12
      down vote



      accepted










      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.






      share|improve this answer




















      • "you should bypass the Ardiuno core and manipulate the UART registers directly". Any good library for this?
        – Alex Millette
        Sep 10 at 18:59






      • 5




        @AlexMillette Ummm... no. That's the whole point. You will be avoiding any library / core functions and using the registers directly. Read the datasheet.
        – Majenko♦
        Sep 10 at 19:02






      • 2




        I think it would be handy @Majenko if you could point Alex at some example code....
        – boatcoder
        Sep 11 at 1:25






      • 3




        There is a fair chance that once you bypass the core, your code will run as slow as the right part, and not as fast as the left one.
        – IMil
        Sep 11 at 3:27






      • 1




        For smooth serial communication you really want an MCU with DMA to do the transfers for you...
        – Majenko♦
        Sep 11 at 9:21














      up vote
      12
      down vote



      accepted










      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.






      share|improve this answer




















      • "you should bypass the Ardiuno core and manipulate the UART registers directly". Any good library for this?
        – Alex Millette
        Sep 10 at 18:59






      • 5




        @AlexMillette Ummm... no. That's the whole point. You will be avoiding any library / core functions and using the registers directly. Read the datasheet.
        – Majenko♦
        Sep 10 at 19:02






      • 2




        I think it would be handy @Majenko if you could point Alex at some example code....
        – boatcoder
        Sep 11 at 1:25






      • 3




        There is a fair chance that once you bypass the core, your code will run as slow as the right part, and not as fast as the left one.
        – IMil
        Sep 11 at 3:27






      • 1




        For smooth serial communication you really want an MCU with DMA to do the transfers for you...
        – Majenko♦
        Sep 11 at 9:21












      up vote
      12
      down vote



      accepted







      up vote
      12
      down vote



      accepted






      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.






      share|improve this answer












      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.







      share|improve this answer












      share|improve this answer



      share|improve this answer










      answered Sep 10 at 18:49









      Majenko♦

      62.3k42773




      62.3k42773











      • "you should bypass the Ardiuno core and manipulate the UART registers directly". Any good library for this?
        – Alex Millette
        Sep 10 at 18:59






      • 5




        @AlexMillette Ummm... no. That's the whole point. You will be avoiding any library / core functions and using the registers directly. Read the datasheet.
        – Majenko♦
        Sep 10 at 19:02






      • 2




        I think it would be handy @Majenko if you could point Alex at some example code....
        – boatcoder
        Sep 11 at 1:25






      • 3




        There is a fair chance that once you bypass the core, your code will run as slow as the right part, and not as fast as the left one.
        – IMil
        Sep 11 at 3:27






      • 1




        For smooth serial communication you really want an MCU with DMA to do the transfers for you...
        – Majenko♦
        Sep 11 at 9:21
















      • "you should bypass the Ardiuno core and manipulate the UART registers directly". Any good library for this?
        – Alex Millette
        Sep 10 at 18:59






      • 5




        @AlexMillette Ummm... no. That's the whole point. You will be avoiding any library / core functions and using the registers directly. Read the datasheet.
        – Majenko♦
        Sep 10 at 19:02






      • 2




        I think it would be handy @Majenko if you could point Alex at some example code....
        – boatcoder
        Sep 11 at 1:25






      • 3




        There is a fair chance that once you bypass the core, your code will run as slow as the right part, and not as fast as the left one.
        – IMil
        Sep 11 at 3:27






      • 1




        For smooth serial communication you really want an MCU with DMA to do the transfers for you...
        – Majenko♦
        Sep 11 at 9:21















      "you should bypass the Ardiuno core and manipulate the UART registers directly". Any good library for this?
      – Alex Millette
      Sep 10 at 18:59




      "you should bypass the Ardiuno core and manipulate the UART registers directly". Any good library for this?
      – Alex Millette
      Sep 10 at 18:59




      5




      5




      @AlexMillette Ummm... no. That's the whole point. You will be avoiding any library / core functions and using the registers directly. Read the datasheet.
      – Majenko♦
      Sep 10 at 19:02




      @AlexMillette Ummm... no. That's the whole point. You will be avoiding any library / core functions and using the registers directly. Read the datasheet.
      – Majenko♦
      Sep 10 at 19:02




      2




      2




      I think it would be handy @Majenko if you could point Alex at some example code....
      – boatcoder
      Sep 11 at 1:25




      I think it would be handy @Majenko if you could point Alex at some example code....
      – boatcoder
      Sep 11 at 1:25




      3




      3




      There is a fair chance that once you bypass the core, your code will run as slow as the right part, and not as fast as the left one.
      – IMil
      Sep 11 at 3:27




      There is a fair chance that once you bypass the core, your code will run as slow as the right part, and not as fast as the left one.
      – IMil
      Sep 11 at 3:27




      1




      1




      For smooth serial communication you really want an MCU with DMA to do the transfers for you...
      – Majenko♦
      Sep 11 at 9:21




      For smooth serial communication you really want an MCU with DMA to do the transfers for you...
      – Majenko♦
      Sep 11 at 9:21










      up vote
      3
      down vote













      Majenko already gave the right answer: as soon as the buffer is full, everything falls apart (for a time sensitive application).



      It is possible to enlarge the serial buffer for your project. However, in the future, with a new Arduino version, you might have forgotten that you have changed a library and the project does no longer work that well.



      I want to point out that you can use the usb serial port that is inside some microcontrollers and processors. That is not a real serial uart with a baudrate and a clock, but a usb CDC device.

      A atmega32u4 and the arm m0+ have such a usb CDC serial port.

      The arduino leonardo, micro and pro micro use the atmega32u4.

      The arduino zero, m0, mkr series use the arm m0+ processor.



      What about these numbers:



      NB_CHARS: Time (microsec)
      1: 6.93
      2: 7.60
      3: 8.06
      [...]
      99: 153
      100: 154
      101: 152
      [...]
      199: 1685
      200: 1624
      201: 1705


      That is with a arm m0+ processor. I used the same sketch as you, but I changed the Serial to SerialUSB.






      share|improve this answer
























        up vote
        3
        down vote













        Majenko already gave the right answer: as soon as the buffer is full, everything falls apart (for a time sensitive application).



        It is possible to enlarge the serial buffer for your project. However, in the future, with a new Arduino version, you might have forgotten that you have changed a library and the project does no longer work that well.



        I want to point out that you can use the usb serial port that is inside some microcontrollers and processors. That is not a real serial uart with a baudrate and a clock, but a usb CDC device.

        A atmega32u4 and the arm m0+ have such a usb CDC serial port.

        The arduino leonardo, micro and pro micro use the atmega32u4.

        The arduino zero, m0, mkr series use the arm m0+ processor.



        What about these numbers:



        NB_CHARS: Time (microsec)
        1: 6.93
        2: 7.60
        3: 8.06
        [...]
        99: 153
        100: 154
        101: 152
        [...]
        199: 1685
        200: 1624
        201: 1705


        That is with a arm m0+ processor. I used the same sketch as you, but I changed the Serial to SerialUSB.






        share|improve this answer






















          up vote
          3
          down vote










          up vote
          3
          down vote









          Majenko already gave the right answer: as soon as the buffer is full, everything falls apart (for a time sensitive application).



          It is possible to enlarge the serial buffer for your project. However, in the future, with a new Arduino version, you might have forgotten that you have changed a library and the project does no longer work that well.



          I want to point out that you can use the usb serial port that is inside some microcontrollers and processors. That is not a real serial uart with a baudrate and a clock, but a usb CDC device.

          A atmega32u4 and the arm m0+ have such a usb CDC serial port.

          The arduino leonardo, micro and pro micro use the atmega32u4.

          The arduino zero, m0, mkr series use the arm m0+ processor.



          What about these numbers:



          NB_CHARS: Time (microsec)
          1: 6.93
          2: 7.60
          3: 8.06
          [...]
          99: 153
          100: 154
          101: 152
          [...]
          199: 1685
          200: 1624
          201: 1705


          That is with a arm m0+ processor. I used the same sketch as you, but I changed the Serial to SerialUSB.






          share|improve this answer












          Majenko already gave the right answer: as soon as the buffer is full, everything falls apart (for a time sensitive application).



          It is possible to enlarge the serial buffer for your project. However, in the future, with a new Arduino version, you might have forgotten that you have changed a library and the project does no longer work that well.



          I want to point out that you can use the usb serial port that is inside some microcontrollers and processors. That is not a real serial uart with a baudrate and a clock, but a usb CDC device.

          A atmega32u4 and the arm m0+ have such a usb CDC serial port.

          The arduino leonardo, micro and pro micro use the atmega32u4.

          The arduino zero, m0, mkr series use the arm m0+ processor.



          What about these numbers:



          NB_CHARS: Time (microsec)
          1: 6.93
          2: 7.60
          3: 8.06
          [...]
          99: 153
          100: 154
          101: 152
          [...]
          199: 1685
          200: 1624
          201: 1705


          That is with a arm m0+ processor. I used the same sketch as you, but I changed the Serial to SerialUSB.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Sep 10 at 22:38









          Jot

          1,647416




          1,647416




















              up vote
              2
              down vote













              Your "long" delay is not too long at all.



              If you measure the throughput of the right part, you have about 30 characters sent in 2500 microseconds. This means the rate is roughly (30 * 8 * 1,000,000) / 2500, which is 96,000 bits/sec.



              It's a bit less than 115,200 you specified, but serial protocols use service bits, so in fact you'd have to replace 8 with 10. This gives 120,000 baud which is within measurement error.



              The left part is actually much faster than you required, but as @Majenko correctly noticed, this is thanks to buffering. Apparently, you can increase the buffer size up to 256 bytes. If you need consistency instead of maximum speed, you may decrease the buffer size instead.



              Finally, you should test performance in a realistic scenario. In your example you just keep sending data in a loop; obviously you soon fill up the buffer and run into port speed limit. However, in real life your loop would probably read some input, do some calculations, then send the result. In this case, you'd be using the buffer more effectively.






              share|improve this answer


























                up vote
                2
                down vote













                Your "long" delay is not too long at all.



                If you measure the throughput of the right part, you have about 30 characters sent in 2500 microseconds. This means the rate is roughly (30 * 8 * 1,000,000) / 2500, which is 96,000 bits/sec.



                It's a bit less than 115,200 you specified, but serial protocols use service bits, so in fact you'd have to replace 8 with 10. This gives 120,000 baud which is within measurement error.



                The left part is actually much faster than you required, but as @Majenko correctly noticed, this is thanks to buffering. Apparently, you can increase the buffer size up to 256 bytes. If you need consistency instead of maximum speed, you may decrease the buffer size instead.



                Finally, you should test performance in a realistic scenario. In your example you just keep sending data in a loop; obviously you soon fill up the buffer and run into port speed limit. However, in real life your loop would probably read some input, do some calculations, then send the result. In this case, you'd be using the buffer more effectively.






                share|improve this answer
























                  up vote
                  2
                  down vote










                  up vote
                  2
                  down vote









                  Your "long" delay is not too long at all.



                  If you measure the throughput of the right part, you have about 30 characters sent in 2500 microseconds. This means the rate is roughly (30 * 8 * 1,000,000) / 2500, which is 96,000 bits/sec.



                  It's a bit less than 115,200 you specified, but serial protocols use service bits, so in fact you'd have to replace 8 with 10. This gives 120,000 baud which is within measurement error.



                  The left part is actually much faster than you required, but as @Majenko correctly noticed, this is thanks to buffering. Apparently, you can increase the buffer size up to 256 bytes. If you need consistency instead of maximum speed, you may decrease the buffer size instead.



                  Finally, you should test performance in a realistic scenario. In your example you just keep sending data in a loop; obviously you soon fill up the buffer and run into port speed limit. However, in real life your loop would probably read some input, do some calculations, then send the result. In this case, you'd be using the buffer more effectively.






                  share|improve this answer














                  Your "long" delay is not too long at all.



                  If you measure the throughput of the right part, you have about 30 characters sent in 2500 microseconds. This means the rate is roughly (30 * 8 * 1,000,000) / 2500, which is 96,000 bits/sec.



                  It's a bit less than 115,200 you specified, but serial protocols use service bits, so in fact you'd have to replace 8 with 10. This gives 120,000 baud which is within measurement error.



                  The left part is actually much faster than you required, but as @Majenko correctly noticed, this is thanks to buffering. Apparently, you can increase the buffer size up to 256 bytes. If you need consistency instead of maximum speed, you may decrease the buffer size instead.



                  Finally, you should test performance in a realistic scenario. In your example you just keep sending data in a loop; obviously you soon fill up the buffer and run into port speed limit. However, in real life your loop would probably read some input, do some calculations, then send the result. In this case, you'd be using the buffer more effectively.







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Sep 11 at 13:16

























                  answered Sep 11 at 3:55









                  IMil

                  1213




                  1213



























                       

                      draft saved


                      draft discarded















































                       


                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2farduino.stackexchange.com%2fquestions%2f55993%2fwhy-is-serial-write-that-slower-when-writing-x1-characters-than-when-it-is-writ%23new-answer', 'question_page');

                      );

                      Post as a guest













































































                      這個網誌中的熱門文章

                      How to combine Bézier curves to a surface?

                      Why am i infinitely getting the same tweet with the Twitter Search API?

                      Carbon dioxide