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;
}
}