Arduino Timer– To Overflow or not to Overflow

Part of the learning curve in mastering the use of the Arduino – is how to use delays. The simplest sketches (programs to most people) show turning a light on, waiting a second, turning it off, waiting a second… in a permanent loop.

Still don’t know what an Arduino is? Well, perhaps you should because Google want to put these things in our schools – it’s like a PIC chip but different – a cheap and cheerful way for kids to learn about computers… or put another way, a damned powerful and CHEAP microprocessor to let you do control experiments – timers, lighting systems, heating control, robots….. you name it.

That’s easy – but almost NO programs are so simple that all they do is flash lights (though the chip does a cracking job of emulating a police car set of lights given red and blue LEDS)! The problem with delays is that you can’t DO anything while waiting for the delay to finish.

Perhaps you might want to get clever and make use of interrupts to ensure that certain things happen at the right time – the problem with that is one of volatility – i.e. using variables in the interrupt routine (which can happen at any time) which may be affected by stuff going on in the main program – and vice-versa. Yes interrupts are do-able but anyone who tells beginners that interrupts are easy is delusional. If there’s another way, simple avoid the subject.

I figured instead I’d make use of a standard Arduino routine called millis() – quite safe, it tells you how many milliseconds have elapsed since the chip was last reset. Well, that’s easy – except that it isn’t. There is a whole lot of mumbo-jumbo about how long it takes before millis() overflows… and what does that mean?

It is quite simple really, the millis() routine stores it’s value in an "unsigned long" which you can’t easily access – no black magic, this is a 32-bit number which can count from 0 to just over 4 billion – and that doesn’t take too long really at a count of 1000 a second. Depending what you are building that might not be a problem but any program with any kind of long term timer might end up in trouble.

So as an alternative to sitting in a loop you can look to see how long it was since the last time you read millis() and run code accordingly. The problems with that are two-fold… eventually millis() will reset and you could end up with a duff comparison – OR you could be busy doing something else, call millis() a little late… and now the WHOLE thing is put back a little. Accumulatively you end up building up inaccuracies over time that could be significant.

I decided I needed a delay that was accurate and if I was a little late calling it – well, it would time a little earlier next time to make up for lost time – then I realised people might not want this – even if they were way too late they might not want another call before the minimum specified… so I looked around for routines to do the timing and offer the option of catching up or not. Look for METRO library – sounds great but in order to retain accuracy you have to call that at least every millisecond – WHAT? The simplest DALLAS temperature chip calls sometimes go away for a SECOND… I’ve fixed that incidentally – but you know what I mean.

So, I needed a routine that would handle overflow, that would not mind my calling it a bit late and would give me options to compensate next time for the delay – or NOT.

I’ve wrapped this in a class just really to make sure I understood classes.. and put it on GITHUB again just as a training exercise.

Enjoy.. but TEST – don’t take my word that this works…. if you want to test the overflow- remember the limit for a 32 bit number in HEX is FFFFFFFF (ie 6 Fs). Consider a last timing just under that- add the interval – you get a lower value as it overflows – but actually do the math and you’ll find the difference is still a positive number because both millis() and the comparison are 32 bits and so it still works.

So now you can write a program with routines that might take some time – and you can then check for intervals… an example might be to update the screen every 1 second – if you’re not fussed about accuracy use TRUE for the last parameter – on the other hand you might want a rock-steady beep every second – use FALSE or 0 as the last parameter.

As always a thanks to my pal Aidan – in this case the answer was mine but simply the ability to have someone to bounce the questions off and get intelligent answers makes all the difference.

Incidentally this is NOT super-accurate – you may check the routine at any time – not just dead on the millisecond so WORSE CASE you might find a stagger of somewhat less than a millisecond – ok 1 in a 1000 isn’t that bad – but it’s not perfect. It might mean in a real time clock the difference between catching a show and missing the first second or so Smile

So simple – but it does work. Proof…. call every 1000ms and print out the value of millis() on an LCD and it will display having added 1000 every time i.e. it remains accurate.

class Timing
{
private:
 unsigned long counter;
 boolean catchup;
 
public:
    void begin(boolean cat)
    {
        counter=millis();
        catchup=cat;
    }
        
    boolean isOver(unsigned long interval)
    {
        unsigned long newmillis=millis();  // temp vars so easier comparison
        if ((newmillis-counter)>=interval)
            {
            if (catchup) counter=newmillis; else counter+=interval;
            return true;
            }
        return false;
    }
};

// you can hide that class in an include file... so here's how to use it.
Timing myTimer;

void setup()
{
 myTimer.begin(0); 
 // 0 means catch up, 1 means delay will always 
 // be at least the value stated
}

void loop()
{
   if (myTimer.isOver(1000))
     {
        // do something here
     }
}

This code may be improved on – and I’m most likely to store improvements over at GITHUB. Here’s the link for the latest version. Enjoy.

Peter Scargill

Advertisements

2 thoughts on “Arduino Timer– To Overflow or not to Overflow

  1. “…that doesn’t take too long really at a count of 1000 a second.”
    It takes seven weeks. That’s enough for most applications!

  2. Seven weeks might be enough for things you turn on and off… but timers, clocks etc might stay on for a long time… anyway if you take a look at the page (perhaps hit refresh) – I’ve redone it – put it in a class – and so now it is SUPER easy to use – so easy that for anyone reading this – the problem is now solved…. time to get on with more exciting stuff…

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s