Pages: [1]   Go Down
Author Topic: Exactly... How fast is Arduino?  (Read 1410 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 1
Posts: 27
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm implementing a PID controller (similar to this one http://www.arduino.cc/playground/Main/BarebonesPIDForEspresso) on my Arduino and I'd like to use a sampling time of 1ms (frequency = 1 kHz).

I've read that Arduino runs at 16 MHz (btw is that true?) and I thought it would not be a problem to execute (more or less) 60 float operations every 1 ms: it indeed is a problem and I have to slow down to 250 Hz (once every 4 ms).


Do you think that this is an expected result?
Thanks  smiley
Logged

Forum Administrator
Offline Offline
Newbie
*****
Karma: 3
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello

Why would you not believe it runs at 16MHz? smiley


If you are using an original arduino  you can see by yourself by looking at the quartz next to the processor.
It should say S16B00K7 the 16 means 16MHz

in terms of floating point speed it all depends on the quality of the software implementation as the processor doesn't have a floating point coprocessor

we are using the one that comes with avr-gcc so you should check if there is any indication on the avr-libc website

massimo


Logged

0
Offline Offline
Newbie
*
Karma: 1
Posts: 27
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Hello
Why would you not believe it runs at 16MHz? smiley
Simply because I didn't read it on the datasheet... but I guess I can trust Massimo!  smiley-wink

Quote
If you are using an original arduino  you can see by yourself by looking at the quartz next to the processor.
It should say S16B00K7 the 16 means 16MHz
Nice!

Quote
in terms of floating point speed it all depends on the quality of the software implementation as the processor doesn't have a floating point coprocessor
we are using the one that comes with avr-gcc so you should check if there is any indication on the avr-libc website
The question is... how may cycles might it take to sum or multiply two floats?
I've found a few documents (page 34 of http://manet.die.udec.cl/~biomedica/senales/avr-libc-user-manual-1.6.1.pdf and http://www.nongnu.org/avr-libc/user-manual/group__avr__math.html) but they're not useful for my purpose.

...Any idea?


PS: I thought I might calculate how much time it takes for two floats to be added or multiplied but I need a more precise version of the millis() function... does a version of millis() that work with microseconds (instead of milliseconds) exist?
Thank you.
Logged

London
Offline Offline
Faraday Member
**
Karma: 10
Posts: 6248
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote

PS: I thought I might calculate how much time it takes for two floats to be added or multiplied but I need a more precise version of the millis() function... does a version of millis() that work with microseconds (instead of milliseconds) exist?
Thank you.
You can use timer1 which can be accurate to a fraction of a microsecond but its easier just doing a  big loop of floating points and using millis. If you do a say ten thousand fp operations you should get a pretty good estimate of how long one would take
Logged

0
Offline Offline
Newbie
*
Karma: 1
Posts: 27
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
You can use timer1 which can be accurate to a fraction of a microsecond but its easier just doing a  big loop of floating points and using millis. If you do a say ten thousand fp operations you should get a pretty good estimate of how long one would take

I used a program to separately calculate ADD and MULT time.
The results were: 12 microseconds and 5 microseconds respectively.

My code has 28 multiplies and 36 sums for a total of 572 microseconds.
In addition it must be considered that I'm working with matrixes and that I'm handling 4 PWM outputs and one analog input.

...Is it enough to exceed 3 milliseconds?


PS:
This is the code I wrote (the printDouble function was created by mem!):
Code:
float val = 0.03;
float add = 0.012;
float mult = 1.008;
float time = 0;
int prec = 30000;
long start = 0;
long end = 0;
long total = 0;

void setup() {
  digitalWrite(13, HIGH);
}


void loop() {
  
  //ADD
  start =  millis();
  for( int i = 1;  i < prec;  i++ ) {
    val = val + add;
  }
  end = millis();
  total = end - start;
  
  Serial.begin(9600);
  Serial.print("It has taken ");
  Serial.print( total );
  Serial.println(" milliseconds in total.");
  time = (total*1000)/prec;
  printDouble( time, 6 );
  Serial.println(" microseconds per one ADD");
  
  
  //MULTIPLY
  start =  millis();
  for( int i = 1;  i < prec;  i++ ) {
    val = val*mult;
  }
  end = millis();
  total = end - start;
  
  Serial.begin(9600);
  Serial.print("It has taken ");
  Serial.print( total );
  Serial.println(" milliseconds in total.");
  time = (total*1000)/prec;
  printDouble( time, 6 );
  Serial.println(" microseconds per one MULT");
  
  
  digitalWrite(13, LOW);
  while(1);
}


void printDouble( double val, byte precision){
  // prints val with number of decimal places determine by precision
  // precision is a number from 0 to 6 indicating the desired decimial places
  // example: printDouble( 3.1415, 2); // prints 3.14 (two decimal places)

  Serial.print (int(val));  //prints the int part
  if( precision > 0) {
    Serial.print("."); // print the decimal point
    unsigned long frac;
    unsigned long mult = 1;
    byte padding = precision -1;
    while(precision--)
       mult *=10;
      
    if(val >= 0)
      frac = (val - int(val)) * mult;
    else
      frac = (int(val)- val ) * mult;
    unsigned long frac1 = frac;
    while( frac1 /= 10 )
      padding--;
    while(  padding--)
      Serial.print("0");
    Serial.print(frac,DEC) ;
  }
}
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 59
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This may or may not be a valid thought, but doesn't using a for loop add overhead, so you're not getting an accurate result for how long it takes to do a multiple or add?
Logged

Las Vegas, NV
Offline Offline
God Member
*****
Karma: 0
Posts: 507
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

The overhead will only be a few hundred nanoseconds per iteration.
Logged


0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 59
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ah, well never mind then! smiley
Logged

Las Vegas, NV
Offline Offline
God Member
*****
Karma: 0
Posts: 507
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

It's definitely good to consider things like that to make sure that your estimates are reliable.  If he was trying to time how long it takes to add and multiply integers, the overhead of the for loop would be significant.  In this case it seems the overhead is maybe about 5 - 10% of the total time, so it can be safely ignored if all we care about is an order of magnitude estimate.

- Ben
Logged


0
Offline Offline
Faraday Member
**
Karma: 8
Posts: 2526
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Basic for loops generally take two instructions (not sure about the ATmega, I could be off +/- one instruction).  This doesn't account for compiler optimization games like loop unrolling.

Speaking of unrolling, you can stuff more work into your loop to mitigate the loop overhead.  For example:
Code:
float f1=0.0, f2=0.0, f3=0.0, f4=0.0, f5=0.0;
int i;

long start, end;

start = millis();

for (i=0; i<10000; i++)
{
   f1 += 3.14159;
   f2 += 3.14159;
   f3 += 3.14159;
   f4 += 3.14159;
   f5 += 3.14159;
}

end = millis() - start;
...

-j

« Last Edit: August 06, 2008, 06:15:18 pm by kg4wsv » Logged

0
Offline Offline
Newbie
*
Karma: 1
Posts: 27
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
This may or may not be a valid thought, but doesn't using a for loop add overhead, so you're not getting an accurate result for how long it takes to do a multiple or add?

I get your point but in my program (the one described in the first post) all the operations happen inside for loops, so I guess that in this case it's important not to mitigate the loop overhead.

Thanks for all the replies  smiley
Logged

London
Offline Offline
Faraday Member
**
Karma: 10
Posts: 6248
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I doubt that worrying about the time spent in the for loop is the right place for your efforts to improve speed. I think you would get a far greater performance improvement if you can do the math using longs rather than floats. In many applications one can scale floats to longs with sufficient precision and if yours is one than you will considerably speed up your execution time. You can probably find a number of examples of how to do this on these and other AVR forums.
Logged

0
Offline Offline
Newbie
*
Karma: 1
Posts: 27
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I doubt that worrying about the time spent in the for loop is the right place for your efforts to improve speed.

Thanks for the hint; actually I don't want to improve (250 Hz should be enough) but I want to better understand how things are working.
Logged

Pages: [1]   Go Up
Jump to: