Very irregular loop times

I notice that when I run a simple loop, the time it takes reported by millis() is all over the map. See the code below. Is my loop really taking anywhere from 0.25ms to 3 ms, or is the resolution of millis() only +/- 3 ms? What you see below was run on a 3.3V, 8MHz Arduino Pro Mini.

unsigned long msecs; // Storage for result of millis()
unsigned long variable; // Just for time killing
unsigned int k[20]; // Storage for split times

void setup()
{
Serial.begin(9600); // Set up serial monitor
delay(2000); // Wait for me to open monitor window
variable=500;
for(unsigned int i=0; i<20; i++){ // For 20 split times
for(unsigned int j=0; j<500; j++){ // Kill some time between splits
variable=variable^msecs;
}
msecs=millis();
k*=(unsigned int)msecs; // Record the split time*

  • }*
  • for(unsigned int i=0; i<20; i++){ // End of measurement,*
    _ Serial.println(k*); // Display result*_
    * }*
    }
    void loop()
    {
    }
    /* Results are:
    1998
    2000
    2000
    2000
    2000
    2002
    2002
    2002
    2002
    2004
    2004
    2004
    2004
    2007
    2007
    2007
    2007
    2009
    2009
    2009
    */

First, read How to post code properly and fix up your post with code tags.
Second, how did you get that to compile?

sketch_jun29a.ino:15:6: error: incompatible types in assignment of 'unsigned int' to 'unsigned int [20]'

Pete

Try measuring using micros() instead.
Make sure all time variables are unsigned long.

Thank you, CrossRoads. The suggestion of using micros() instead of millis() and trying the same code on a Diecimila demonstrates clearly that mills() has a resolution of only 2 milliseconds on a processor running at 8MHz. I guess this is because it uses timer0 which has been set up for other purposes. If I want to do better, I guess I must either use micros() or dedicate another timer to the task.

Per the advice of el_supremo, I'm posting the modified code below. I see that "

" gets inserted, but otherwise the preview looks the same.

[code]unsigned long msecs1;                  // Storage for result of millis()
unsigned long msecs2;                  // Storage for result of micros()
unsigned long variable;                // Just for time killing
unsigned int k[20];                    // Storage for split times
unsigned int m[30];

void setup() 
{
  Serial.begin(9600);                  // Set up serial monitor
  delay(2000);                         // Wait for me to open monitor window
  variable=500;
  for(unsigned int i=0; i<20; i++){    // For 20 split times
    for(unsigned int j=0; j<500; j++){ // Kill some time between splits
      variable=variable^msecs1;
    }
    msecs1=millis();
    msecs2=0.001*micros();
    k[i]=(unsigned int)msecs1;         // Record the split time
    m[i]=(unsigned int)msecs2;
  }
  for(unsigned int i=0; i<20; i++){    // End of measurement,
    Serial.print(k[i]);                // Display result
    Serial.write("   ");
    Serial.println(m[i]);
  }
}

void loop()
{
}

Results are:
1998 2000
2000 2001
2000 2001
2000 2002
2000 2002
2002 2003
2002 2003
2002 2004
2004 2005
2004 2005
2004 2006
2004 2006
2007 2007
2007 2007
2007 2008
2007 2008
2009 2009
2009 2010
2009 2010
2009 2011

Your time killing loop is probably being optimized into oblivion by the compiler.
Try it with this:

volatile unsigned long variable;

Pete

If you want close control of timing make sure that loop() can repeat absolutely as fast as possible (no delay() or anything like that) and use millis() or micros() to manage the timing as shown in Several Things at a Time

...R

It matters not whether my time killer is being optimized away by the compiler, or how fast I can make the loop go. Since the loop is clearly being executed multiple times per millisecond, as reported by micros(), the fact that millis() running in the same loop always reports an increase of zero or two milliseconds, but never an increase of one millisecond is pretty conclusive proof that the resolution of mills() is only two milliseconds (with the 8 MHz clock rate).

The bottom line is that I now know what to do, and it does not include using millis(). Thanks for your help.