Arduino and how to avoid delay() – Part 1
The main problem with using delay() in your Arduino sketch is simply: it will block the whole system for the amount of time you specified. Since your microprocessor is pretty fast compared to most of the delay() time he is very bored, gets lonely and depressive if you do not care for him…
While that could be okay for most circumstances and projects, when going more advanced in programming, and your projects get more complex, it could be pain in the %&?.
But there is a way out of the delay-dilema and its available right at your hands: millis()
What about the idea that you dont block the system for a specified amount of time but counting time, visiting the value each loop() (which is done pretty fast), if it reaches a certain value”fire” something, if not just do the next thing in the loop()?
The Arduino method millis() counts the time in milliseconds since the Arduino started. That could be the impressive number of 4,294,967,295 at maximum (what is about 50 days) what is btw an “unsigned long”. One seconds is eg. 1,000 milliseconds, one minute is eg. 60,000 milliseconds etc.
So what can we do?
Lets say we need these things:
- A trigger value -> your “delay” value
- A value that keeps track of the last “event” when the trigger was “fired”
- A structure to check “if” the the value has been reached and handle it
Converting this concept to code could look something like this:
unsigned long lastEvent;
int triggerValue = 1000;
if(millis()-lastEvent >= triggerValue)
lastEvent = millis();
What are we doing here:
We check each loop if millis()-lastEvent is greater or equal than your trigger value.
As an example maybe we have these values: 3500 – 3000 >= 1000. That would result in this calculation: 500 >= 1000 and will not fire since the condition is not met. If the millis() exceeds 4000 the event will fire: 4001-3000 >= 1000 is 1001 >= 1000 and then the if()-structure will become true.
The first thing we need to do after the if()-structure became “true” is to save the milliseconds of the last event to a global variable (lastEvent) so we can check again afterwards. Then we can do what we like to fire at each event: doSomehtingGreat().
Thats pretty nice since you can multiple of this timers in parallel and the best thing: it does not block the execution of other code thats running in the loop() so you can do asynchronous things.
To make this more convenient lets pack this stuff in a Arduino class and enjoy it even more: head over to part 2!