Does micros() return count of the internal timer or the actual execution time

I am newbie in this field trying to implement some code on Arduino Mega. I need to measure the execution time of my code. For that I used the micros() function. But I have a query in this regard. Is the value returned by the micros() function is actually the no. of microseconds taken by the code to be fully executed. Or is it the count of the internal timer which means we need to divide the value returned by micros() by the clock frequency (i.e - 16 MHz) to get the time of execution.

Please help me to solve the query.

It returns a number in microseconds. If you want a number in clock cycles, multiply by 16.

The number comes from Timer 0 which is running at 250 kHz so it's only counts every 4 microseconds anyway.

See: hardware/arduino/cores/arduino/wiring.c

If you want a more precise timer, use one of the other hardware timers and you can count at 16 MHz.

Thanks for solving the query but can you tell me how to implement the timer apart from using micros() function?

Along with Arduino Mega I have implemented the same code on Arduino Due as well. But why is it taking much more time in Due compared to Mega. Can anybody throw some light.

The DUE is a completely different processor. You'd have to show the code for someone to be able to guess why it takes longer on a DUE. Perhaps it is because integers on a DUE are larger than integers on an MEGA?

If you use the Arduino hardware timer you may need to implement it separately for UNO, MEGA and DUE.

Simple Code for DUE

include <stdio.h>

void setup() {
// put your setup code here, to run once:
Serial.begin(115200);

short a = 15;
short b = 20;
short c;
c = a*b;
Serial.print (c);
Serial.print(" ");
unsigned long time = micros();
Serial.print(time);
}

void loop() {
// put your main code here, to run repeatedly:

}

I get an output of 300 2193

Using the same Code for MEGA.
Output is 300 264.

Why is there such a vast difference even for this simple code. I tried changing the int data types to short in Due since int takes 32 bits. But there wasn’t any considerable change in timing.

Please help me out

First off post your code in the proper tags, see the how to use this forum sticky post.

Next this is not timing how long it takes to do anything. What you are doing is timing how long it takes to start the micro. The Due communicates directly through USB and so has to establish contact with the host PC. That is what you are measuring. To measure the speed of any code take the time befor the code and subtract it from the time after the code.

void setup() {
  // put your setup code here, to run once:
Serial.begin(115200);

short a = 15;
short b = 20;
short c;
unsigned long time = micros();  // this will measure the duration of c=a*b
c = a*b;
time = micros() - time;
Serial.print (c);
Serial.print(" ");
Serial.print(time);
}

void loop() {
  // put your main code here, to run repeatedly:
  }

Result (atmega1284p @16MHz):

300 4

Try this code:

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);

  short a = 15;
  short b = 20;
  short c;
  unsigned long time1 = micros();  // this will measure the duration of c=a*b
  for (int i=0; i<1000; i++)
    c = a*b;
  time1 = micros() - time1;
  unsigned long time2 = micros();  // this will measure the duration of c=a*b
  for (int i=0; i<1000; i++)
    ;
  time2 = micros() - time2;
  Serial.print (c);
  Serial.print(" ");
  Serial.print((time1-time2) / 1000.0, 6);
}

void loop() {
  // put your main code here, to run repeatedly:
}

Since the ‘micros()’ timer has a 4 microsecond precision this should give you about a 4 nanosecond precision.

If the answer comes out ‘0.000000’ it’s because the compiler noticed that neither loop did anything useful and optimized them away. Declaring some of the variables ‘volatile’ might get the optimizer to leave the code alone.

Why are we considering the two for loops ( i=0 to 1000)
I may sound stupid but can you please explain.

Thanks a lot.

sohini25: Why are we considering the two for loops ( i=0 to 1000)

So that the code running is much longer than the resolution of the counter.

Thanks a lot. I can understand. But I have one more query.

Suppose if I have a print statement at the end of the code and if we are measuring the time before that will the print statement affect the time measurement in any way?

If I use the below code -

void setup() {
  Serial.begin(115200);
  int number1[5] = {14, 22, 36, 42, 52};
  int number2[5];
  int i;
  
  unsigned long start = micros();
  
  for ( i=0; i<5; i++)
  {
    number2[i] = number1[i] + 2;
  }
  
  unsigned long finish = micros();
  
  Serial.print("Time : ");
  Serial.println(finish - start);
  
  for ( i=0; i<5; i++)
  {
    Serial.print(number2[i]);
    Serial.print(" ");
  }
  

}

void loop() {
  // put your main code here, to run repeatedly: 
  
}

I get output of 12 as execution time.
But when I comment out the Serial.print statements at the end, the execution time is shown as 0.

 void setup() {
  Serial.begin(115200);
  int number1[5] = {14, 22, 36, 42, 52};
  int number2[5];
  int i;
  
  unsigned long start = micros();
  
  for ( i=0; i<5; i++)
  {
    number2[i] = number1[i] + 2;
  }
  
  unsigned long finish = micros();
  
  Serial.print("Time : ");
  Serial.println(finish - start);
  
  for ( i=0; i<5; i++)
  {
    //Serial.print(number2[i]);
    //Serial.print(" ");
  }
  

}

void loop() {
  // put your main code here, to run repeatedly: 
  
}

Can you please explain the reason .

Can you please explain the reason .

Because the compiler optimises away most of the code as it is not being used.
Write the code like this and you will see no difference if you comment out the print statements or not.

  int number1[5] = {14, 22, 36, 42, 52};
  int number2[5];
  int i;
  
void setup() {
  Serial.begin(115200);  
  unsigned long start = micros();
  
  for ( i=0; i<5; i++)
  {
    number2[i] = number1[i] + 2;
  }
  
  unsigned long finish = micros();
  
  Serial.print("Time : ");
  Serial.println(finish - start);
  
  for ( i=0; i<5; i++)
  {
   Serial.print(number2[i]);
   Serial.print(" ");
  }

}

void loop() {
  // put your main code here, to run repeatedly: 
    for ( int i=0; i<5; i++)
  {
    number2[i] = i * 2;
  }

}

Because the compiler optimises away most of the code as it is not being used.
Write the code like this and you will see no difference if you comment out the print statements or not.

As mentioned in the code,

void loop() {
  // put your main code here, to run repeatedly: 
    for ( int i=0; i<5; i++)
  {
    number2[i] = i * 2;
  }

Why are we using this particular piece of code? Can we use any kind of for loop inside the void loop() part to prevent the execution time from being changed by commenting out print statements.

Why are we using this particular piece of code?

You just need some code that uses the variables so that the compiler optimization does not throw away the code you are trying to time because it can see it is not used further. Did you noticed that I changed the variables into global ones so that they would persist outside the setup function?

In your original code you were printing out the values, so the compiler thought you needed the values and did not remove them. When you commented out the printing there was no need for the compiler to keep in the values because they were never used. You have to be careful when doing these tests that you are actually testing what you think you are testing.

Yes I saw that you have made the variables global. I get your point. So I just need to take the variable whose print statement I am commenting out and use that variable in some other place preferably inside the void loop().

Thanks a lot for explaining. :)