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

Hmm, doesn't seem to matter how long I set the interval, with the code as written there is 1mS jitter as to when latchpin goes from High to Low. The whole time update section & incrementing, rolling over, etc, takes .02mS The whole shift out sequence only takes 0.8mS.

On to the previousMillis update ...

Okay, I updated the code as follows:

unsigned long currentmillis = 0;
unsigned long previousmillis = 0;
unsigned long interval = 10;
unsigned long elapsedmillis = 0;

byte latchpin = 2; // connect to pin 12 on the 74HC595
byte clockpin = 3; // connect to pin 11 on the 74HC595
byte datapin = 4; // connect to pin 14 on the 74HC595
byte testpin5 = 5;

byte ones_seconds = 0;
byte tens_seconds = 0;
byte ones_minutes = 0;
byte tens_minutes = 0;
byte tenths = 0;
byte hundredths= 0;


int segdisp[10] = {
  63,6,91,79,102,109,125,7,127,111 }; //segment references using 74HC595 Shift Registers
//The above numbers light up different segments of a digit

byte time_update = 0;// added new flag
void setup()
{
  pinMode(latchpin, OUTPUT);
  pinMode(clockpin, OUTPUT);
  pinMode(datapin, OUTPUT);
  pinMode(testpin5, OUTPUT);
  Serial.begin(57600);
}

void loop()
{
  currentmillis = millis();  // read the time.
  elapsedmillis = currentmillis - previousmillis;

  if (elapsedmillis >= interval) // 10 milliseconds have gone by
  {
    previousmillis  = previousmillis + elapsedmillis;  // save the time for the next comparison
    time_update = 1;
//    if (elapsedmillis>10){                       // commented this out to display time below
//      Serial.println (ones_seconds,DEC);
//      Serial.println (elapsedmillis,DEC);
//    }
    // digitalWrite (testpin5, LOW); // used to see how long the nex section took
  }
  // else {digitalWrite (testpin5, HIGH);}  // set flag to upate & shift out

  if (time_update == 1){  // no updating if not at 10ms interval, skip this whole section
    // increment the counters, roll as needed, shift the digits out

    time_update = 0; // reset for next pass thru

    hundredths = hundredths +1;

    if (hundredths == 10){
      hundredths = 0;
      tenths = tenths +1;
    }

    if (tenths == 10){
      tenths = 0;
      ones_seconds = ones_seconds +1;
      Serial.print ( tens_minutes,DEC);  // sending minutes/seconds to the screen
      Serial.print (ones_minutes,DEC);
      Serial.print (tens_seconds,DEC);
      Serial.println(ones_seconds,DEC);
    }

    if (ones_seconds == 10){
      ones_seconds = 0;
      tens_seconds = tens_seconds +1;
    }

    if (tens_seconds == 6){
      tens_seconds = 0;
      ones_minutes = ones_minutes +1;
    }

    if (ones_minutes == 10){
      ones_minutes = 0;
      tens_minutes = tens_minutes +1;
    }
    if (tens_minutes == 6){
      tens_minutes = 0;
    }
    // digitalWrite (testpin5, HIGH); // used to see how long the if's were taking
    // counters are all updated now, just do the shiftout one time here:
    digitalWrite(latchpin, LOW); // send the digits down to the shift registers!
    shiftOut(datapin, clockpin, MSBFIRST, segdisp[hundredths]); // print the % first "hundredths" digit
    shiftOut(datapin, clockpin, MSBFIRST, segdisp[tenths]); // print the tens of hundredths digit
    shiftOut(datapin, clockpin, MSBFIRST, segdisp[ones_seconds]); // print the % first "seconds" digit
    shiftOut(datapin, clockpin, MSBFIRST, segdisp[tens_seconds]); // print the tens of seconds digit
    shiftOut(datapin, clockpin, MSBFIRST, segdisp[ones_minutes]); // print the % first "minute" digit
    shiftOut(datapin, clockpin, MSBFIRST, segdisp[tens_minutes]); // print the tens of minutes digit
    digitalWrite(latchpin, HIGH);

  } // end if time to be updated

} // end void loop

am seeing that elapsedmillis = 11 four times a second consistently. Have it running now, comparing time to my laptop clock, see if they stay in sync together.

Hmm, PC clock not good enough - I get the impression that it drifts a little also, as the two of them don't seem to update once a second together, the display lag between them drifts.

I’m running your code above Robert and it seems to be running almost 2 secs slow after 3 minutes… :-[

I’m running more tests now.

@Warren Reeve: Give this a try...

unsigned long currentmillis = 0;
unsigned long previousmillis = 0;
unsigned long interval = 10;
unsigned long elapsedmillis = 0;

byte latchpin = 2; // connect to pin 12 on the 74HC595
byte clockpin = 3; // connect to pin 11 on the 74HC595
byte datapin = 4; // connect to pin 14 on the 74HC595
byte testpin5 = 5;

byte ones_seconds = 0;
byte tens_seconds = 0;
byte ones_minutes = 0;
byte tens_minutes = 0;
byte tenths = 0;
byte hundredths= 0;


int segdisp[10] = {
  63,6,91,79,102,109,125,7,127,111 }; //segment references using 74HC595 Shift Registers
//The above numbers light up different segments of a digit

void setup()
{
  pinMode(latchpin, OUTPUT);
  pinMode(clockpin, OUTPUT);
  pinMode(datapin, OUTPUT);
  pinMode(testpin5, OUTPUT);
  Serial.begin(57600);
}

void loop()
{
  currentmillis = millis();  // read the time.
  elapsedmillis = currentmillis - previousmillis;

  while (elapsedmillis >= interval) // 10 milliseconds have gone by
  {
    hundredths = hundredths +1;

    if (hundredths == 10){
      hundredths = 0;
      tenths = tenths +1;
    }

    if (tenths == 10){
      tenths = 0;
      ones_seconds = ones_seconds +1;
      Serial.print ( tens_minutes,DEC);  // sending minutes/seconds to the screen
      Serial.print (ones_minutes,DEC);
      Serial.print (tens_seconds,DEC);
      Serial.println(ones_seconds,DEC);
    }

    if (ones_seconds == 10){
      ones_seconds = 0;
      tens_seconds = tens_seconds +1;
    }

    if (tens_seconds == 6){
      tens_seconds = 0;
      ones_minutes = ones_minutes +1;
    }

    if (ones_minutes == 10){
      ones_minutes = 0;
      tens_minutes = tens_minutes +1;
    }
    if (tens_minutes == 6){
      tens_minutes = 0;
    }
    previousmillis  = previousmillis + interval;  // save the time for the next comparison
  }

  // digitalWrite (testpin5, HIGH); // used to see how long the if's were taking
  // counters are all updated now, just do the shiftout one time here:
  digitalWrite(latchpin, LOW); // send the digits down to the shift registers!
  shiftOut(datapin, clockpin, MSBFIRST, segdisp[hundredths]); // print the % first "hundredths" digit
  shiftOut(datapin, clockpin, MSBFIRST, segdisp[tenths]); // print the tens of hundredths digit
  shiftOut(datapin, clockpin, MSBFIRST, segdisp[ones_seconds]); // print the % first "seconds" digit
  shiftOut(datapin, clockpin, MSBFIRST, segdisp[tens_seconds]); // print the tens of seconds digit
  shiftOut(datapin, clockpin, MSBFIRST, segdisp[ones_minutes]); // print the % first "minute" digit
  shiftOut(datapin, clockpin, MSBFIRST, segdisp[tens_minutes]); // print the tens of minutes digit
  digitalWrite(latchpin, HIGH);

} // end void loop

Will try it now Codey (thank you).

After more test Robert that was loosing 5 secs after 12 mins..

Hi Codey, it wont start?? I changed all my latch pin numbers etc to match mine but it is just showing 00:00:00?? :-/

Code I am using;

unsigned long currentmillis = 0;
unsigned long previousmillis = 0;
unsigned long interval = 10;
unsigned long elapsedmillis = 0;

byte latchpin = 8; // connect to pin 12 on the 74HC595
byte clockpin = 12; // connect to pin 11 on the 74HC595
byte datapin = 11; // connect to pin 14 on the 74HC595


byte ones_seconds = 0;
byte tens_seconds = 0;
byte ones_minutes = 0;
byte tens_minutes = 0;
byte tenths = 0;
byte hundredths= 0;


int segdisp[10] = {
  63,6,91,79,102,109,125,7,127,111 }; //segment references using 74HC595 Shift Registers
//The above numbers light up different segments of a digit

void setup()
{
  pinMode(latchpin, OUTPUT);
  pinMode(clockpin, OUTPUT);
  pinMode(datapin, OUTPUT);


}

void loop()
{
  currentmillis = millis();  // read the time.
  elapsedmillis = currentmillis - previousmillis;

  while (elapsedmillis >= interval) // 10 milliseconds have gone by
  {
    hundredths = hundredths +1;

    if (hundredths == 10){
      hundredths = 0;
      tenths = tenths +1;
    }

    if (tenths == 10){
      tenths = 0;
      ones_seconds = ones_seconds +1;
      
    }

    if (ones_seconds == 10){
      ones_seconds = 0;
      tens_seconds = tens_seconds +1;
    }

    if (tens_seconds == 6){
      tens_seconds = 0;
      ones_minutes = ones_minutes +1;
    }

    if (ones_minutes == 10){
      ones_minutes = 0;
      tens_minutes = tens_minutes +1;
    }
    if (tens_minutes == 6){
      tens_minutes = 0;
    }
    previousmillis  = previousmillis + interval;  // save the time for the next comparison
  }

  // counters are all updated now, just do the shiftout one time here:
  digitalWrite(latchpin, LOW); // send the digits down to the shift registers!
  shiftOut(datapin, clockpin, MSBFIRST, segdisp[hundredths]); // print the % first "hundredths" digit
  shiftOut(datapin, clockpin, MSBFIRST, segdisp[tenths]); // print the tens of hundredths digit
  shiftOut(datapin, clockpin, MSBFIRST, segdisp[ones_seconds]); // print the % first "seconds" digit
  shiftOut(datapin, clockpin, MSBFIRST, segdisp[tens_seconds]); // print the tens of seconds digit
  shiftOut(datapin, clockpin, MSBFIRST, segdisp[ones_minutes]); // print the % first "minute" digit
  shiftOut(datapin, clockpin, MSBFIRST, segdisp[tens_minutes]); // print the tens of minutes digit
  digitalWrite(latchpin, HIGH);

} // end void loop

Sorry about that. Give this one a try...

unsigned long currentmillis = 0;
unsigned long previousmillis = 0;
unsigned long interval = 10;

byte latchpin = 8; // connect to pin 12 on the 74HC595
byte clockpin = 12; // connect to pin 11 on the 74HC595
byte datapin = 11; // connect to pin 14 on the 74HC595


byte ones_seconds = 0;
byte tens_seconds = 0;
byte ones_minutes = 0;
byte tens_minutes = 0;
byte tenths = 0;
byte hundredths= 0;


int segdisp[10] = {
  63,6,91,79,102,109,125,7,127,111 }; //segment references using 74HC595 Shift Registers
//The above numbers light up different segments of a digit

void setup()
{
  pinMode(latchpin, OUTPUT);
  pinMode(clockpin, OUTPUT);
  pinMode(datapin, OUTPUT);


}

void loop()
{
  currentmillis = millis();  // read the time.

  while (currentmillis - previousmillis >= interval) // 10 milliseconds have gone by
  {
    hundredths = hundredths +1;

    if (hundredths == 10){
      hundredths = 0;
      tenths = tenths +1;
    }

    if (tenths == 10){
      tenths = 0;
      ones_seconds = ones_seconds +1;

    }

    if (ones_seconds == 10){
      ones_seconds = 0;
      tens_seconds = tens_seconds +1;
    }

    if (tens_seconds == 6){
      tens_seconds = 0;
      ones_minutes = ones_minutes +1;
    }

    if (ones_minutes == 10){
      ones_minutes = 0;
      tens_minutes = tens_minutes +1;
    }
    if (tens_minutes == 6){
      tens_minutes = 0;
    }
    previousmillis  = previousmillis + interval;  // save the time for the next comparison
  }

  // counters are all updated now, just do the shiftout one time here:
  digitalWrite(latchpin, LOW); // send the digits down to the shift registers!
  shiftOut(datapin, clockpin, MSBFIRST, segdisp[hundredths]); // print the % first "hundredths" digit
  shiftOut(datapin, clockpin, MSBFIRST, segdisp[tenths]); // print the tens of hundredths digit
  shiftOut(datapin, clockpin, MSBFIRST, segdisp[ones_seconds]); // print the % first "seconds" digit
  shiftOut(datapin, clockpin, MSBFIRST, segdisp[tens_seconds]); // print the tens of seconds digit
  shiftOut(datapin, clockpin, MSBFIRST, segdisp[ones_minutes]); // print the % first "minute" digit
  shiftOut(datapin, clockpin, MSBFIRST, segdisp[tens_minutes]); // print the tens of minutes digit
  digitalWrite(latchpin, HIGH);

} // end void loop

Sorry about that. Give this one a try...

Lol.. no worries. Ok, that 1 is running.. I will report back in 10 mins or so and see what it's like.. :)

Hi Codey, After 17 minutes it is just over 3 seconds slow..??

After 25mins it reads = 4.66 secs slow?? Approx

There are two possibilities left…

  1. Whatever you are using for comparison is not accurate. What are you using? Have you tried something else?

  2. The board you are using has a resonator or oscillator instead of a crystal. What board are you using?

Hi Codey, yes I have tried that.. I was originally timing it from my mobile phone but after all the controversy I though it would be a good idea to double/treble check how accurate it was. I checked my mobile phone against my PC and it was accurate to it and then I checked the both of them against a hand held stopwatch/lap timer.. all 3 ran the same speed. My arduino is approx 4 weeks old and is an Arduino Uno.

Hope that helps. :-/

I believe that the Uno has a resonator and... (4.66 / (25 * 60)) * 100 = 0.31 % ...is about the typical accuracy for a resonator.

But, you should have someone else confirm what I'm saying.

I also suggest you try to get a few other Uno users to confirm what you're seeing. The shiftOut calls can be replaced with Serial.print calls.

 if (ones_seconds == 10){
      ones_seconds = 0;
      [glow]hundredths = hundredths +7;[/glow]   // Speed up the clock!
        tens_seconds = tens_seconds +1;
    }

Would this be acceptable as a fix? (shown previously) Basically, if the Uno is out a little would it not be ok to give it a little back each loop? I don't want to bad code or anything like that but if the internal time is not accurate I don't see much choice in this situation. Also please keep in mind that I am a complete novice with all this. :P

PS. Time difference after 1 hour = 11 seconds. :-[

Would this be acceptable as a fix? (shown previously)

Only you can decide. If what you are trying to build is "for entertainment purposes" then I can't imagine a little tweak being a problem. If money or pride is involved, you may end up involved in some heated arguments (or fights).

Basically, if the Uno is out a little would it not be ok to give it a little back each loop?

Certainly. But you should first confirm that your Arduino really does have a resonator instead of a crystal.

Yes, I agree.. lap times can become a very heated conversation at times.. I would certainly not like to be the guy who made the racer go slower...!!! >:( haha.. then you would see some fast laps as I left the building!! Lol.

But you should first confirm that your Arduino really does have a resonator instead of a crystal.

If anyone reading this can shed any light on this.. please do otherwise I will try and get an answer from Arduino or someone else as soon as I can. Thanx again to Robert and Codey for all your time and help. Really appreciated. :)

I suspect you'll get a quick response if you...

  • Take a well focused low-resolution picture of the board focusing on the area near the processor
  • Post the picture in the Hardware / Troubleshooting forum
  • Politely ask for someone to identify the clock as either a crystal or a resonator

This has certainly been a perplexing one Warren. Robert

Warren, I've adjusted it to use micros() instead millis() (ignore the names) and have it printing the time on screen once a second. I downloaded a clock that CNET had a link to, to have something to watch that the PC updated once a second. The screen update seems to update with no discernible change in rate, while the PC clock seems to catch up every once on a while - yet the two times are still in agreement after 37 minutes. Has not gained or lost any time. I am wondering what I have that has more accurate time - maybe my Garmin Nuvi GPS? Have to see if the battery is charged and compare to that.

Have you decided if you have crystal, such as pictured here next to the USB connector, or a resonator, which may look like the 3-lead blue part here or this yellow part

unsigned long currentmillis = 0;
unsigned long previousmillis = 0;
unsigned long interval = 10000;
unsigned long elapsedmillis = 0;

byte latchpin = 2; // connect to pin 12 on the 74HC595
byte clockpin = 3; // connect to pin 11 on the 74HC595
byte datapin = 4; // connect to pin 14 on the 74HC595
byte testpin5 = 5;

byte ones_seconds = 0;
byte tens_seconds = 0;
byte ones_minutes = 0;
byte tens_minutes = 0;
byte tenths = 0;
byte hundredths= 0;


int segdisp[10] = {
  63,6,91,79,102,109,125,7,127,111 }; //segment references using 74HC595 Shift Registers
//The above numbers light up different segments of a digit

byte time_update = 0;// added new flag
void setup()
{
  pinMode(latchpin, OUTPUT);
  pinMode(clockpin, OUTPUT);
  pinMode(datapin, OUTPUT);
  pinMode(testpin5, OUTPUT);
  Serial.begin(57600);
}

void loop()
{
  currentmillis = micros();  // read the time.
  elapsedmillis = currentmillis - previousmillis;

  if (elapsedmillis >= interval) // 10 milliseconds have gone by
  {
    previousmillis  = previousmillis + elapsedmillis;  // save the time for the next comparison
    time_update = 1;
   // if (elapsedmillis>10000){  
   //   Serial.println (ones_seconds,DEC);
   //   Serial.println (elapsedmillis,DEC);  I notice this prints out 10004 a lot, with an occasional 10008
   //}
  
  } 
  

  if (time_update == 1){  // no updating if not at 10ms interval, skip this whole section
    // increment the counters, roll as needed, shift the digits out

    time_update = 0; // reset for next pass thru

    hundredths = hundredths +1;

    if (hundredths == 10){
      hundredths = 0;
      tenths = tenths +1;
    }

    if (tenths == 10){
      tenths = 0;
      ones_seconds = ones_seconds +1;
      Serial.print ( tens_minutes,DEC);
      Serial.print (ones_minutes,DEC);
      Serial.print (tens_seconds,DEC);
      Serial.println(ones_seconds,DEC);
    }

    if (ones_seconds == 10){
      ones_seconds = 0;
      tens_seconds = tens_seconds +1;
    }

    if (tens_seconds == 6){
      tens_seconds = 0;
      ones_minutes = ones_minutes +1;
    }

    if (ones_minutes == 10){
      ones_minutes = 0;
      tens_minutes = tens_minutes +1;
    }
    if (tens_minutes == 6){
      tens_minutes = 0;
    }
    // counters are all updated now, just do the shiftout one time here:
    digitalWrite(latchpin, LOW); // send the digits down to the shift registers!
    shiftOut(datapin, clockpin, MSBFIRST, segdisp[hundredths]); // print the % first "hundredths" digit
    shiftOut(datapin, clockpin, MSBFIRST, segdisp[tenths]); // print the tens of hundredths digit
    shiftOut(datapin, clockpin, MSBFIRST, segdisp[ones_seconds]); // print the % first "seconds" digit
    shiftOut(datapin, clockpin, MSBFIRST, segdisp[tens_seconds]); // print the tens of seconds digit
    shiftOut(datapin, clockpin, MSBFIRST, segdisp[ones_minutes]); // print the % first "minute" digit
    shiftOut(datapin, clockpin, MSBFIRST, segdisp[tens_minutes]); // print the tens of minutes digit
    digitalWrite(latchpin, HIGH);

  } // end if time to be updated

} // end void loop

Okay, am running compared to official us gov't time! http://www.time.gov/timezone.cgi?Eastern/d/-5/java Lets see how that matches up.

Well, its been 2 hrs, 25 minutes, and my duemilanova seems to have gained about a second on the gov't time. Will let it continue to run overnight & see what happens. Got a feeling tho that my laptop will go into sleep mode or something, and reset the serial interface and lose track of where it is.