millis() is innacurate on my arduino.

I'm new to Arduino and am learning as I go. Today I got my 16x2 parallel LCD working and tried to run the following code:

#include <LiquidCrystal.h>

LiquidCrystal lcd(11, 13, 12, 7, 8, 9, 10);

int i;

void setup()
{
lcd.clear();
}

void loop()
{
lcd.home();
lcd.print(millis());
}

It displays just fine, and counts up. However, I've timed it and in 5 minutes, it's only counted up to ~200,000 (vice 300,000.) It's 2/3 slow every time I try to run it.

Why is my arduino timing things slow? Have I done anything wrong?

-Brady

From wiring.c :

/* Delay for the given number of microseconds. Assumes a 8 or 16 MHz clock.

  • Disables interrupts, which will disrupt the millis() function if used
  • too frequently. */
    void delayMicroseconds(unsigned int us)

And, looking inside the LiquidCrystal.cpp :
void LiquidCrystal::home()
{
command(0x02); // set cursor position to zero
delayMicroseconds(2000);
}

Your sketch is calling that home() function constantly so there's a good chance that the controller will be in the delayMicroseconds() routine with interrupts disabled when the counter overflows...

You might try replacing the home function with:
void LiquidCrystal::home()
{
command(0x02); // set cursor position to zero
unsigned long waitUntil = millis() + 2L;
while( millis() < waitUntil ) ; // Block until you've waited the minimum delay here.
}

I don't have an LCD to try this out with but the following sketch looks happy compared to my PCs clock

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

void loop()
{
waitASec(5000);
Serial.println(millis(), DEC);
}

void inline waitASec(int i)
{
unsigned long timeToWait = millis()+i;
while( millis() < timeToWait ) ;
}

That's pretty good debugging, Fjornir! :slight_smile:

I encountered a similar problem when monitoring serial GPS data. Whenever I used lcd.home() or lcd.clear(), I would start dropping characters from the software serial port. It turned out to be exactly the same problem.

Thanks,

Mikal

Okay, I tried running your sketch and checking millis() in serial. Works fine, 5 minutes had 300,000 milliseconds.

I added in the changes to LiquidCrystal.cpp, and it made no difference. (Is there another step I need beside just making the change and saving the file?)

But I did try:

#include <LiquidCrystal.h>
LiquidCrystal lcd(11, 13, 12, 7, 8, 9, 10);

void setup()
{
lcd.clear();
}

void loop()
{
waitASec(5000);
lcd.home();
lcd.print(millis());
}

void inline waitASec(int i)
{
unsigned long timeToWait = millis()+i;
while( millis() < timeToWait ) ;
}

And that seems to be working perfectly. I'm still not sure what the original problem was, but at least I know I don't have a "slow" arduino! Thanks Fjornir!

If you modified LiquidCrystal.cpp to not call into delayMicroseconds() when you're using the home() method then you might need to delete the LiquidCrystal.o file (I hear the arduino environment is a bit bad about detecting changes to library files) before asking it to rebuild your sketch.