Timer within a timer

Hi guys.

I finally completed my first Arduino sketch project with your help.
I do have a question though, to expand this first project.

As we already know the "Loop" section of a script acts like a timer, it takes a measured amount of time to complete the list of commands in the script, once it reaches the bottom of the script then "Delays" the commanded milliseconds, followed by returning to the top of the loop to start over.
I need to be able to have several commands inside the main loop execute every 6 minuets while the rest of the loop continues to loop at about every second.

Is it possible to have two loops operating at different delays like that? If so what prevents the outside main loop from resetting the inside loop that is running much slower?

thank you.

  • Your phrasing needs to be a bit different, but yes it’s doable.

Example


//                                            l o o p ( )
//================================================^================================================
//
void loop()
{ 
  //========================================================================  T I M E R  heartbeatLED
  //condition returned: STILLtiming(0), EXPIRED(1) or TIMERdisabled(2)
  //is it time to toggle the heartbeat LED ?
  if (heartbeatTIMER.checkTIMER() == EXPIRED)
  {
    //toggle the heartbeat LED
    digitalWrite(heartbeatLED, digitalRead(heartbeatLED) == HIGH ? LOW : HIGH);
  }
 
  //========================================================================  T I M E R  switches
  //condition returned: STILLtiming(0), EXPIRED(1) or TIMERdisabled(2)
  //is it time to check our switches ?
  if (switchesTIMER.checkTIMER() == EXPIRED)
  {
    checkSwitches();
  }
 
  //========================================================================  T I M E R  machine
  //condition returned: STILLtiming(0), EXPIRED(1) or TIMERdisabled(2)
  //is it time to service our State Machine ?
  if (machineTIMER.checkTIMER() == EXPIRED)
  {
    checkMachine();
  }
 
 
  //================================================
  //       Other non blocking code goes here
  //================================================
 
 
} //END of   loop()

2 Likes

The concept behind "blink without delay" to the rescue.

const byte fastLED = 13;
const byte slowLED = 12;

const unsigned long slowStuffInterval = 6 * 60 * 1000ul;
const unsigned long fastStuffInterval =      1 * 1000ul;

unsigned long fastStuffDone = 0;
unsigned long slowStuffDone = 0;

void setup() {
   pinMode(fastLED, OUTPUT);
   pinMode(slowLED, OUTPUT);
}

void loop() {
   unsigned long now = millis();

   if( now - fastStuffDone > fastStuffInterval ) {
      doFastStuff();
      fastStuffDone = now;
   }
   if( now - slowStuffDone > slowStuffInterval ) {
      doSlowStuff();
      slowStuffDone = now;
   }
}

void doFastStuff() {
   digitalWrite(fastLED, !digitalRead(fastLED));
}

void doSlowStuff() {
   digitalWrite(slowLED, !digitalRead(slowLED));
}
3 Likes

Hello allenjarosz

Check this mult-timer example:

//https://forum.arduino.cc/t/timer-within-a-timer/1390187
//https://europe1.discourse-cdn.com/arduino/original/4X/7/e/0/7e0ee1e51f1df32e30893550c85f0dd33244fb0e.jpeg
#define ProjectName "Timer within a timer"
#define NotesOnRelease "Arduino MEGA tested"
// make names
enum TimerEvent {NotExpired, Expired};
// make variables
uint32_t currentMillis = millis();
// make structures
//-----------------------------------------
struct TIMER
{
  uint32_t interval;
  uint32_t now;
  uint8_t expired(uint32_t currentMillis)
  {
    uint8_t timerEvent = currentMillis - now >= interval;
    if (timerEvent == Expired) now = currentMillis;
    return timerEvent;
  }
};
//-----------------------------------------
// make objects
TIMER timer6Minutes;
TIMER timer1Second;
//-----------------------------------------
// make application
void setup()
{
  Serial.begin(115200);
  for (uint8_t n = 0; n < 32; n++) Serial.println("");
  Serial.print("Source: "), Serial.println(__FILE__);
  Serial.print(ProjectName), Serial.print(" - "), Serial.println(NotesOnRelease);
  timer6Minutes = {6 * 60 * 1000ul, 0};
  timer1Second =  {1 * 1000ul, 0};
  delay(2000);
  Serial.println(" =-> and off we go\n");
}
void loop()
{
  currentMillis = millis();

  if (timer6Minutes.expired(currentMillis) == Expired)
  {
    Serial.println("timer6Minutes");
  }
  
  if (timer1Second.expired(currentMillis) == Expired)
  {
    Serial.println("timer1Second");
  }
}

Have a nice day and enjoy coding in C++.

2 Likes

Here's several different ways to achieve what you want:

1 Like

Some misconceptions to clear up here!

Not really. Those commands do take a little time to complete. But it's very difficult, impossible for a beginner, to know exactly how long they will take. So it's not a great way to make a timer.

Only if you put a delay() at the bottom of loop()! You don't have to have one. Generally only beginner/example code will have that. As soon as your coding gets more advanced, you realise that having a delay() in loop() causes problems.

You can only have one loop() (on almost all types of Arduino). But it's not a problem, you can do what you wanted, and much more, with just the one loop().

You would not use delay() to make your 6 timers. Only one delay() can be running at any time. Instead, you would use a different function: millis().

4 Likes

And distinct temporal variables — one for each task to be timed.