Switch between two codes

Maybe the OP is working through the tutorial in between real life weekend.

When there is code that does some things, waits, and repeats that few or many times, the whole sequence can be cut into what is done and the waits between as a step by step process.

I put all that code into a void function() that will run over and over in loop, it may need to check the time against a wait.

I only need one timer for all the delays being replaced, each sets start time and how long to wait then the one timer runs it.
So you will see a 1-shot timer at the start of the function, it only runs when set and turns itself off when done.

After the timer is a switch-case statement. A variable holds which step to run, at the end of the step the variable is ++.

In code it looks like this, only with more code in the steps.

not tested

void undelayExample() // this function does not block yet does run code steps on time
{
  static byte doStep =0; // static variables stay when scope ends, hold values
  static unsigned long doWaitStartMs; doWaitMs = 0;

  if ( doWaitMs > 0 )  //  1-shot timer only runs when wait > 0
  {
    if ( millis() - doWaitStartMs < doWaitMs )  // wait is NOT over
    {
      return;  //  instead of waiting in a delay(), the rest of the sketch gets a chance to run
    }
    else  //  wait is over
    {
      doWaitMs = 0;  //  turn 1-shot off
    }
  }

  switch ( doStep )
  {
    case 0 :  //  doStep == 0
    // do the first step
    doStep = 1;  //  when the timer finishes, the next step code will run
    doWaitStartMs = millis();  //  set start time for the timer
    doWaitMs = 100;  //  setting wait time triggers the 1-shot timer next time the function is run
    break;

    case 1 :  //  doStep == 1
    // do the second step
    doStep = 2;  //  when the timer finishes, the next step code will run
    doWaitStartMs = millis();  //  set start time for the timer
    doWaitMs = 500;  //  setting wait time triggers the 1-shot timer next time the function is run
    break;

  ............................................

    case 20 :  //  doStep == 20
    // do the last step
    doStep = 0;  //  when the timer finishes, the next step will be the start
    doWaitStartMs = millis();  //  set start time for the timer
    doWaitMs = 60UL*60UL*1000UL;  //  run again an hour from now, UL is to keep the compiler from using 16-bit signed
    break;
  }
}