Running multiple waiting functions simultanously

I looked at that.

There were some issues with scoping and keeping the multiple timer1s coordinated with timer2.

Here's some modified code using code tags:

// https://wokwi.com/projects/327743322672071250
// modified from 
// https://forum.arduino.cc/t/timing-utility-an-alternative-to-delay/965542
// 
// https://forum.arduino.cc/t/running-multiple-waiting-functions-simultanously/975765/91

const byte led1 = 5;
const byte led2 = 7;

void setup() {
  Serial.begin(9600);
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
}

//--------------------------------------------------
int tickPeriod = 100; //Défines the duration of one tick in milliSeconds. All timers are incremented at this tick rate.
// Also defines timers resolution. The tickPeriod should be longer than the void-loop duration.
unsigned long int tickCounter = 0; //counts millis divided by tickPeriod.
unsigned int mainTimer = 0; //mainTimer increases every tickPeriod. All declared timers rely on mainTimer to maesure time.

unsigned int timer1[4] = {0, 0, 0, 0 }; //declare 2 timers
unsigned int timer2[4] = {0, 0, 0, 0 };

//--------------------------------------------------

void loop() {
  //EXAMPLE OF USE:
  tickTimers(); //Increase all declared timers by one at each tickPeriod milliSeconds.
  flashLed1(5); //flash LED 1, period of 1 sec.
  flashLed2(7); //flash LED 2, period of 1.4 sec.
}

//--------------------------------------------------
// Note: only for demonstration purpose: flashLed could be more efficient...
void flashLed1(int period) {
  static unsigned int timer1[4] = {0, 0, 0, 0 };
  static byte toggle = 0;
  startTimer(timer1, period);
  if (checkTimer(timer1)) {
    if (toggle == 0) {
      Serial.println(" LED 1 is ON");
      toggle = 1;
      digitalWrite(led1, HIGH);
    }
    else {
      Serial.println(" LED 1 is OFF");
      toggle = 0;
      digitalWrite(led1, LOW);
    }
  }
}

//-----------------------------
void flashLed2(int period) {
  static unsigned int timer1[4] = {0, 0, 0, 0 };
  static byte toggle = 0;
  startTimer(timer1, period);
  if (checkTimer(timer1)) {
    if (toggle == 0) {
      Serial.println(" LED 2 is ON");
      toggle = 1;
      digitalWrite(led2, HIGH);
    }
    else {
      Serial.println(" LED 2 is OFF");
      toggle = 0;
      digitalWrite(led2, LOW);
    }
  }
}

//------------------------------------- TIMERS UTILITY -------------------------------------

void tickTimers() { //Must be called at least once in a void ... loop
  //Increments tickCounter up to tickPeriod, and then increments mainTimer.
  if ((unsigned long)(millis() - tickCounter) >= tickPeriod) {
    tickCounter += tickPeriod;
    Serial.print("time = "); Serial.println(mainTimer); mainTimer ++;
  }
}

//-----------------------------
//A timer is an array of 4 unsigned integers.
// array[0] is the timerPeriod: the timer increments up to this Period before checkTimer returns true.
// A null (0) timerPeriod is iterpreted as an infinite Period: the timer is counting but will never end.
// array[1] is the StartedTime: a copy of mainTimer taken when the timer was initially started with startTimer.
// array[2]is the time when timer was paused: a copy of mainTimer when pauseTimer was called.Used to resumeTimer.
// array[3] is the timer status: 0: the timer is running, !=0: the timer is paused.
// PRINCIPLE: To measure time, one takes note of mainTimer when startTimer is called.
// Elapsed time = actual (running) mainTimer minus the originally noted mainCounter.

const byte timerPeriod = 0;
const byte startedTime = 1;
const byte pausedTime = 2;
const byte timerStatus = 3;
const byte timerRunning = 0;
const byte timerPaused = 1;

//-----------------------------ok
void startTimer (unsigned int aTimer[], unsigned int aTimerPeriod) {

  //NOTE: **** startTimer has no effect on an already running timer, allowing to call startTimer in a loop; ****

  if (aTimer[timerPeriod] != 0) {
    return;
  }
  else {
    aTimer[timerPeriod] = aTimerPeriod; //the timer becomes active:
    aTimer[startedTime] = mainTimer; //note the startTime.
  }
}

//-----------------------------ok
void runTimer(unsigned int aTimer[]) {
  aTimer[timerStatus] = timerRunning; //let the timer run.
}
//-----------------------------ok
void rewindTimer(unsigned int aTimer[]) { //rewinds the timer to zero and let it run.
  aTimer[startedTime] = mainTimer;
  aTimer[timerStatus] = timerRunning; //let the timer run
}

//-----------------------------ok
void pauseTimer(unsigned int aTimer[]) { // Pause timer
  aTimer[pausedTime] = mainTimer; //write a copy of actual time; used by resumeTimer.
  aTimer[timerStatus] = timerPaused;
}

//-----------------------------ok
void resumeTimer(unsigned int aTimer[]) { //make a timer run again after beeing paused.
  if (aTimer[timerPeriod] == 0) {
    return;
  }
  aTimer[startedTime] = mainTimer - aTimer[pausedTime] + aTimer[startedTime]; //puts the timer where it was when paused.
  aTimer[timerStatus] = timerRunning; //remove pause = run timer
}
//-----------------------------ok
bool checkTimer (unsigned int aTimer[]) { //Checks if the timer arrived at its end.
  if (aTimer[timerPeriod] == 0 || aTimer[timerStatus] != timerRunning) { //If timer is not active or paused.
    return false;
  }
  if (mainTimer - aTimer[startedTime] >= aTimer[timerPeriod]) { // if time elapsed...
    aTimer[startedTime] += aTimer[timerPeriod]; //advance the start time.Optionnally: aTimer[startedTime] = mainTimer;Texte préformaté
    return true; //return true if time elapsed.
  }
  else {
    return false;
  }
}

//-----------------------------
void setTimerPeriod (unsigned int aTimer[], unsigned int aTimerPeriod) {
  aTimer[timerPeriod] = aTimerPeriod; //set new period
  aTimer[startedTime] = mainTimer; //rewind timer
}
//------------------------------------- END OF TIMERS UTILITY -------------------------------------

Testing in:

1 Like