Serial line speed - a basic question

Hello Everyone,

I completely new to Arduino so apologies in advance for the basic questions. Hopefully they'll get more complex with time!

I'm experimenting with my new Uno and have been checking out the time taken for the code to execute serial line commands.

Consider the following code:

unsigned long count = 0;
unsigned long bookmark = 0;

void setup()
{
  Serial.begin(115200);
  bookmark = micros() + 1000000;
}

void loop()
{
  count++;
  if(micros() >= bookmark)
  {
    Serial.print(count, DEC);
    Serial.println(" counts achieved");
    count = 0;
    bookmark = micros() + 1000000;
  }
}

I have deduced from the average output of 129284 counts that the Loop handling, increment and if statement comparison takes 7.545us each cycle.

Now consider the following with an extra Serial.println line:

unsigned long count = 0;
unsigned long bookmark = 0;

void setup()
{
  Serial.begin(115200);
  bookmark = micros() + 1000000;
}

void loop()
{
  count++;
  Serial.println(count,DEC);
  if(micros() >= bookmark)
  {
    Serial.print(count, DEC);
    Serial.println(" counts achieved");
    count = 0;
    bookmark = micros() + 1000000;
  }
}

By introducing the extra serial command I am reduced to 2146 counts, thus implying that Loop handling, increment, if statement comparison AND Serial.println takes 465.98us each time

This means that the serial command, on its own, takes 458.435us, which seems massive in comparison.

My question, therefore... Am I right in my conclusion that the serial line is a massive bottleneck and should be avoided if fast execution is a must?

Are there any other protocols that would similarly hold up my code? - I2C, USB, etc? What would be recommended for speed?

Many thanks in advance,

Tim

Yes, serial is a bottleneck.

There is an output buffer which is filled by the Serial.print and Serial.println functions. When this fills up (as it will do rapidly, it's only small), then all subsequent prints will block until there is enough room in the output buffer (emptied at leisure by the serial interrupt) to take more characters. The slower the serial connection, the longer this will take.

Thirty years ago we connected terminals to computers and were happy when we moved from 300 Bd to 9600 Bd, because that was faster than you can read. ( We even started to draw fancy boxes around texts, because it was that fast. )

But of course your observation is correct: Serial is slow, you should take that into account.

  • Never assume the whole text has arrived, just because there's something available().

  • loop() has the chance to do a lot of other stuff while data is arriving.

  • You can set speed to "incredible" rates. 115200 baud is just the default max in Serial Monitor, you could go even higher if the other side (and the line) allows.

  • There's a limited read and a write buffer, but there's no hardware handshake signal.

  • While you don't reach the write buffer limits, your loop remains fast.

  • Baud is bit/sec and a byte or char is 10 bit, when transmitted via Serial.
    (115200 = 11,500 char/sec) If you really need that speed, perhaps sending binary data instead of asccii text reduces size considerably.

BTW: Without Serial.begin() , loop() can be even faster, if it's just for counting.

Thanks very much for the responses!

My project is essentially a UAV using Raspberry Pi (non-time critical stuff) and an Arduino (time critical stuff) connected via I2C, hopefully. I want to do all the sensor integration and control laws myself though, rather than get an ArduIMU and ArduPilot. The learning is the fun part!

As a result of your answers I'm going to hook my GPS (serial line) up to the Raspberry Pi and have the data sent to the Arduino by I2C when ready.

Thanks again,

Tim

As a result of your answers I'm going to hook my GPS (serial line) up to the Raspberry

What does your GPS module send at which speed ?
The ones I know send "sometimes" a little ascii text at 4800 Bd, which would leave a lot of free time for an ATMega328.
Of course you should not try to draw a map with an Arduino.

Hello Michael,

I'm using an EM-406a which operates at 4,800 Bd. The Arduino will be used mainly for two purposes:

  1. Sampling gyros, accels, mags and doing IMU calcs
  2. Running control laws

According to the experts at work (I work in Aerospace) item 1 will need a very high sample rate to reduce gyro integration error. Thus I can't really afford to wait around for a serial line to complete its business. I plan to use the Raspberry Pi which, among its other jobs, will send a discrete to the Arduino to signal 'data ready', at which point the Arduino will retrieve the fresh data over i2c.

That's the plan for now, at least!

Cheers,

Tim

I can't really afford to wait around for a serial line to complete its business.

It won't wait for a serial line. ( At least it does not have to, and it should not )

But I agree, you have to handle each character, which is more load than dealing with preprocessed data.

  1. Sampling gyros, accels, mags and doing IMU calcs
  2. Running control laws

... should run at a higher priority, timer or external interrupt driven, correct.
Is a 16MHz Arduino fast enough ? Minimal loop time > 5µs, analog read ~ 100µs ( can be handled interrupt driven, though )

I like scrutiny - increases the chances of this thing actually working some day in the distant future! :slight_smile:

I'm getting hold of a Pololu MinIMU which has an i2c interface => no analogue reads required (I think!)

With regard to clock speed, I'm going to see what sort of sample rate (and thus accuracy) I achieve with my Arduino Uno. For ~£25 it's worth giving it a good shot, even if it needs upgrading in the end - I'd be able to use mostly the same code, so no real waste of time... Hopefully!

Tim

i2c is very convenient from a wiring standpoint but not fast depending on your definition of "fast".

Keep in mind that the default clock of i2c in arduino is not very fast at 400k/sec.
That is moving data slower than the async serial port at 115200 especially when you consider the i2c overhead.

--- bill