You will not be able to write a non-blocking function that replaces delay. You need to think differently.
You can however write a function that checks if a certain duration has lapsed.
/*
check if a duration has lapsed
In:
duration (in ms)
Returns:
false if duration has not lapsed, else true
*/
bool wait(unsigned long duration)
{
static unsigned long startTime;
static bool isStarted = false;
// if wait period not started yet
if(isStarted == false)
{
// set the start time of the wait period
startTime = millis();
// indicate that it's started
isStarted = true;
// indicate to caller that wait period is in progress
return false;
}
// check if wait period has lapsed
if(millis() - startTime >= duration)
{
// lapsed, indicate no longer started so next time we call the function it will initialise the start time again
isStarted = false;
// indicate to caller that wait period has lapsed
return true;
}
// indicate to caller that wait period is in progress
return false;
}
And in loop() you can use something like
void loop()
{
bool waitFinished = wait(1000);
if(waitFinished == true)
{
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN);
}
// do something else here
}
Now this a 'difficult' way to do a blink-without-delay but it's there to demonstrate the use of the wait function. Note that this code is not tested.
Now, if you have a need for a delay, it usually indicates that your program has a few steps to execute in sequence. In that case you can look at statemachines.
In the below example, a statemachine is used.
First we define the steps (states); in this case there are 4
1)
switch led on
2)
wait for given duration
3)
switch led off
4)
wait for given duration
Each time a step is completed, the code will go to the next step. Using the earlier wait function, the code will not go to the next step till the wait function indicates that the duration has lapsed.
#define ST_LEDON 0 // state where the led will be switched on
#define ST_WAITON 1 // state where we wait till the led has been on for a given duration
#define ST_LEDOFF 2 // state where the led will be switched off
#define ST_WAITOFF 3 // state where we wait till the led has been off for a given duration
void setup()
{
pinMode(LED_BUILTIN, OUTPUT);
}
void loop()
{
// remember the current state; initialise with ST_LEDON
static byte currentState = ST_LEDON;
switch (currentState)
{
case ST_LEDON:
// switch the led on
digitalWrite(LED_BUILTIN, HIGH);
// go to the next step (state)
currentState = ST_WAITON;
break;
case ST_WAITON:
// check if on duration has lapsed
if (wait(750) == true)
{
// if lapsed, go to next step (state)
currentState = ST_LEDOFF;
}
break;
case ST_LEDOFF:
// switch the led off
digitalWrite(LED_BUILTIN, LOW);
// go to the next step (state)
currentState = ST_WAITOFF;
break;
case ST_WAITOFF:
// check if off duration has lapsed
if (wait(250) == true)
{
// if lapsed, go to next step (state)
currentState = ST_LEDON;
}
break;
}
}
/*
check if a duration has lapsed
In:
duration (in ms)
Returns:
false if duration has not lapsed, else true
*/
bool wait(unsigned long duration)
{
static unsigned long startTime;
static bool isStarted = false;
// if wait period not started yet
if (isStarted == false)
{
// set the start time of the wait period
startTime = millis();
// indicate that it's started
isStarted = true;
// indicate to caller that wait period is in progress
return false;
}
// check if wait period has lapsed
if (millis() - startTime >= duration)
{
// lapsed, indicate no longer started so next time we call the function it will initialise the start time again
isStarted = false;
// indicate to caller that wait period has lapsed
return true;
}
// indicate to caller that wait period is in progress
return false;
}
Code tested