I see this pop up often so I thought I'd pen a simple note for everyone.
Most use delay() to keep their place in line (program counter) until the given time has passed. Fine, if you feel that delay() is the only way to do this, so be it. You are NOT however, handcuffed during that period.
If you examine the delay function, which can be found in wiring.c, you'll see this:
void delay(unsigned long ms)
{
uint32_t start = micros();
while (ms > 0) {
yield();
while ( ms > 0 && (micros() - start) >= 1000) {
ms--;
start += 1000;
}
}
}
Tucked unobtrusively in the middle is a function called yield(). Further investigation will reveal the definition of yield() in hooks.c.
static void __empty() {
// Empty
}
void yield(void) __attribute__ ((weak, alias("__empty")));
You'll note that it is defined as empty with an attribute of weak. What this means, empty, is that as it sits, it does nothing. Weak means that you can re-define it in your own code and the compiler won't have a fit.
So, drop a little routine
void yield()
{
// do something
}
into your sketch and keep checking for serial input or pin changes or what ever while you delay. Just remember, yield() takes no arguments and returns nothing.
The other option is to do what many have already done and write your own routine:
return-type wait(uint32_t ms [,arguments])
{
uint32_t _now = millis();
while ((millis() - _now) < ms)
{
// do something here;
}
return whatever;
}
and then you've got complete control over what happens while you wait.
Cheers.