Millis() not accurate

Hi everybody,
I wrote the attached simple sketch to understand millis function, but opening the serial monitor I noticed the the time values are not accurate; it indicate 1 millisec more every 250 delay loop. Someone could explain me why and how to solve this inaccuracy?

Thanks.

unsigned long time=0;

void setup()
{
Serial.begin (9600);
}

void loop()
{
time=millis();
Serial.print("The time is: ");
Serial.println (time);
delay (250);
}

Monitor output extract:
The time is: 0
The time is: 249
The time is: 499
The time is: 750
The time is: 1000
The time is: 1251
The time is: 1501
The time is: 1752
The time is: 2001
The time is: 2252
The time is: 2502
The time is: 2753
The time is: 3004
The time is: 3254
The time is: 3505
The time is: 3755
The time is: 4005
The time is: 4255
The time is: 4506

How do you know that delay() is accurate ? millis() will sometimes skip a value if other code takes time to execute.
Try this

unsigned long startTime;
unsigned long interval = 250;

void setup()
{
  Serial.begin (115200);
}

void loop()
{
  static unsigned long startTime=millis();
  if (millis() - startTime >= interval)
  {
    Serial.print("The time is: ");
    Serial.println (startTime);
    startTime = startTime + interval;
  }
}

millis is indeed not exact, and notice that printing takes also time.

so don't use delay, try this

unsigned long lastTimePrint = 0;
unsigned long lastMinute = 0;
unsigned long lastTimeBlink = 0;

void setup()
{
  pinMode(13, OUTPUT);
  Serial.begin (115200);  // note the higher baud rate!
}

void loop()
{
  if (millis() - lastTimePrint >= 250)  // 4x per second
  {
     Serial.print("The time is: ");
     Serial.println (lastTimePrint );
    lastTimePrint += 250;
  } 

  if (millis() - lastMinute >= 60000UL)  // 1x per minute
  {
    Serial.print(lastMinute);
    Serial.println("\tTICK");
    lastMinute += 60000UL;
  } 

  if (millis() - lastTimeBlink >= 100)  // 10 x per second
  {
    digitalWrite(13, !digitalRead(13)); // invert on board led;
    lastTimeBlink += 100;
  } 
}

@UKHeliBob - you just beat me by two minutes :wink:

120,000 milliseconds :slight_smile:

You are great! Thanks, but...some other questions... the UKHeliBob's sketch is simpler than robtillaart's one and, for a rookie like me, more understandable.
Both used "Serial.begin (115200)": is there some specific reason to use a higher baud rate?
The robtillaart's example is pretty complicated for me but interesting.
First question:

  if (millis() - lastTimePrint >= 250)  // 4x per second
  {
     Serial.print("The time is: ");
     Serial.println (lastTimePrint );
    lastTimePrint += 250;

What is the meaning of: lastTimePrint += 250? that every loop lastTimePrint increases of 250 msec?

Second question:

if (millis() - lastMinute >= 60000UL)  // 1x per minute
  {
    Serial.print(lastMinute);
    Serial.println("\tTICK");
    lastMinute += 60000UL;

The scheme is like before, but why you use UL? What is?
TICK is the sound of the clock?

Thank you again and... ]:smiley: ]:smiley: bloody delay!!! :wink:

"Serial.begin (115200)": is there some specific reason to use a higher baud rate?

Yes, it reduces the time to get the data out, potentially reducing the time the processor will spend blocked with a full transmit buffer.

The robtillaart's example is pretty complicated for me but interesting.

It is not really more complicated if you look at it. It is really just 3 examples of my code one after the other. What it is doing is to show how 3 different events can be timed apparently at the same time. In practice the checks for the time periods being up are made in series rather than in parallel but the checks happen so frequently that they appear to happen at the same time.

60000UL is used to force the compiler to regard 60000 as an unsigned long in the comparison. It is important to use unsigned long for the timing variables and constants to avoid problems when the millis() value rolls over to zero after 49 and a bit days. Using millis() minus the period start time in the comparison also prevents the comparison returning the wrong value when the rollover occurs.

thanx!!!

What is the meaning of: lastTimePrint += 250? that every loop lastTimePrint increases of 250 msec?

it is equal to lastTimePrint = lastTimePrint + 250;

to make it a bit more complicated:
sometimes you want to do [1] lastTimePrint = lastTimePrint + 250;
and sometimes you want [2] lastTimePrint = millis();

The difference is that the first one will try to catch up respecting (more or less) the interval steps (250). It will keep lastTimePrint in multiples of 250.
The second one "ignores" all missed "events" and can make a jump in time. It will loose the multiple of 250 quite fast in fact.

The first one forces that over a longer period of time there are 4 actions per second on average. The second code can't guarantee that.

(this all under the assumption that the actions are on average shorter in time than the average intervals.)

TICK is the sound of the clock?

Some clocks do, I just wanted to show three different actions with different intervals.