Let me talk about why real quick, because I know it comes up and confuses people quite often.
Let's talk first about the code that sets the old time to millis. I'm going to use the previousMillis
and currentMillis
names from BlinkWithoutDelay.ino
even though I hate those names just so I don't have to rewrite the whole thing. But I am going to abbreviate as PM and CM.
In the normal BWoD we have a line like this:
previousMillis = currentMillis;
and you'll sometimes see it like this:
previousMillis = millis();
with the difference being that if it takes some time to complete whatever task you are doing in the if statement then the second method will get the actual time it completed and the first will get the time that it started.
So let's imagine that we are timing something at 50Hz, 20ms. Let's say we start with millis at 0 and PM at 0. 20ms later CM is 20 and 20 - 0 is 20 so the thing happens and PM gets set to 20. 20ms later CM is 40 and 40-20 is 20 so it happens again and PM gets set to 40.
Now let's imagine that on the next loop something else takes a long time and the timing misses 60 exactly and gets checked instead at 61. So CM is 61 and 61-40 is greater than 20 so the thing happens. But now PM gets set to 61, not 61.
So next it happens at 81, then 101, then let's say something takes a long time again and it doesn't get checked until 103. So now PM gets set to 103 and the next round happens at 113 then 123...
You see the patter developing. Every time the check is a little late, the PM variable gets a few extra millis added. So the events get progressively later and later and out of sync.
NOW THE OTHER WAY:
So let's talk about what I did in the last post. Instead of setting the PM to the actual time, I just added the interval to it. This means that when the timing gets checked late and CM is 61, PM still just gets set to 60 meaning the next event will happen only 19ms later and get back in sync.
The problem there is when you need to enforce a minimum interval. Let's imagine for a second that something took a really really long time and while PM was at 60 it doesn't get checked again until millis is at 120.
So 120 - 60 is greater than 20 so an event happens. And 20 gets added to PM to make 80. On the very next loop the timing gets checked again and this time CM is probably still 120 and PM is 80 and 120 - 80 is still greater than 20 so another event is fired and PM gets set to 100. On the very next loop another event will fire because it is still more than 20ms between CM and PM. So PM gets set to 120 now.
So you can see that in the example where we set PM to millis or currentMillis
we are able to enforce a minimum interval between events and no two events will ever happen less than 20ms apart. But we run the risk of the events getting out of sync.
With the add-the-interval method we are able to always stay in sync, but if events are missed then they will happen rapid-fire style to catch up. You can stop that with some additional clever code to check if more than one interval has passed, but you still will have cases where the 20ms was actually 18 or 19 between some events.