Decades ago I wrote a tiny non-blocking timer function in Pascal, which resulted in a lot of likes.
Here's my Arduino adaptation. I think it's great for learning purposes.
There's just a single function chkTimer which needs to be included in your sketch.
For each independent running timer you must declare an unsigned long (=4 bytes) variabele to store the expiration time. The function returns true when the expiration time was reached. When that happens a new expiration time is stored in the variabele by adding the value of loopTime to the expireTime variabele. So continuously polling the function will result in a repetitive loop that checks true every loopTime.
It can do milliseconds or microseconds depending on which line containing the currentTime declaration is commented out.
The maximum single shot duration is 232-1 ~ 50 days for ms or 72 min for µs.
The maximum loopTime duration is 231-1 ~ 25 days for ms or 36 min for µs .
Here's the function
/* Function chkTimer resets and returns true when the timer expired.
* It stores the end time in the unsigned long variabele passed to &expireTime.
* When expired the value of loopTime is added to the expireTime so continuously
* polling this function checks true every loopTime.
* The time scale can either be in milliseconds or in microseconds, depending
* on which line containing currentTime is commented out.
* All information the timer needs is stored in the variable, so to have more
* independent timers, just declare more variabeles.
* Written by Femme Verbeek 30-4-2020
* Use for free
*/
boolean chkTimer (unsigned long &expireTime, unsigned long loopTime) {
unsigned long currentTime = millis(); // use this for milliseconds
//unsigned long currentTime = micros(); // use this for microseconds
if (currentTime >= expireTime) //check the timer
{ if ( (bitRead(currentTime,31) == 1) &&
(bitRead(expireTime,31) == 0) ) //check overflow
return false; //integer overfow but not expired
else { //expired
expireTime += loopTime; //set new expireTime
return true; } //OK, chkTimer was triggered
} else return false; //not expired
}
Unlike most polling timers, this one will keep running fine when the integer value overflows after 50 days of running. So it can be used as the basis for longer running counters. It checks for the transition of bit 31. Assuming that the polling frequency is much faster than the timer loop, expireTime will overflow first, followed by currentTime within the loopTime duration.
Here's a test program.
void setup() {
Serial.begin(115200);
}
unsigned long mytimer1 = 0; //start timing loop immediately
unsigned long mytimer2 = 5000; //wait 5 seconds before starting timing loop
unsigned long mytimer3 = 10000; //wait 10 seconds before starting timing loop
void loop() {
if (chkTimer(mytimer1,377)) Serial.print("Hello ");
if (chkTimer(mytimer2,610)) Serial.println("world ");
if (chkTimer(mytimer3,1597)) Serial.println("and the universe ");
}
The initial value of the timers equals the one shot time in ms before the repetitive loop starts.
The loopTime values of 377, 610, 1597 are Fibonacci numbers for maximum chaos.
Comments welcome.