Ultimate Blink Without Delay Timer Class Library With Lambda & Callback- for UNO

My Blink Without Delay Timer using Lambda and Callbacks:
ZTimer has come about with help from many people on this forum and I must thank them for the ideas and concepts they provided that helped me out.
Nick Gammon for your time helping with Lambda I couldn't have made this without your help :
LarryD From your structure timer I created the powerful class library Post #6 You Shared
Coding Badly For helping me understand timer rollover along time ago
and many others who gave suggestions and support

Thank You!

Please try and share you ideas and improvements.
I have included a section that triggers every function included in the class with detailed descriptions on how they work. After watching this discussion I will add Documentation to the class and post any changes you may suggest to improve the code.

#include "ZTimer.h"
ZTimer TimerZ;

void setup() {
  pinMode(13, OUTPUT);
  Serial.begin(115200);
  Serial.println("Testing ZHomeslices ZTimer Library");
  
  // Lets set the Callback functions to trigger code each time CheckTime() triggers true
  TimerZ.SetCallBack([&]() {                          // Call back and Lamba to allow for many functions to be called when CheckTime() returns true.
    digitalWrite(13, !digitalRead(13));               // Blink onboard LED
    Serial.println (TimerZ.GetNow());                 // send the time now
    if( TimerZ.GetNow() == 50000) TimerZ.StopTimer(); // Stop the timer after 50 seconds
  });
  
  /*************************************************************************************************/
  // Testing all functions:
  // The below functions return a pointer to itself so that you can simply put a .function to trigger additional functions
  
  TimerZ.StopTimer()                   // Stopps the timer but and freezes the time delay to be continued upon StartTimer() call.
        .StartTimer()                  // Resumes the timer with exactly the time that is left from when the StopTimer() was called.
        .ResetTimer(true)              // Resets the timer to continue with full delay from this point. (true timer will not pause at end of run, false Timer will pause see .Pause() for warnings) 
        .SetWaitTime(1000)             // Sets the wait time.
        .SetLastTime(TimerZ.GetNow())  // Sets the time when the last trigger would have occured. (We will set it to right now for this example)
        .Pause()                       // At end of timer the timer will stop resetting (*** Waning *** the CheckTime() function will continuously return true after timer completes).
        .Every()                       // Wait Time is added to Last time to get the next time If a long pause occures this will wind up and cause multiple triggers catching up to present time.
        .After()                       // After Wait time the Last time is given the current time to use which could cause loss in time depending on code.
        .Micros()                      // Uses micros() to calculate durations.
        .Millis();                     // Uses millis() to calculate durations.
        
  ZTimer * ZPoiner = &TimerZ.This();   // Returns the pointer to the ZTimer
  
  unsigned long x = TimerZ.GetNow();   // Returns the time now based on which clock was chosen micros() or millis()
  unsigned long y = TimerZ.WaitTime(); // Gets the delay time set with SetWaitTime().
  unsigned long z = TimerZ.LastTime(); // Gets the last time that was set when last triggered.

  TimerZ.CheckTime();                  // returns true upon timer completion . This also triggers the callback function we set with SetCallBack()

  /*************************************************************************************************/
  
  // now that we messed arround above lets set up the timer for real
  TimerZ.Millis().After().SetWaitTime(1000).ResetTimer(true); // We are using millis() waiting at least 1000 milliseconds and starting the timer now with auto restart on
}

void loop() {
  if(TimerZ.CheckTime() == true){ // Check to see if time has expired and if it has run the callback set in the setup then return true for the optional if statement
    Serial.println(" The Other way");
  }
}

ZTimer.cpp (2.97 KB)

ZTimer.h (913 Bytes)

Using delay() was dirt simple.

Using BwoD (or Robin2's classic Several Things demo methind - same thing) was more complex, but most Arduino programmers can wrap their head around it.

Then your one-line, loop based timer that seemed to turn loop inside out. It was a good exercise for learning, and I jumped into it, trying out the code in some examples I used. But it was the opposite of self documenting code.

Now this, which seems to have taken complexity to the limit. It makes my head explode.

Please post some clearer examples using your library.

Thanks for your continued work on this topic!

It sounds interesting. Incidentally, the core Arduino library for the ESP8266 includes the class Ticker which is similar, although does not have all the functionality of ZTimer.

6v6gt:
It sounds interesting. Incidentally, the core Arduino library for the ESP8266 includes the class Ticker which is similar, although does not have all the functionality of ZTimer.

Thank you 6v6gt The ESP8266 is incredible and was the initial inspiration that arduino's could use lambda and callbacks although I have been using callbacks for quite a while with the attachInterrupt() function provided with the UNO's core
The Tinker Library is a great example of using timers and interrupts to run a timed process. Unfortunately the atmega328p tends to freeze when too much is done when the main code is interrupted to do something else. The forum discussions are intense when new programmers place Serial.print() within timer interrupts :o . if this wasn't the case Tinker would be excellent because of its accuracy and consistency as a precise timer. I may keep this in mind as a alternate timer similar to attachInterrupt, but for now I think we will continue to compare millis() to a value and trigger within the main code stream.

ChrisTenone:
Using delay() was dirt simple.

Using BwoD (or Robin2's classic Several Things demo methind - same thing) was more complex, but most Arduino programmers can wrap their head around it.

Then your one-line, loop based timer that seemed to turn loop inside out. It was a good exercise for learning, and I jumped into it, trying out the code in some examples I used. But it was the opposite of self documenting code.

Now this, which seems to have taken complexity to the limit. It makes my head explode.

Please post some clearer examples using your library.

Thanks for your continued work on this topic!

Absolutly ChrisTenone I would be happy to. :slight_smile:

Simplest Basic use:

#include "ZTimer.h"
ZTimer TimerZ;

void setup() {
  pinMode(13, OUTPUT);
  Serial.begin(115200);
  Serial.println("Testing ZHomeslices ZTimer Library Basic Simple");
  TimerZ.SetWaitTime(1000); //Timer will trigger at 1 second intervals
  TimerZ.ResetTimer(true);  // reset the timer with restart flag true and enable the timer 
}

void loop() {
  if (TimerZ.CheckTime() == true) { // Check to see if time has expired 
    Serial.println(" The Basic Way");
    digitalWrite(13, !digitalRead(13));               // Blink onboard LED
  }
}

Same but using Callbacks just like attachinterrupt() does but without interrupting the main flow:

#include "ZTimer.h"
ZTimer TimerZ;

void setup() {
  pinMode(13, OUTPUT);
  Serial.begin(115200);
  Serial.println("Testing ZHomeslices ZTimer Library Call Back");
  TimerZ.SetCallBack(MyFunction); // Attach MyFunction as the callback this function is triggered each time CheckTime() returns true
  TimerZ.SetWaitTime(1000); //Timer will trigger at 1 second intervals
  TimerZ.ResetTimer(true);  // reset the timer with restart flag true and enable the timer 
}

void loop() {
  TimerZ.CheckTime();
}

void MyFunction(){
    Serial.println(" The Callback Way");
    digitalWrite(13, !digitalRead(13));               // Blink onboard LED
}

Same but using Callbacks with Lambda:

#include "ZTimer.h"
ZTimer TimerZ;

void setup() {
  pinMode(13, OUTPUT);
  Serial.begin(115200);
  Serial.println("Testing ZHomeslices ZTimer Library Call Back With Lambda");
  TimerZ.SetCallBack( // Call back and Lamba to allow for many functions to be called when CheckTime() returns true.
    []() {     // lambda inline function starts here    its just a funciton without a name you put inline  it becomes part of ZTimer to be used when needed          
      Serial.println(" The Callback Labmda Way");
      digitalWrite(13, !digitalRead(13));               // Blink onboard LED
    }         // lambda function ends here
  );
  TimerZ.SetWaitTime(1000); //Timer will trigger at 1 second intervals
  TimerZ.ResetTimer(true);  // reset the timer with restart flag true and enable the timer 
}

void loop() {
  TimerZ.CheckTime();
}

Everything else is control
How to manage and change control
Basic with no frills way using basic example

#include "ZTimer.h"
ZTimer TimerZ;

void setup() {
  pinMode(13, OUTPUT);
  Serial.begin(115200);
  Serial.println("Testing ZHomeslices ZTimer Library Basic Simple Added Features");
  TimerZ.Micros();                  // Uses micros() to calculate durations.
  TimerZ.SetWaitTime(1000000);      //Timer will trigger at 1 second intervals
  TimerZ.Every();                   // Wait Time is added to Last time to get the next time If a long pause occures this will wind up and cause multiple triggers catching up to present time.
  TimerZ.ResetTimer(true);          // reset the timer with restart flag true and enable the timer 
}

void loop() {
  if (TimerZ.CheckTime() == true) { // Check to see if time has expired 
    Serial.println(" The Basic Way ");
    digitalWrite(13, !digitalRead(13));               // Blink onboard LED
  }
}

An alternative Way:

#include "ZTimer.h"
ZTimer TimerZ;

void setup() {
  pinMode(13, OUTPUT);
  Serial.begin(115200);
  Serial.println("Testing ZHomeslices ZTimer Library Basic Simple Added Features alternative way");
  TimerZ.Micros()                  // Uses micros() to calculate durations.
        .SetWaitTime(1000000)      //Timer will trigger at 1 second intervals
        .Every()                  // Wait Time is added to Last time to get the next time If a long pause occures this will wind up and cause multiple triggers catching up to present time.
        .ResetTimer(true);          // reset the timer with restart flag true and enable the timer 
}

void loop() {
  if (TimerZ.CheckTime() == true) { // Check to see if time has expired 
    Serial.println(" The Basic Way ");
    digitalWrite(13, !digitalRead(13));               // Blink onboard LED
  }
}

Why use callbacks with lambda/function example:
Fun example using ZTimer Library "Driving with the kids"

#include "ZTimer.h"
ZTimer TimerZ;
bool Driving = true;

void setup() {
  Serial.begin(115200);
  Serial.println("Testing ZHomeslices ZTimer Library Driving with the kids");
  randomSeed(analogRead(0));
  TimerZ.SetCallBack( // Call back and Lamba to allow for many functions to be called when CheckTime() returns true.
    []() {     // lambda inline function starts here    its just a funciton without a name you put inline  it becomes part of ZTimer to be used when needed          
      if(Driving) Serial.println(" Yes We are Finally here!");
      Driving = false;
    }         // lambda function ends here
  );
  TimerZ.SetWaitTime(random(10000,20000)); //Timer will trigger at 5 second intervals
  TimerZ.StartTimer();  //Timer will run once and return true once completed
}

void loop() {
  if(Driving){// If true We must still be going 
    delay(random(200,3000)); // random spam delay to shut up kids and to represent the annoyance of using delay()
    switch(random(0,4)){
      case 1:
         Kid1();
      break;
      case 2:
         Kid2();
      break;
      case 3:
         Kid3();
      break;
    }
  } 
}

void Kid1(){
  Serial.println(" Are we there Yet");
  TimerZ.CheckTime(); //check timer
}
void Kid2(){
  Serial.println(" I'm Hungry");
  TimerZ.CheckTime(); //check timer
}
void Kid3(){
  Serial.println(" I got to go potty");
  TimerZ.CheckTime(); //check timer
}

Let me know what you think :slight_smile:

Z

MOVED... Berried in some unknown forum category :confused:
I guess this isn't worth the effort of sharing.

Would you like it in Programming?

You have come a long way, thanks for sharing.

.

CrossRoads:
Would you like it in Programming?

My hope was for some reviews and advise for improvements This community has helped me tremendously. I enjoy sharing my success. Where would you suggest this be posted for review and further testing by the community :slight_smile:
Z

LarryD:
You have come a long way, thanks for sharing.

Thank You :slight_smile:
After fiddling around with macros which are fun, You shared with me your structured timer and that gave me the kick I needed to create this. I have added to it and created basic functions for all the features to easily configure the timer in much the same way your init function did. With the ability to stack the functions like JQuery (Web Programming with javascript) does the configuration is much easier to read. with the addition of the callback features and inline lambda functions this has become incredibly powerful I give you full credit for my inspiration LarryD Thank you again :slight_smile:
Z

zhomeslice:
MOVED... Berried in some unknown forum category :confused:
I guess this isn't worth the effort of sharing.

Oh but it is, Z! I like to stroll through the Gallery every now and then just for the inspiration. Finding your new work there was fun.

Thank you for sharing your work, AND for the additional examples you subsequently posted - I'm with my extended family this weekend, about 200 miles from my Arduinos, but I'm 'chomping at the bit' (there are horses here) to play with ztimer, when I get back to the school next week
.

I have not used, heard of Lambda functions, going to have to look into the technique.

Seems like the links in the opening post don't work.

.

You may find this interesting:
http://forum.arduino.cc/index.php?topic=396591.0

As a result my preference would be to
Change:
if (restart) lastTime = (everyTime) ? (lastTime + waitTime) : Now;
To:
if (restart) lastTime = (everyTime) ? (lastTime + Now) : Now;

Or, use method 4 as suggested in the discussion.

But, there could be an argument to leave it as is.

I would leave this posting here.
.

LarryD:
I have not used, heard of Lambda functions, going to have to look into the technique.
Seems like the links in the opening post don't work.

Post #6 Link: Blink without delay Macros "Simplifying the New Arduino Programmers Life" - Libraries - Arduino Forum ... Stupid GUI editor keeps on adding trash to the link every time I edit the post lol

Lambda is excellent! it is an anonymous function or a function without a name.
See my recent forum post Are anonymous function or lambda possible with UNO? [YES] [solved]
I knew that lambda was possible but I didn't know what it was called. I used it like crazy with Javascript and website development but javascript doesn't quite port to C. I was using lamba and didn't even know it (Self Taught) to do crazy web page manipulation! In fact this very website is brought to us using lambda lol
Just View source and go to line 192
Javascript .ready( with inline callback Lambda function(){ call starts here!

$(document).ready(function() {

note that JQuery library in the above javascript code uses $ as some kind of macro for quickly accessing its class (Cheaters) :slight_smile:
the above code is saying when the webpage "document" is ready trigger this inline funciton. Easy to read!
C lambda starts out differently but its really just the same.

MyFunction(document).ready([]() {

so anything in arduino that takes a callback like attachInterrupt can handle inline lambda!
a Tachometer code using inline lambda and attachInterrupt():

#define interruptPin 2
volatile unsigned long timeX = 1;
volatile unsigned long LastTime;
volatile int PulseCtrX;

void setup() {
  attachInterrupt(digitalPinToInterrupt(interruptPin), 
    // inline lambda
    []() {
       unsigned long Time;
       Time = micros();
       timeX = (Time - LastTime); // this time is accumulative between readings
       LastTime = Time;
       PulseCtrX ++; // will usually be 1 unless something else delays the use of hte sample
    }  // end of lambda function
    , FALLING); // end of attachInterrupt()
}

void loop() {
// Other code to handle tachometer input
}

Thanks :slight_smile:
Z

LarryD:
You may find this interesting:
Blink Without Delay problem. Warning. - Programming Questions - Arduino Forum

As a result my preference would be to
Change:
if (restart) lastTime = (everyTime) ? (lastTime + waitTime) : Now;
To:
if (restart) lastTime = (everyTime) ? (lastTime + Now) : Now;
Or, use method 4 as suggested in the discussion.
But, there could be an argument to leave it as is.
I would leave this posting here.

if (restart) lastTime = (everyTime) ? (lastTime + Now) : Now;
Your suggestion isn't quite going to work lastTime would be a large number and Now is just as large adding them together would exponentially extend the time. :slight_smile:

The post addresses what I consider 2 timer modes "Every" and "After" mode. These modes can be switched at any time during program execution!
This is considered with the following line of code:

    if (restart) lastTime = (everyTime) ? (lastTime + waitTime) : Now; //get ready for the next iteration Every or (After) Has Different affects

Sorry. I tend to stick things on one line if I can. I know that it can be confusing but I struggle with spread out code in a similar way trying to get the big picture :slight_smile:

    if (restart){
       if(everyTime){
          lastTime = (lastTime + waitTime) ; //catches up when there was a big delay
       }else{
          lastTime =  Now; // interval plus the delay by code
       }
    }

"The first one catches up when there was a big delay. But sometimes that is wanted when it has to stay tuned to the time. I say: "it is not a bug, it is a feature". The second one is the interval plus the delay by code." quote from BulldogLowell Post#18 Blink Without Delay problem. Warning.

These two modes can be chosen using the following to functions in my class

       TimerZ.Every()                       // Wait Time is added to Last time to get the next time If a long pause occures this will wind up and cause multiple triggers catching up to present time.
       TimerZ.After()                       // After Wait time the Last time is given the current time to use which could cause loss in time depending on code.

These two functions just set the everyTime flag either true or false
Z

ChrisTenone:
Oh but it is, Z! I like to stroll through the Gallery every now and then just for the inspiration. Finding your new work there was fun.

Thank you for sharing your work, AND for the additional examples you subsequently posted - I'm with my extended family this weekend, about 200 miles from my Arduinos, but I'm 'chomping at the bit' (there are horses here) to play with ztimer, when I get back to the school next week
.

It is always nice to hang out with family. Here in the USA we are celebrating the "Thanks Giving Holliday" It is a great time to be with family and friends. Lucky me I invited them over to my house :slight_smile:
I look forward to hearing what you think.
Thanks for your support.
Z

"Sorry. I tend to stick things on one line if I can. I know that it can be confusing but I struggle with spread out code in a similar way trying to get the big picture"

I can only see two inches in front of me, I need a big picture.
I never use the ternary operator as I like to see things as they unfold, extra text is documenting and I need to be lead. :wink:

This was my attempt at a BWD Class a while back, but as mentioned I've been using a 'structure' contained in the sketch for visibility reasons.

#include <Arduino.h>

// CreateTimer.cpp
// CreateTimer.h"
//
// Rev 
//  1.00   October 2,  2015 Functional code
//  1.01   October 4,  2015 Renamed variables and functions. Added: After() Remaining() Elapsed()
//  1.02   October 10, 2015 Added the Repeat option to the Start function
//  1.03   Cctober 10, 2015 Made some name changes
//
//=============================================================================
//                    F U N C T I O N    P R O T O T Y P E S
//=============================================================================
/*
CreateTimer::
Start(unsigned long Interval);                      Starts your timer, requires an Interval 
StartRepeat(unsigned long Interval, long Repeats);  Starts your timer, 
                                                    requires an Interval, requires a "Repeat" value  
Restart(void);                                      The timer Interval is restarted
Enable(void);                                       Allow timer action
Disable(void);                                      Disable timer action
SetInterval(unsigned long, Interval);               Change timer Interval
IsEnabled(void);                                    bool returns the timer enable status
Remaining(void);	                                 unsigned long returns the ms left in this timer
Repeat(void);                                       bool true when interval is reached, may repeat timing
                                                         if you used StartRepeat() to start the timer
Once(void);                                         bool true  when  interval is reached, false there after
While(void);                                        bool true  until interval is reached, false there after
After(void);                                        bool false until interval is reached, true there after  
*/

//                      C l a s s   C r e a t e T i m  e r  
 
class CreateTimer
{
public:
  //CreateTimer();
  //void begin();
  void Start(unsigned long Interval);  
  void StartRepeat(unsigned long Interval, long Repeats);  //1.02
  void Restart(void);
  void Enable(void);
  void Disable(void);
  void SetInterval(unsigned long Interval);
  unsigned long Remaining(void);	         //1.01
  bool IsEnabled(void);
  bool Repeat(void);
  bool Once(void);
  bool While(void);
  bool After(void);					         //1.01
  
private:
  unsigned long Elapsed();		            //1.01  No access to the user

  long _Repeats;                            //1.02
  bool enabled;
  unsigned long _Interval;
  unsigned long lastMillis; 
  unsigned long _temp;			           //temporary variable 1.01

};  // END of CreateTimer class  
// In C++ you must have a ; at the end of a class definition
//*****************************************************************************

#include "CreateTimer.h"

//
//*****************************************************************************
//                    C l a s s   C r e a t e T i m e r  
//*****************************************************************************
//Constructor
/*
CreateTimer::CreateTimer()
{
} // END of CreateTimer()
*/

//********************************************************** 
//Initialization
/*
void CreateTimer::begin()
{
} // END of begin()
*/

// ********************************************************** 
// Initialize the timer. This starts the timing for this timer.
void CreateTimer::Start(unsigned long Interval)
{
  _Interval = Interval;
  _Repeats = -1;               //1.02
  lastMillis = millis();  
  enabled = true;
} // END of Start()

//********************************************************** 
// Initialize the timer. This starts the timing for this timer. "Repeats" is the number of repeating intervals.  
void CreateTimer::StartRepeat(unsigned long Interval,long Repeats)   //1.02
{
  _Interval = Interval;
  _Repeats = Repeats;            
  lastMillis = millis();  
  enabled = true;
} // END of StartRepeat()

//********************************************************** 
// Enable the timer
void CreateTimer::Enable(void)
{
  enabled = true;  
} // END of Enable()

//********************************************************** 
// Disable the timer
void CreateTimer::Disable(void)
{
  enabled = false;  
} // END of Disable()

//********************************************************** 
// Return true if the timer is enabled false if disabled
bool CreateTimer::IsEnabled(void)
{
  return enabled;
} // END of IsEnabled()

//********************************************************** 
// Restart the timing sequence
void CreateTimer::Restart(void)
{
  lastMillis = millis();  
} // END of Restart()

//********************************************************** 
//
unsigned long CreateTimer::Elapsed(void)	//1.01
{
  return millis() - lastMillis;
} // END of Elapsed()

//********************************************************** 
// Return the time left in the timer: >=0 time left <= interval
unsigned long CreateTimer::Remaining(void)	//1.01
{
  _temp = _Interval - Elapsed();
  if(_Interval >= _temp)
  {
    return _temp;
  }
  else
  {
    return 0;  //under flow, return zero
  }
} // END of Remaining()

//********************************************************** 
// Change the timer interval 
void CreateTimer::SetInterval(unsigned long Interval)
{
  _Interval = Interval;  
} // END of SetInterval()

//********************************************************** 
// Return false in the interval, return true at the end of the interval, then restart the timer
bool CreateTimer::Repeat(void)
{ 
  if(enabled && Elapsed() >= _Interval)
  {
    //_Repeats being negative indicates this is a continuous timer.
    if(_Repeats < 0)  //1.02
    {
      lastMillis = lastMillis + _Interval;
      return true;
    }
    //_Repeats being positive, indicates this is a timer that "Repeats" a given number of times.   1.02
	//2,147,483,647 is the maximum number the timer can repeat
    else if(_Repeats-- != 0)
    {
      lastMillis = lastMillis + _Interval;
      return true;
    }
    else
    {
      //We have now completed _Repeats number of Intervals 
      enabled = false;
      return false;	  
    }
  }

  return false;
} // END of Repeat()

//********************************************************** 
// Return false in the interval, return true "at" the end of the interval, then false there after
bool CreateTimer::Once(void)
{
  if(enabled && Elapsed() >= _Interval)
  {
    enabled = false;
    return true;
  }  

  return false;
} // END of Once()

//**********************************************************
// Return true while in the interval and false after the interval has expired 
bool CreateTimer::While(void)
{
  if(enabled && Elapsed() <= _Interval)
  {
    return true;
  }  

  enabled = false;
  return false;
} // END of While()

//**********************************************************
// Return false in the interval and true after the interval has expired 
bool CreateTimer::After(void)	//1.01
{
  if(enabled && Elapsed() <= _Interval)
  {
    return false;
  }  

  enabled = false;
  return true;
} // END of After()


// END of CreateTimer class definition

Will have to look into Lambda this week.

Example

#include <CreateTimer.h>
/*
Start(unsigned long Interval);                      Starts your timer, requires an Interval 
StartRepeat(unsigned long Interval, long Repeats);  Starts your timer, 
                                                    requires an Interval also requires a "Repeats" value  
Restart(void);                                      The timer Interval is restarted
Enable(void);                                       Allow timer action
Disable(void);                                      Disable timer action
SetInterval(unsigned long, Interval);               Change timer Interval
IsEnabled(void);                                    bool returns the timer enable status
Remaining(void);                                unsigned long returns the ms left in this timer
Repeat(void);                                       bool true when interval is reached, may repeat timing
                                                         if you used StartRepeat() to start the timer
Once(void);                                         bool true when interval is reached, then false there after
While(void);                                        bool true until interval is reached, false there after
After(void);                                        bool false until interval is reached, true there after  
*/

//Instantiate objects
CreateTimer MyTimer;  
CreateTimer My1stTimer;
CreateTimer My2ndTimer;  
CreateTimer My3rdTimer;  
CreateTimer FlashLED;
CreateTimer Flash2ndLED;  

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

  MyTimer.Start(5000UL);             //Start this timer with a 5 second Interval
  My1stTimer.Start(4000UL);          //Start this timer with a 4 second Interval
  FlashLED.Start(100UL);             //Start this timer with a 100ms Interval 
  My2ndTimer.Start(6000UL);          //Start this timer with a 6 second Interval
  Flash2ndLED.StartRepeat(500UL,20); //Start this timer with a 500ms Interval, repeat number = 20 times 
  My3rdTimer.Start(10000UL);         //Start this timer with a 10 second Interval

  pinMode(13,OUTPUT); //LED connected to this pin
  pinMode(12,OUTPUT); //LED connected to this pin
  pinMode(11,OUTPUT); //LED connected to this pin
  pinMode(10,OUTPUT); //LED connected to this pin
  pinMode(9,OUTPUT);  //LED connected to this pin
}

void loop()
{
  // The following 6 examples are non blocking
  
  //*************************************************************************
  //Ex: #1, This timer was started by: MyTimer.Start(5000UL); 
  //executes code while in an Interval period.
  if(MyTimer.While())     
  {
    //**********************************************************************
    //Ex: #2, This timer was started by: FlashLED.Start(100UL);  
    //executes code after an Interval period, the timer restarts automatically      
    if(FlashLED.Repeat()) 
    {
      digitalWrite(13,!digitalRead(13));
    }
  }

  Serial.print("Time left in MyTimer = ");
  Serial.println(MyTimer.Remaining());     //Outputs the time in ms left in this timer

  //*************************************************************************
  //Example #3 This timer was started by: My1stTimer.Start(4000UL);
  //executes code after an Interval has passed   
  if(My1stTimer.After())   
  {
    digitalWrite(12,!digitalRead(12));
    delay(50);             //so you can see the LED flash  
  }

  //  Serial.print("Time left in My1stTimer = ");
  //  Serial.println(My1stTimer.Remaining()); //Outputs the time in ms left in this timer

  //*************************************************************************
  //Ex: #4, This timer was started by: My2ndTimer.Start(6000UL);
  //executes code "ONCE ONLY" after an Interval period
  if(My2ndTimer.Once()) 
  {
    Serial.println("My2ndTimer Interval has expired");
    digitalWrite(11,!digitalRead(11)); //Toggle LED on then off
    delay(10);                         //so you can see the LED flash
    digitalWrite(11,!digitalRead(11));
  }

  //  Serial.print("Time left in My2ndTimer = ");
  //  Serial.println(My2ndTimer.Remaining()); //Outputs the time in ms left in this timer

  //*************************************************************************
  //Ex: #5, This timer was started by: My3rdTimer.Start(10000UL); 
  //executes code after an Interval period, then starts the Interval period timing again
  if(My3rdTimer.Once())    
  {
    Serial.println("My3rdTimer Interval has expired");
    digitalWrite(10,!digitalRead(10));
    delay(10);                 //so you can see the LED flash
    digitalWrite(10,!digitalRead(10));
    
    My3rdTimer.Start(10000UL); //Start this Interval period again
  }

  //  Serial.print("Time left in My3rdTimer = ");
  //  Serial.println(My3rdTimer.Remaining()); //Outputs the time in ms left in this timer

  //*************************************************************************
  //Ex: #6, This timer was started by:  Flash2ndLED.StartRepeat(500UL,20);  
  //executes code after an Interval. This happens a number of times, in this example, 20 times  
  if(Flash2ndLED.Repeat()) 
  {
    digitalWrite(9,!digitalRead(9));
    delay(100);                        //so you can see and count the the LED flashes
    digitalWrite(9,!digitalRead(9));

  }

  //  Serial.print("Time left in Flash2ndLED = ");
  //  Serial.println(Flash2ndLED.Remaining()); //Outputs the time in ms left in this timer

} //END of loop()

Edit
I have included:
StartRepeat(unsigned long Interval, long Repeats); Starts your timer, requires an Interval, requires a "Repeat" value

.

You may want to check your links in your posts.
They are either broken or go somewhere not expected.

LarryD:
You may want to check your links in your posts.
They are either broken or go somewhere not expected.

Thanks :slight_smile:
The gui editor is inserting trash within links. I'm surprised it hasn't been resolved. But I now know when it happens and I will try to catch them before posting :slight_smile:
How or who should I report this web site flaw to?

I am not experiencing any problems adding links here.

The work you have done is very interesting and stimulates one to further development, I like it.
However, back to your earlier quote:
"new users struggle with this every day and are confused on how to code blink without delay especially when it comes to getting the rollover properly handled"

If this method was introduced to 'new users' I think their eyes would glaze and blow up. :wink:
I still believe it is mandatory for new users master the very basic concept of BWD.
After all, if they cannot, IMO they will never advance very far.

.