Accuracy of Time Measurement: What's normal?

Hello everyone. I today got my hands on my first Arduino, an Illuminato. I have been fiddling with the basics, and have noticed that the time related functions seem to be a little screwy. Using both delay() and millis() to blink the pin 13 LED every half second, the results are... imperfect. I'm not in a position to post video, but I will explain as best I can.

The millis() sketch is this one;

int ledPin = 13;                // LED connected to digital pin 13
int value = LOW;                // previous value of the LED
long previousMillis = 0;        // will store last time LED was updated
long interval = 500;           // interval at which to blink (milliseconds)

void setup()
{
  pinMode(ledPin, OUTPUT);      // sets the digital pin as output
}

void loop()
{
  // here is where you'd put code that needs to be running all the time.

  // check to see if it's time to blink the LED; that is, is the difference
  // between the current time and last time we blinked the LED bigger than
  // the interval at which we want to blink the LED.
  if (millis() - previousMillis > interval) {
    previousMillis = millis();   // remember the last time we blinked the LED

    // if the LED is off turn it on and vice-versa.
    if (value == LOW)
      value = HIGH;
    else
      value = LOW;

    digitalWrite(ledPin, value);
  }
}

This sketch blinks the LED in a fashion that is very close to perfect. The on/off intervals are very regular for the first 14 or so blinks, and then the off period is noticeably short, although not severe. Repeat.

The delay() sketch is this one;

int LEDPin = 13;

void setup() {
  pinMode(LEDPin, OUTPUT);
}

void loop() {
  digitalWrite(LEDPin, HIGH);
  delay(500);
  digitalWrite(LEDPin, LOW);
  delay(500);
}

This sketch is much more noticeably wrong. The on/off periods are regular until the 5th HIGH state, which is then significantly shorter than 500ms. Repeat. So to rephrase, every 5th visibly on state of the LED is obviously short. Goes on like that forever.

So my question is, is this to be expected? I don't know what the accuracy of the hardware is, or what is considered normal. Just curious, thanks! :slight_smile:

I was using my Arduino to do direct digital synthesis and noticed that when I had delay() statements in my loop() it was preventing my timer interrupts from firing at the appropriate rate. I don't know what's -wrong- with the delay() function but I did notice that when I remove the delay()s from my loop() my application's timer interrupt was firing at the correct rate and I was able synthesize the wave correctly.

I don't know what's actually -wrong- with the delay() routine but I do know that for the stuff that was happening in my loop() counting millis was plenty good enough for me.

Wiring.c

void delay(unsigned long ms)
{
unsigned long start = millis();

while (millis() - start < ms)
;
}

unsigned long millis()
{
unsigned long m;
uint8_t oldSREG = SREG;

// disable interrupts while we read timer0_millis or we might get an
// inconsistent value (e.g. in the middle of the timer0_millis++)
cli();
m = timer0_millis;
SREG = oldSREG;

return m;
}

This is the reason for delay() messing up interrupt driven code, it uses the millis() which disables interrupts with cli().

At least, I think that is why.

Oh, excellent, thank you. That explains rather a lot I think. I checked the delay*.h files for anything that would mess with interrupts but didn't realize my delay() was coming from wiring.c instead. Egg on my face for not looking closer.

I'm curious why my own implementation of delay (which looks almost exactly the same as the one in the wiring.c ) didn't exhibit the same behavior. Perhaps because I didn't inline it and there was that much more overhead of the function call to deal with to let my interrupt timer fire without being in the cli()'d portion of millis()?

I'm curious why my own implementation of delay (which looks almost exactly the same as the one in the wiring.c ) didn't exhibit the same behavior.

Can you post you version? :slight_smile: