My Millis is not equal to 1 second (UNO)

HI,

While making test with my Arduino project, I found that my “millis” is not equal to 1 second.

My counter using millis is counting to 10 but if I compare, I get 9.25 seconds to my stopwatch.

To debug that, I add 2 lines to my code with “serial.print” so I can see my variable “Countermillis and CounterMillis1”

I start the counter and found that the difference between both was not 1000.

I tried to change the value of my interval but it’s not working.

It look like my full code takes more that a second to fully run on my UNO (I think)

I set my variable at the beginning of my code

  unsigned long CounterMillis = 0;
  unsigned long CounterMillis1 = 0;
  const long interval2 = 900;

And this is the part of my code for the counter

void LcdCounter(){


    CounterMillis = millis();
    if (CounterMillis - CounterMillis1 >= interval2) {

    if (a < 40 && purge == 0 && stateRELAY1 == HIGH) // value of 40 for testing purpose.              
    {                                                 // The final goal will be 360 seconds
    a ++;
    lcd_2.setCursor(11, 1);
    lcd_2.print(a);
    Serial.println(CounterMillis); // for debug millis
    Serial.println(CounterMillis1); // for debug millis
    }
    
    else
    {
    if (purge == 1){
    a = 0;
    purge = 0;
    lcd_2.setCursor(11, 1);
    lcd_2.print(F("     "));
    }

    if (a >= 40) // value of 40 for testing purpose. 
                 // The final goal will be 360 seconds
    {
    stateRELAY1 = LOW;
    stateRELAY2 = LOW;
    stateRELAY3 = LOW;
    lcd_2.setCursor(11, 1);
    lcd_2.print(F("Purge"));
    }
    }
    CounterMillis1 = CounterMillis;
    }
}

When I check on serial print the value of CounterMillis and CounterMIllis1 I get this

2059008
2058103

Off course the values changed at each print but every time I check, the difference between them is around the same value and it’s not 1000.

Question

How can I get 1 second for my counter?

You have interval2 set to 900. So it shouldn't take a whole second. It should take 0.9 seconds.

From the code you posted the output looks about right. It took just a shade longer than 900ms between the two and you have to account for the other things that might have slowed you down and kept you from getting back to that comparison at exactly 900ms.

Additionally, you're not going to get the Arduino to time things exactly compared to your stopwatch. It's running on a crystal resonator with a pretty wide tolerance on speed. You're trying to compare with a stopwatch that likely has a quartz crystal running at an exact speed. If you need exactly one second you need to start looking at RTC chips.

Hi Delta_

If I put the interval to 1000, the counter become slower and when it reach 10, my stopwatch show me 14 seconds. I tried a few value and 900 was the closest to 1 second.

OK, well you've given us part of the code to work with and you've got part of an answer. When you're ready to give us a look at the whole project then we can move forward.

Hi Delta_G

I didn’t think the full code could be useful for that question but since
I’m looking for help, I’m certainly not going to argue with you so see
my code attached.

Thanks,

Control_Compressor_VR_Oct_1_FlowsensorV7.ino (12.5 KB)

Write a bare minimum sketch to check out millis().
What are the results?

.

Nick’s reply on “Re: How accurate is millis()?” #8,

fyi, there is a lot of blocking code in your project... for example...

void DallasTemperature::requestTemperatures()
{
  _wire->reset();
  _wire->skip();
  _wire->write(STARTCONVO, parasite);

  // ASYNC mode?
  if (!waitForConversion) return; 
  blockTillConversionComplete(&bitResolution, 0);

  return;
}

(it even admits to it)

all kidding aside, if you look at the Dallas spec sheets, you will see just how long it takes to get a temperature, depending on the resolution you asked for. I cannot tell if any of that is affecting your millis() timer but you have to know all of the potential parts of the sketch that can potentially block.

because of your structure, you can easily just omit functions in loop() to see what may be the culprit.

Two possible issues.

1 - the resonator is inaccurate. This can't be fixed - you need to purchase a proper Real Time Clock module. They are ten bucks.

2 - the sketch marks a period by setting the new start of the timed interval to millis() after something that takes time has occured.

dont do this:

if(millis() - startMs >= 1000) {
  do_something_that_takes_200ms();
  startMs = millis();
}

do this

if(millis() - startMs >= 1000) {
  startMs = millis();
  do_something_that_takes_200ms();
}

or better still, do this

if(millis() - startMs >= 1000) {
  startMs += 1000;
  do_something_that_takes_200ms();
}

Just be sure, if you use that third one, to initialise startMs in your setup().

Hi BulldogLoell,

I deactivated all sections in my loops except the counter and then millis = 1000
the temperature section only add .005. The pressure and the O2 analysing
section are the ones who takes more but anyway I won’t change that.
Correcting millis or using a RTC may do it but I don’t know yet.
still reading and asking questions.

Hi PaulMurrayCbr,

I would like to try your example but i’m not sure where to put in in my code
and do I replace lines with yours or add them ? Do I initialize (int statMs;) or need to be set to 0 ?

My code again.

void LcdCounter(){


    CounterMillis = millis();
    if (CounterMillis - CounterMillis1 >= interval2) {

    if (a < 40 && purge == 0 && stateRELAY1 == HIGH) // value of 40 for testing purpose.              
    {                                                 // The final goal will be 400 counts
    a ++;
    lcd_2.setCursor(11, 1);
    lcd_2.print(a);
    Serial.println(CounterMillis); // for debug millis
    Serial.println(CounterMillis1); // for debug millis
    }
    
    else
    {
    if (purge == 1){
    a = 0;
    purge = 0;
    lcd_2.setCursor(11, 1);
    lcd_2.print(F("     "));
    }

    if (a >= 40) // value of 40 for testing purpose. 
                 // The final goal will be 400 counts
    {
    stateRELAY1 = LOW;
    stateRELAY2 = LOW;
    stateRELAY3 = LOW;
    lcd_2.setCursor(11, 1);
    lcd_2.print(F("Purge"));
    }
    }
    CounterMillis1 = CounterMillis;
    }
}

you see I’m just a beginner and still need to be taken by the hand for now.

many thanks