Optimizing an Arduino code I am working on project and using Arduino Pro Mini (Atmega328p running on 2xAA) to measure the time to charge a capacitor (when the volt level is high). This is the code I used while testing:

int counter = 0;

// Charge the capacitor
digitalWrite(8,HIGH);

while (digitalRead(7) == LOW) {
    counter = counter +1;
    if (counter &gt; 250) {
        break; // CHARGING FAILED!
    }
}


The code was working fine when the board was running at 16MHz since the loop was fast enough to give good result. ( counter =~ 28 when the test cap is charged). 

However, the intention is to run the system on a battery with clock of 1MHz (to reduce power consumption) and when tested at that speed the counter only reaches 2~3 because the loop it too slow now that the cap will charge in about two to three cycles.

So I did two changes which are using byte instead of int for the counter, and reading the value of the pin directly from the PIND register:

byte counter = 0;

// Charge the capacitor
digitalWrite(8,HIGH);

while ((PIND &amp; (1&lt;&lt;PD7)) == 0) {
    counter = counter +1;
    if (counter &gt; 250) {
        break; // CHARGING FAILED!
    }
}


Both of these changes increased the speed and now counter reads ~20 which is much better and almost close to the 16MHz.

Is there any further optimizations?

Can I use one of the general registers instead of the counter, if yes then how? and will that improve the speed?

Is there a more clever and faster way to do this loop?




Update:


I am going to follow the suggested answer and use the analog comparator, but I also wanted to add to my finding which might help others with general optimization.

Instead of incrementing the counter and comparing if it is larger than some value, it is faster to decrements and compare if it is equal to zero. The counter improved to ~23.
Get rid of the loop altogether. Instead of twiddling and checking bits manually, use timer 1 to trigger the output and capture the input.

If you perform the output on pin 10 and the input on pin 8 then you can use timer 1's output compare to send the pulse out and its input capture to detect when the capacitor has charged.

Untested:

#include &lt;avr/interrupt.h&gt;

void setup(void)
{
  cli();
  DDRB |= _BV(PB2); // Configure OC1B as output
  TCCR1B &amp;= ~(_BV(CS12) | _BV(CS11) | _BV(CS10)); // Stop timer 1
  TCNT1 = 0; // Initialize timer count
  OCR1A = 0xffff; // Reset the timer at this count
  OCR1B = 0xf000; // Upper limit of the timed value, plenty of time before timer reset
  ICR1 = 0xff00; // Set to an invalid initial value
  TCCR1A = _BV(COM1B1); // Trigger output at 0, clear at upper limit
  TCCR1B = _BV(ICES1); // Capture on leading edge
  TCCR1B |= _BV(WGM13) | _BV(WGM12); // High bits for 16-bit fast PWM
  TCCR1A |= _BV(WGM11) | _BV(WGM10); // Low bits for 16-bit fast PWM
  TIMSK = _BV(ICIE1) | _BV(OCIE1B); // Enable input capture and limit interrupts
  sei();
  TCCR1B |= _BV(CS10); // Start the timer at its highest clock speed
}

ISR(TIMER1_CAPT_vect)
{
  TIMSK &amp;= ~(_BV(ICIE1) | _BV(OCIE1B)); // Disable input and limit interrupts
  TCCR1B &amp;= ~(_BV(CS12) | _BV(CS11) | _BV(CS10)); // Stop the timer
  PORTB &amp;= ~_BV(PB2); // Kill the charging output
  // Check ICR1 for the captured value
}

ISR(TIMER1_COMPB_vect)
{
  if (ICR1 == 0xff00)
  {
    // WELL CRAP, charging is taking too long
    // Maybe try with a slower clock?
  }
}

void loop()
{
  // Do other stuff
}