How fast can arduino count?

Or, how many clock cycles to increment or decrement a variable by 1?
Or, how long would it take to count from 0 to 65,535, or from 65,535 to 0?
Assume whatever is the fastest counting method.

I want to find out which uC's secret number is closest to a test number.

  • There are two uC's.
  • They each have their own secret number. "Secret" in that each uC doesn't know the other uC's secret number. I don't know their secret numbers either.
  • Then there's a test number, for example 36,342. Everybody knows the test number.
  • I want to find out which uC's secret number is closest to the test number. Let's assume the test number is higher than both secret numbers.
  • My method is to have each uC count up from their own secret number until they reach the test number.
  • When either uC reaches the test number, they turn on their own LED.
  • Whichever uC turns on their LED first is the uC who's secret number is closest to the test number. (let's assume i can see which LED turns on first even if it's super fast.)

So i'd like a ballpark on how fast an Arduino can do this.

Let's assume the test number is lower than 65,535.

What are your requirements ?

Do you have access to an oscilloscope ?

For what practical reason do you want to determine this? What Arduino, what counting method, software or hardware etc. How are you generating the counts. Without details this question cannot be answered.

An AVR can increment a long in around 4 instructions and can compare it to 1E6 in another 4 or so. Maybe 4 more for loop control. Most instructions run in a single clock cycle. To a first approximation a 16MHz AVR, counting to 1E6 and stopping would take a bit under a second.

Can you say how this information would help you?

gardner:
An AVR can increment a long in around 4 instructions and can compare it to 1E6 in another 4 or so. Maybe 4 more for loop control. Most instructions run in a single clock cycle. To a first approximation a 16MHz AVR, counting to 1E6 and stopping would take a bit under a second.

Can you say how this information would help you?

Fantastic answer, @gardner!
Sorry i cannot share my use-case, but you have helped!

A dark secret it must be.

The hardware counters can count at 16 MHz on an UNO but they can only count to 65535. You have to add some code to count 15 overflows (983,040) and an additional 16,960 ticks. That would take 62.5 milliseconds plus a few cycles for interrupt overhead. If you can predict the interrupt overhead you can end the count early and come in at exactly 62.5 milliseconds.

johnwasser:
The hardware counters can count at 16 MHz on an UNO but they can only count to 65535. You have to add some code to count 15 overflows (983,040) and an additional 16,960 ticks. That would take 62.5 milliseconds plus a few cycles for interrupt overhead. If you can predict the interrupt overhead you can end the count early and come in at exactly 62.5 milliseconds.

Fantastic, John. Would it be correct to say your answer contradicts gardner's answer above? Or, does his answer assume a slower algorithm?

jremington:
A dark secret it must be.

Yes, @jremington. Btw, why do you tie up your camel? A dark secret it must be :smiley:

theboom:
Fantastic, John. Would it be correct to say your answer contradicts gardner's answer above? Or, does his answer assume a slower algorithm?

theboom:
Fantastic, John. Would it be correct to say your answer contradicts gardner's answer above? Or, does his answer assume a slower algorithm?

His answer is a guess that you want to do some kind of timing - the hardware timers offer a better way to do that.

theboom:
(in js, counting backwards is faster).

Is it really?
Or is it just simpler/ quicker to compare to zero than it is to compare to 106?

(I actually don't know the answer because I don't know JS that well but I used to work on an architecture where larger constants took longer to load, so it made sense to take that hit once at the top of the loop, rather than for each iteration)

Do you really need "counting" in your secret application or this is just to wait a known amount of time?

theboom:
Fantastic, John. Would it be correct to say your answer contradicts gardner's answer above? Or, does his answer assume a slower algorithm?

His answer is correct for counting in a C++ program loop. My answer was for counting in hardware. With a bunch of loop unrolling you could get an intermediate answer.
Since counting to a million does no useful work, the C++ compiler will optimize the loop away and give you the result VERY quickly. In fact, it seems to take -2 instruction cycles to do the loop! So one answer to "how long would it take to count from 0 to 1 million" is -125 nanoseconds.

// Fast Timer
// Returns the current time in 16ths of a microsecond.
// Overflows every 268.435456 seconds.


// Note: Since this uses Timer1, Pin 9 and Pin 10 can't be used for
// analogWrite().


void setup()
{
  Serial.begin(115200);
  while (!Serial);
  StartFastTimer();
}


void StartFastTimer()
{
  noInterrupts ();  // protected code
  // Reset Timer 1 to WGM 0, no PWM, and no clock
  TCCR1A = 0;
  TCCR1B = 0;


  TCNT1 = 0;  // Reset the counter
  TIMSK1 = 0; // Turn off all Timer1 interrupts


  // Clear the Timer1 Overflow Flag (yes, by writing 1 to it)
  // so we don't get an immediate interrupt when we enable it.
  TIFR1 = _BV(TOV1);


  TCCR1B = _BV(CS10); // start Timer 1, no prescale
  // Note: For longer intervals you could use a prescale of 8
  // to get 8 times the duration at 1/8th the resolution (1/2
  // microsecond intervals).  Set '_BV(CS11)' instead.


  TIMSK1 = _BV(TOIE1); // Timer 1 Overflow Interrupt Enable
  interrupts ();
}


volatile uint16_t Overflows = 0;


ISR(TIMER1_OVF_vect)
{
  Overflows++;
}


unsigned long FastTimer()
{
  unsigned long currentTime;
  uint16_t overflows;


  noInterrupts();
  overflows = Overflows;  // Make a local copy


  // If an overflow happened but has not been handled yet
  // and the timer count was close to zero, count the
  // overflow as part of this time.
  if ((TIFR1 & _BV(TOV1)) && (TCNT1 < 1024))
    overflows++;


  currentTime = overflows; // Upper 16 bits
  currentTime = (currentTime << 16) | TCNT1;
  interrupts();


  return currentTime;
}


void loop()
{
  static unsigned long previousTime, currentTime;
  unsigned long l;


  previousTime = FastTimer();
  currentTime = FastTimer();
  unsigned long overhead = currentTime - previousTime;
  Serial.print("Overhead=");
  Serial.println(overhead);


  previousTime = FastTimer();
  for (l = 0; l < 1000000ul; l++) ;  // Count from 0 to a million
  currentTime = FastTimer();


  Serial.println(l);


  Serial.println(currentTime - previousTime);
  
  delay(3000);
}

J-M-L:
Do you really need "counting" in your secret application or this is just to wait a known amount of time?

Good question, J-M-L. I'm actually comparing to a variable, to see how long it takes to reach that variable. Here's a bit more about my application (i'll add this to my top post):

I want to find out which uC's secret number is closest to a test number.

  • There are two uC's.
  • They each have their own secret number. "Secret" in that each uC doesn't know the other uC's secret number. I don't know their secret numbers either.
  • Then there's a test number, for example 36,342. Everybody knows the test number.
  • I want to find out which uC's secret number is closest to the test number. Let's assume the test number is higher than both secret numbers.
  • My method is to have each uC count up from their own secret number until they reach the test number.
  • When either uC reaches the test number, they turn on their own LED.
  • Whichever uC turns on their LED first is the uC who's secret number is closest to the test number. (let's assume i can see which LED turns on first even if it's super fast.)

So i'd like a ballpark on how fast an Arduino can do this.

@JohnWasser, for the sake of simplicity, let's assume the test number is lower than 65,535 (so no overflow complexities to worry about).

TheMemberFormerlyKnownAsAWOL:
is it just simpler/ quicker to compare to zero?

Interesting question! You might be right. If so, i guess backwards counting wouldn't help in this scenario.

OK - yes that makes sense if both µC are the same and use the same algorithm to count (may be one will count up and the other down though)

how many bytes are really required to code the secret number and the known number?

if it's lower than 65,535 then indeed it fits on 2 bytes (Timer1 would do on a UNO or MEGA)

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.