Stopwatch with Pause/Lap  6 digit 7 seg LED. HELP!

No sweat! Well, I say "no sweat" assuming that the gunk that I try to pass as English prose can be deciphered. :smiley:

Start at the top of loop. The current time is recorded and compared to the previous recorded time checking for a difference of 10 ms...

  currentmillis = millis();  // read the time.
  if (currentmillis - previousmillis >= interval) // 10 milliseconds have gone by
  {

Slowly scroll through loop. You'll notice that there is quite a lot of code. Lots of integer math (which is the correct choice). Lots of if's. Then there are some calls to digitalWrite and shiftOut.

How long do you think all that code takes to run? Let's say it takes 10.001 ms.

We go back around to the top of loop. The current time is recorded and compared to the previous recorded time checking for a difference of 10ms. Because the code in loop took 10.001 ms, the condition is already true and hundredths is incremented. But what happens to the 0.001 ms? Because the "line in the sand" is moved up to the current time...

    previousmillis  = currentmillis;  // save the time for the next comparison

...the 0.001 ms is lost. On a single pass through loop, the 0.001 ms is irrelevant. But, after 1000 passes through loop, the error adds up to a full millisecond. Add enough of those tiny errors and eventually we get to 2 seconds lost out of 5 minutes.

The problem is much easier to visualize if you assume that loop takes 11 milliseconds (or more; like 2 full seconds) to run. In that case, we add one to hundredths but we should have added 1.1.

Does that make sense?


There are at least three solutions to the problem...

The first is to reduce the amount of code in loop. Changing the appropriate variables (like hundredths) to byte will certainly help. But, without very careful analysis and testing we cannot prove that we've solved the problem.

The second solution is to loop while "currentmillis - previousmillis >= interval" is true AND change "previousmillis = currentmillis;" to "previousmillis += interval;". This solution is very likely to fully succeed. If there is still too much work to do, in the worst case, the display will "jump ahead" by one one-hundredth when the error accumulates to a full 10 ms.

The final solution is remove the incrementing code and calculate the various parts each pass through loop. This solution is nice because the display is guarenteed to always be as accurate as possible at the bottom of loop. But, it requires a bunch of fiddly math.