Best timer library

Hi!
I'm looking for a timer library.
I am confused about how many related libraries are available.
I would like to have one with rollover protection, delay on, delay off, blink, and easy to use.
What do you suggest?

What kind of timer lib are you searching? To use the hardware timers? Or a software timer lib to create nonblocking delays in loop more easy?

What does Best mean ?

You don’t need a library, follow the BWD example in the IDE.

I'm looking for something non-blocking like delay(), and easier than millis()

So what you saying is no library is better than millis(). Right?

What you're describing is typically one of the responsibilities of an operating system. For smaller to medium sized projects you're better off learning how to do asynchronous programming using the millis function.

A delay library would do the same as using the millis() technique in non blocking delays.


A library does speed implementation.

If you need a library, this is one I use often.

Lots of other versions are easily found.


//                           M A C R O S
//**********************************************************************
//
//Define some MACROS:
//
//1. LED wiring where a HIGH on the pin turns the LED on
#define LEDon                    HIGH
#define LEDoff                   LOW

#define PUSHED                   LOW
#define notPUSHED                HIGH


//                   c l a s s     m a k e T i m e r
//======================================================================
//
class makeTimer
{
#define MILLIS true
#define MICROS false

    //Note: since code takes time to execute, precise micro second timing is difficult.

    //StartTime  = the time this "Timer" was (re)started
    //Interval   = Interval/delay time we are looking for
    //Restart    = do we start "this timer" again and again
    //EnableFlag = is "this timer" enabled/allowed to be accessed
    //TimerType  = true = millis(), false = micros()
    //**********************
    //For each timer object you need:
    //Example:
    //   makeTimer myTimer = //create a Timer named "myTimer"
    //   {
    //     0, 200UL, true, true, MILLIS  //StartTime, Interval, Restart, EnableFlag, TimerType (MILLIS/MICROS)
    //   };
    //
    //Each Timer object is made up of 5 variables:
    //myTimer.StartTime, myTimer.Interval, myTimer.Restart, myTimer.EnableFlag and myTimer.TimerType
    //
    //You have the following class functions:
    //myTimer.CheckTime() and  myTimer.EnableTimer()  and  myTimer.DisableTimer()
    //**********************

  public:
    unsigned long StartTime;
    unsigned long Interval;
    bool          Restart;
    bool          EnableFlag;
    bool          TimerType;

    unsigned long currentTime;

    //                        m a k e t i m e r ( )
    //**********************************************************************
    //Constructor
    //Note: If you do not have this constructor, the compiler will make this for you.
    //
    makeTimer(unsigned long ST, unsigned long INT, bool RES, bool ENA, bool TT)
    {
      StartTime   = ST;
      Interval    = INT;
      Restart     = RES;
      EnableFlag  = ENA;
      TimerType   = TT;

    } //END of                m a k e t i m e r ( )

    //                       C h e c k T i m e r ( )
    //**********************************************************************
    //Delay time expired function "CheckTime()"
    //
    bool CheckTime()
    {
      //StartTime  = the time TimerX was (re)started
      //Interval   = interval/delay we are looking for
      //Restart    = do we restart TimerX automatically
      //EnableFlag = is TimerX enabled/allowed to be accessed
      //TimerType  = use ms or us timing, MILLIS/true = millis(), MICROS/false = micros()

      if (TimerType == MILLIS)
      {
        //using millis() for this Timer
        currentTime = millis();
      }
      else
      {
        //using micros() for this Timer
        currentTime = micros();
      }

      //Is Timer enabled and has the Timer expired?
      if (EnableFlag == true && currentTime - StartTime >= Interval)
        //Note: if delays of < 2 millis are needed use micros() and adjust 'Interval' as needed
      {
        //Should we restart the Timer automatically?
        if (Restart)
        {
          //get ready for the next iteration
          StartTime = currentTime;
        }

        //This Timer did expired
        return true;
      } //END of   if(EnableFlag == true && currentTime - StartTime >= Interval)

      //This timer did not expire or it is disabled
      return false;

    } //END of               C h e c k T i m e r ( )

    //                      E n a b l e T i m e r ( )
    //**********************************************************************
    //Function to enable and initialize a timer, ex: myTimer.EnableTimer();
    //
    void EnableTimer()
    {
      EnableFlag = true;

      //initialize lastTime to current millis() or micros()
      if (TimerType == true)
      {
        StartTime = millis();
      }
      else
      {
        StartTime = micros();
      }

    } //END of              E n a b l e T i m e r ( )

    //                     D i s a b l e T i m e r ( )
    //**********************************************************************
    //Function to enable and initialize a timer, ex: myTimer.EnableTimer();
    //
    void DisableTimer()
    {
      EnableFlag = false;

    } //END of             D i s a b l e T i m e r ( )

}; //END of              c l a s s     m a k e T i m e r


//**********************************************************************
//     Create timer objects and initialize them in this sketch
//**********************************************************************
makeTimer heartbeatLED =            //create TIMER heartbeatLED
{
  0, 200UL, true, true, MILLIS      //StartTime, Interval, Restart, EnableFlag, TimerType (MILLIS/MICROS)
};

//***************************
makeTimer checkSwitches =           //create TIMER checkSwitches
{
  0, 50UL, true, true, MILLIS       //StartTime, Interval, Restart, EnableFlag, TimerType (MILLIS/MICROS)
};

//***************************
//makeTimer whatEver =              //create TIMER whatEver
//{
//  0, 0UL, false, false, MILLIS    //StartTime, Interval, Restart, EnableFlag, TimerType (MILLIS/MICROS)
//};
//***************************


//**********************************************************************
//                 G l o b a l   v a r i a b l e s
//**********************************************************************
//inputs
const byte mySwitch              = 2; //switch is on Arduino pin 2, pushed = LOW

//outputs
const byte heartbeatLEDpin       = 13;
const byte switchLEDpin          = 12;

//SRAM variables
const unsigned long myLongPress  = 2000UL;// 2 seconds
const unsigned long myShortPress = 500UL; // 1/2 second

byte lastSwitchState;


//                         s e t u p ( )
//**********************************************************************
//
void setup()
{
  pinMode(heartbeatLEDpin, OUTPUT);
  pinMode(switchLEDpin, OUTPUT);

  pinMode(mySwitch, INPUT_PULLUP);  
  
} //END of   setup()

//                           l o o p ( )
//**********************************************************************
//
void loop()
{
  //**********************************
  //Heartbeat LED
  //every 200ms or 500ms
  if (heartbeatLED.CheckTime())
  {
    //toggle heartbeatLED
    digitalWrite(heartbeatLEDpin, !digitalRead(heartbeatLEDpin));
  }

  //**********************************
  //is it time to check the switches ?
  //every 50ms
  if (checkSwitches.CheckTime())
  {
    serviceSwitches();
  }

  //**********************************
  //other none blocking code goes here
  //**********************************


} //END of   loop()


//                 s e r v i c e S w i t c h e s ( )
//**********************************************************************
//
void serviceSwitches()
{
  //**********************************
  byte switchState = digitalRead(mySwitch);

  //has there been a change in switch state ?                      m y S w i t c h
  if (lastSwitchState != switchState)
  {
    //updater to the new state
    lastSwitchState = switchState;

    //did the switch get pushed ?
    if (switchState == PUSHED)
    {
      //toggle the LED on pin 12
      digitalWrite(switchLEDpin, !digitalRead(switchLEDpin));

      //just for fun, change the rate the heartbeatLED flashes
      heartbeatLED.Interval = 500ul;

    }

    //the switch was released
    else
    {
      //the switch is released, do something 
      
      //just for fun, change the rate the heartbeatLED flashes
      heartbeatLED.Interval = 200ul;
      
    }

  } // END of   mySwitch code

  //**********************************
  //next switch code
  
} //END of       serviceSwitches()

I couldn't help but notice that there's a subtle bug in your timer implementation. When increasing the value that the timer was last triggered, the interval should be added instead of setting it to the current time. Otherwise the timer will slowly drift.

For accurate timing other methods would be recommended.

I like using this method as it avoids the problem discussed below:

As long as the user is aware of the options, they should choose what best suits their situation.

I would consider the code with the delay to be the problem though. But you're aware, so I'll just leave it there :slight_smile:

You could try the MoToTimer class of my MobaTools library. It wraps millis for easier use and for more clarity in the sketch.
If you don't want to install the whole library, you can simply copy MoToTimer.h into your scetch directory and include it with

#include "MoToTimer.h"

It contains everything you need. But even if you install the lib completely only the parts you use are compiled into your sketch.
There are also examples for the usage, but unfortunately most of them are commented in german so far.