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

I am basically doing what the example you linked to does.

Think of it this way, quasi coded: void loop { read start/stop button if (start/stop indicates time is running) { currenttime= millis(); // read the time if (currenttime -previoustime >=100) // 0.1seconds, make this 10 for 0.01 seconds { previoustime = currenttime //store it then update all your digits, and roll them over as needed hundreths = hundreths+1; if hundredths = 10, set hundredths to 0 and increment tenths; if tenths = 10, set 10ths to and increment seconds if seconds = 10, set seconds to 0 and increments tens_of_seconds if tens_of_seconds = 6, set tens_of_seconds to 0 and increment minutes if minutes = 10, set minutes to 0 and increment tens_of_minutes if tens_of_minutes = 6, set tens_of_minutes to 0. } // check if the lap time display button is pushed - if it is, do not update the displays // if not, shift out the updated time /*Then shiftout the 6 bytes for each digit out to your display. You have the 595 driving the segments directly? Then you'll habe to do some mapping also. 0 = segments a,b,c,d,e,f on 1 = segmens b,con 2 =segments a,b,d,e,g on 3 = segments a,d,e,f,g on 4 = segments f,g,b,c on etc. */ }// and repeat!

Hi Crossroads, thanks again for the speedy reply although I have to say as much as I understand what the code is 'saying/doing' I don't know how to use it or what with? :'( I am learning lessons everyday but this is too much and with it being pieces I don't know how to use them. I really do apologise for being new-comer pain in the butt and I know your looking at the code and thinking... "Why can't he see it!!!". What I will do is search a bit more to find a sample and then if you don't mind I can ask you to look at how I can adapt it further for my project. I think I need to learn allot more before bothering you or anyone else on the forum.

Many thanks for your help so far and I will be in touch after Xmas sometime.

PS. Happy Xmas to you and yours! :)

No problem Warren. I think the idea is straightforward. You have six digits, representing Tens of Minutes, Minutes, Tens of Seconds, Seconds, Tenths of Seconds, Hundreths of Seconds.

These digits can be, in the order above, 0-5, 0-9, 0-5, 0-9, 0-9, 0-9. 00:00.00 to 59:59.99 See if you can get those working first, just counting up from 0. So make a loop that reads the time from millis(), and whenever 0.01 (10 milliseconds) goes by, update the lowest digit. When that digit goes out of range, from 9 to 10 say for Hundreths of seconds, reset it to 0 and increment the next digit up. Or even simpler to start - just a void loop with a delay(1000) at the end, get all your digits working updating ~1 second at a time, then reduce the delay to speed it up. Whenever a digit changes, shift out the new value to the shift register/display (I assume you are planning all digits chained together to reduce pin usage?) When you can get all the digits increment properly, then start adding stuff like reading push buttons, holding the display off, etc. Eventually replace delay with reading the millis() for more accuracy.

I'll draw up a quick schematic with an idea of how to wire this up, and with a display idea. Robert

So I imagine you have something like this going already, with more digits in the chain and some buttons to start/sotp time, etc. This shift register is nice because it can handle higher voltages for the bigger display in your future. tpic6b595 open drain shift register

HI Robert, Wow.. thank you again so much for your help. this time I return with some good news!! I was reading a section of your text that for some reason inspired me to do my research in a different way?? :P ::):P. the following piece;

0-5, 0-9, 0-5, 0-9, 0-9, 0-9. 00:00.00 to 59:59.99 See if you can get those working first, just counting up from 0.

Long story short, I now have 4 numbers counting. the 2 rightmost are counting to 99 and the next right counts to 9 and to 5 for the next right. This is a small insert of the code I used;

if( f == 10) {
     f = 0;
     g = int(f);
  
     h++;
    i = int(h);
 } 
if( h == 6) {
     h = 0;
i = int(h);
}

I'm sure you know what I mean. :) So my next plan is to add the other 2 digits tonight n get them wired up and then add more of the same code above to include them on the counter. I have added a 'Blink' to pin 13 and temporarily have it connected to a decimal point. After that I will need to add a button to start and stop and another to start/pause/restart new lap. I will try and get some pics up soon. Not sure how much I will get done over the next few days tho with Xmas. Thanks again and I will update you soon, Warren

Just out of curiosity, I am running the count speed like this;

int speed = 9; // used to control speed of counting

This controls the speed of the 100ths which increment the other numbers. Is there a more accurate way to do this? Cheers Warren

Awesome Warren! Sounds like you are making good progress. Please write in when you have more done :-)

Now it's your turn to educate me a little:

I'm a digital hardware engineer, not really a programmer, so my code can look rather bumbly at times and I have some difficulty following the C shortcuts. I am getting better at keeping my ()s & {}s straightened out as I go.

So, I'm interested in what you have going on.

What are you doing with these parts? You don't seem to use g & i:

g = int(f); i = int(h);

Do you have f & h declared as type byte? Why do g & i need to be type int?

h++; would seem to increment h from your following if statement. Yet the arduino reference sections shows:

x++; // increment x by one and returns the old value of x ++x; // increment x by one and returns the new value of x

so it doesn't seem to me that h would be changed by h++;. Maybe if used like this: z=h++; then z would be equal to h+1. I could see ++h changing it. That seems to be the same as h=h+1; (I like to see what really happens so when I'm up too late debugging it sticks out more - I think the compiler makes them come out the same in the end.)

But that h++ is working for you?

"speed = 9" You are using this as delay(speed)?

What you want to do is wrap your whole counting & updating inside a loop that lets it increment based on the millis() time, this is the # of milliseconds that have gone by since your sketch started. unsigned long is 32 bits, so it will take millis() something like 49 days to count from 0 to 2^32-1 before going back to 0 (and even when it does, 0x0000 0005 - 0xFFFF FFFE will still yield the correct result: 7.

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

something like this, within your void loop(){

currentmillis = millis(); // read the time. if (currentmillis - previousmillis >= interval) // 10 milliseconds have gone by { previousmillis = currentmillis; // save the time for the next comparison hundredths = hundreths +1; if (hundredths = 10){ hundredths = 0; tenths = tenths +1;} } etc, like you have now

} // end void loop

If you want it run slower so you can see the .01s & 0.1s incrementing properly, just make interval bigger until you are satisfied.

Robert

Hi Robert, sorry it's been a couple of nights without an update.. we've had a power cut, my computer got a virus and wouldn't load the internet!! then my battery in the van failed and on top of all that the code I thought worked.. didn't really. :( I had it changing when.. for example, it reached 5 in the tens of seconds but that just added a minute at 50 seconds instead of 59/60.. anyway, I worked on that for ages and have now finally came up with a counter that goes up 99 hundredths and then adds 1 second as it shows "00".. the seconds now count to 59 before adding "1" minute as they also show "00" and start re-counting. Same with the minutes, they go up to 59 before showing "00". :) Really, really chuffed with how it works but I'm not sure how to implement the millis() time thing??

What you want to do is wrap your whole counting & updating inside a loop that lets it increment based on the millis() time

I just don't know what to take out and where to put each piece of your code? I did try messing with it the other day but didn't get anywhere, I even tried looking for other examples but without luck.

What are you doing with these parts? You don't seem to use g & i:

g = int(f); i = int(h);

G & I are the last 2 digits.. see full code at the bottom. :)

h++; would seem to increment h from your following if statement. Yet the arduino reference sections shows:

x++; // increment x by one and returns the old value of x ++x; // increment x by one and returns the new value of x

so it doesn't seem to me that h would be changed by h++;. Maybe if used like this: z=h++; then z would be equal to h+1. I could see ++h changing it. That seems to be the same as h=h+1; (I like to see what really happens so when I'm up too late debugging it sticks out more - I think the compiler makes them come out the same in the end.)

But that h++ is working for you?

.. again, I don't really know what most of it means?? What I do know is that everything is relevant to "z". My "z" I have counting to 101. I then take '%10' and '/10' for the hundredths of seconds which in turn increment everything else. So if I need anything to be accurate it would be the "z" in my code. Any help would be great on how to do this.

Here is my "59:59:99" counter full incrementing code; (which is not accurate to time.)

int latchpin = 8; // connect to pin 12 on the 74HC595
int clockpin = 12; // connect to pin 11 on the 74HC595
int datapin = 11; // connect to pin 14 on the 74HC595
float b = 0;
int c = 0;
float d = 0;
int e = 0;
float f = 0;
int g = 0;
float h = 0;
int i = 0;
float j = 0;
int k = 0;
float l = 0;
int m = 0;


int seconds;
int minutes;
int speed = 10; // used to control speed of counting
int segdisp[10] = {
63,6,91,79,102,109,125,7,127,111 }; //segment references using 74HC595 Shift Registers


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



  
}
void loop()
 {  
// Counts up to 59 only!
for (int z=0; z<101; z++)

{
digitalWrite(latchpin, LOW);

shiftOut(datapin, clockpin, MSBFIRST, 0); // clears the left display
shiftOut(datapin, clockpin, MSBFIRST, 0); // clears the left display
shiftOut(datapin, clockpin, MSBFIRST, 0); // clears the left display
shiftOut(datapin, clockpin, MSBFIRST, 0); // clears the left display
shiftOut(datapin, clockpin, MSBFIRST, 0); // clears the left display
shiftOut(datapin, clockpin, MSBFIRST, 0); // clears the left display
digitalWrite(latchpin, HIGH);
if (z<1)
{
digitalWrite(latchpin, LOW);
shiftOut(datapin, clockpin, MSBFIRST, segdisp[z]); // sends the digit down the serial path
shiftOut(datapin, clockpin, MSBFIRST, 0); // sends a blank down the serial path to push the digit to the right
shiftOut(datapin, clockpin, MSBFIRST, 0); // sends a blank down the serial path to push the digit to the right
shiftOut(datapin, clockpin, MSBFIRST, 0); // sends a blank down the serial path to push the digit to the right
digitalWrite(latchpin, HIGH);
}
else if (z>=1)
//------------------------------ Hundredths below
{
d=z%10; // find the remainder of dividing z by 10, this will be the right-hand digit
c=int(d); // make it an integer, c is the right hand digit

b=z/10; // divide z by 10 - the whole number value will be the left-hand digit
e = int(b); // e is the left hand digit
//------------------------------ Ten of Seconds (60) below

if( z == 100) {
     c=0; // clear the hundredths digit
     e=0; // clear the hundredths digit
     z=0; // reset the timer
     seconds++; // add 1 second to "seconds"
      f=seconds%10; // float the %
      g=int (f); // print the % first "seconds" digit

h=seconds/10; // divid the seconds by 10 to get the tens of seconds
i = int (h); // print the tens of seconds digit
}

//------------------------------ Minutes (60) below

if( seconds == 60) {
     g=0; // clear the "seconds" digit
     i=0; // clear the "tens" of seconds digit
    
 seconds=0; // reset the seconds
 minutes++; // add 1 minute to "minutes"
      j=minutes%10; // float the %
      k=int (j); // print the % first "minute" digit

l=minutes/10; // divid the minutes by 10 to get the tens of minutes
m = int (l); // print the tens of minutes digit

} 
//------------------------------ 

if( minutes == 60) {
     k=0; // clear the "minutes" digit
     m=0; // clear the "tens" of minutes digit
   minutes=0; // reset the minutes
} 


digitalWrite(latchpin, LOW); // send the digits down to the shift registers!
shiftOut(datapin, clockpin, MSBFIRST, segdisp[c]); // print the % first "hundredths" digit
shiftOut(datapin, clockpin, MSBFIRST, segdisp[e]); // print the tens of hundredths digit
shiftOut(datapin, clockpin, MSBFIRST, segdisp[g]); // print the % first "seconds" digit
shiftOut(datapin, clockpin, MSBFIRST, segdisp[i]); // print the tens of seconds digit
shiftOut(datapin, clockpin, MSBFIRST, segdisp[k]); // print the % first "minute" digit
shiftOut(datapin, clockpin, MSBFIRST, segdisp[m]); // print the tens of minutes digit
digitalWrite(latchpin, HIGH);


  }


delay(speed);
}}

Hope it all makes sense.. I've tried my best to label it as much as I can. Regards Warren

Hi Warren, I saw that post and all the math, then we went out & I forgot about it until just now.

Anyway, To use millis, what you want to do is increment z here for (int z=0; z<101; z++)

only when your lowest time increment has occurred. Thus

if (time_running == 1) // because you've told it to based on a button push or something
  {
    unsigned long currentMillis = millis();  // see how long its been

    if (currentMillis - previousMillis >= interval) // reached 10mS interval?
    {
      // save the last time we okayed time updates 
      previousMillis = currentMillis; 
     count_update_flag = 1;}

and roll your increments thru from there. I was thinking more along these lines instead of all the math: AB:CD.EF Start at the top, you've reached the time interval:

if (count_update_flag == 1){
count_update_flag = 0; // reset for next pass thru
if (time == 59:59.99) {reset all to 0, set time_update flag to 1}
// which is really: if (A==5 && B==9 && C==5 && D==9 && E==9 && F==9)
if (A<5 and rest == 9:59.99){increment A, reset the lower digits, set time_update flag to 1}
if (B<9 and rest == 59.99){increment B, reset the lower digits, set time_update flag to 1}
if (C<5 and rest == 9.99){increment C, reset the lower digits, set time_update flag to 1}
if (D<9 and rest == 99){increment D, reset the lower digits, set time_update flag to 1}
if (E<5 and F==9){increment E, reset F, set time_update flag to 1}
if (F<9){all that's remaing, eh? increment F, set time_update flag to 1}
}// end of counting update

if (time_update == 1){
time_upate = 0; // reset for next pass thru
shift out the digits that were updated above}
} // end of  interval check

then you can get away from all the floats and converting to ints & stuff. You've got (0.01S/62.5nS) = 160,000 clock cycles for the 5-6 comparisons and the resets and the 6 shiftouts, which all be done well before the next 10mS comparison is due.

Hi Robert, I'm stuck on the time/millis. I still can't get the timer to count accurately and I know I haven't put the code in right?? I have tried numerous ways and looked at other codes but can't figure out what I'm doing wrong. Here's what I have;

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

int latchpin = 8; // connect to pin 12 on the 74HC595
int clockpin = 12; // connect to pin 11 on the 74HC595
int datapin = 11; // connect to pin 14 on the 74HC595
float b = 0;
int c = 0;
float d = 0;
int e = 0;
float f = 0;
int g = 0;
float h = 0;
int i = 0;
float j = 0;
int k = 0;
float l = 0;
int m = 0;
int hundredths1;

int seconds;
int minutes;
int hundredths;

int segdisp[10] = {
63,6,91,79,102,109,125,7,127,111 }; //segment references using 74HC595 Shift Registers


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



}
void loop()
  {
   currentmillis = millis();  // read the time.
if (currentmillis - previousmillis >= interval) // 10 milliseconds have gone by
{ previousmillis  = currentmillis;  // save the time for the next comparison
hundredths = hundredths +1;

}


{

  // Counts up to 101 only!
for (int hundredths=0; hundredths<101; hundredths++)


{
digitalWrite(latchpin, LOW);

shiftOut(datapin, clockpin, MSBFIRST, 0); // clears the left display
shiftOut(datapin, clockpin, MSBFIRST, 0); // clears the left display
shiftOut(datapin, clockpin, MSBFIRST, 0); // clears the left display
shiftOut(datapin, clockpin, MSBFIRST, 0); // clears the left display
shiftOut(datapin, clockpin, MSBFIRST, 0); // clears the left display
shiftOut(datapin, clockpin, MSBFIRST, 0); // clears the left display
digitalWrite(latchpin, HIGH);
if (hundredths<1)
{
digitalWrite(latchpin, LOW);
shiftOut(datapin, clockpin, MSBFIRST, segdisp[hundredths]); // sends the digit down the serial path
shiftOut(datapin, clockpin, MSBFIRST, 0); // sends a blank down the serial path to push the digit to the right
shiftOut(datapin, clockpin, MSBFIRST, 0); // sends a blank down the serial path to push the digit to the right
shiftOut(datapin, clockpin, MSBFIRST, 0); // sends a blank down the serial path to push the digit to the right
digitalWrite(latchpin, HIGH);
}
else if (hundredths>=1)
//------------------------------ Hundredths below
{
d=hundredths%10; // find the remainder of dividing hundredths by 10, this will be the right-hand digit
c=int(d); // make it an integer, c is the right hand digit

b=hundredths/10; // divide hundredths by 10 - the whole number value will be the left-hand digit
e = int(b); // e is the left hand digit
//------------------------------ Ten of Seconds (60) below

if( hundredths == 100) {
     c=0; // clear the hundredths digit
     e=0; // clear the hundredths digit
     hundredths=0; // reset the timer
     seconds++; // add 1 second to "seconds"
      f=seconds%10; // float the %
      g=int (f); // print the % first "seconds" digit

h=seconds/10; // divid the seconds by 10 to get the tens of seconds
i = int (h); // print the tens of seconds digit
}

//------------------------------ Minutes (60) below

if( seconds == 60) {
     g=0; // clear the "seconds" digit
     i=0; // clear the "tens" of seconds digit
    
 seconds=0; // reset the seconds
 minutes++; // add 1 minute to "minutes"
      j=minutes%10; // float the %
      k=int (j); // print the % first "minute" digit

l=minutes/10; // divid the minutes by 10 to get the tens of minutes
m = int (l); // print the tens of minutes digit

} 
//------------------------------ 

if( minutes == 60) {
     k=0; // clear the "minutes" digit
     m=0; // clear the "tens" of minutes digit
   minutes=0; // reset the minutes
} 


digitalWrite(latchpin, LOW); // send the digits down to the shift registers!
shiftOut(datapin, clockpin, MSBFIRST, segdisp[c]); // print the % first "hundredths" digit
shiftOut(datapin, clockpin, MSBFIRST, segdisp[e]); // print the tens of hundredths digit
shiftOut(datapin, clockpin, MSBFIRST, segdisp[g]); // print the % first "seconds" digit
shiftOut(datapin, clockpin, MSBFIRST, segdisp[i]); // print the tens of seconds digit
shiftOut(datapin, clockpin, MSBFIRST, segdisp[k]); // print the % first "minute" digit
shiftOut(datapin, clockpin, MSBFIRST, segdisp[m]); // print the tens of minutes digit
digitalWrite(latchpin, HIGH);


}
delay(10);
}}}

Can you see what is wrong?? I just want to get it counting accurately before adding buttons etc. It's roughly 2 seconds per minute out. Cheers Warren

I tweaked it a little, try this. You had a couple of } in the wrong place, think it was messing the logic up a little, thats why I think you had 4 at the end. Next edit, use the Tools:Autoformat key, it can help you spot things like that, while the compiler may not necessarily complain. You are shifting out 3 times, that may be slowing things down a little as well. Try taking the first 2 sets out.

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

int latchpin = 8; // connect to pin 12 on the 74HC595
int clockpin = 12; // connect to pin 11 on the 74HC595
int datapin = 11; // connect to pin 14 on the 74HC595
float b = 0;
int c = 0;
float d = 0;
int e = 0;
float f = 0;
int g = 0;
float h = 0;
int i = 0;
float j = 0;
int k = 0;
float l = 0;
int m = 0;
int hundredths1;
int seconds;
int minutes;
int hundredths;

[glow]int segdisp[10] = {
  63,6,91,79,102,109,125,7,127,111 }; //segment references using 74HC595 Shift Registers
// not really sure what this is, I did not mess with it[/glow]

[glow]int time_update = 0;// added new flag[/glow]
void setup()
{
  pinMode(latchpin, OUTPUT);
  pinMode(clockpin, OUTPUT);
  pinMode(datapin, OUTPUT);
}

void loop()
{
  currentmillis = millis();  // read the time.
  if (currentmillis - previousmillis >= interval) // 10 milliseconds have gone by
  { 
    previousmillis  = currentmillis;  // save the time for the next comparison
    hundredths = hundredths +1;
    [glow][glow]time_update = 1;[/glow]  }  // set flag to upate & shift out[/glow]

[glow]  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[/glow]
      digitalWrite(latchpin, LOW);

[glow]// why do this? I would think it would just make the display look flickery, 
// going between 0 & a real number each update. Maybe put a copy of this in void setup() to clear the displays to start the program[/glow]
      shiftOut(datapin, clockpin, MSBFIRST, 0); // clears the left display
      shiftOut(datapin, clockpin, MSBFIRST, 0); // clears the left display
      shiftOut(datapin, clockpin, MSBFIRST, 0); // clears the left display
      shiftOut(datapin, clockpin, MSBFIRST, 0); // clears the left display
      shiftOut(datapin, clockpin, MSBFIRST, 0); // clears the left display
      shiftOut(datapin, clockpin, MSBFIRST, 0); // clears the left display
      digitalWrite(latchpin, HIGH);
      if (hundredths<1)
      {
        digitalWrite(latchpin, LOW);

[glow]// why do this again? I would think it would just make the display look flickery, 
// going between 0 & a real number each update[/glow]

        shiftOut(datapin, clockpin, MSBFIRST, segdisp[hundredths]); // sends the digit down the serial path
        shiftOut(datapin, clockpin, MSBFIRST, 0); // sends a blank down the serial path to push the digit to the right
        shiftOut(datapin, clockpin, MSBFIRST, 0); // sends a blank down the serial path to push the digit to the right
        shiftOut(datapin, clockpin, MSBFIRST, 0); // sends a blank down the serial path to push the digit to the right
        digitalWrite(latchpin, HIGH);
      }
      else if (hundredths>=1)
        //------------------------------ Hundredths below
      {
        d=hundredths%10; // find the remainder of dividing hundredths by 10, this will be the right-hand digit
        c=int(d); // make it an integer, c is the right hand digit

        b=hundredths/10; // divide hundredths by 10 - the whole number value will be the left-hand digit
        e = int(b); // e is the left hand digit
      }
        //------------------------------ Ten of Seconds (60) below

        if( hundredths == 100) {
          c=0; // clear the hundredths digit
          e=0; // clear the hundredths digit
          hundredths=0; // reset the timer
          seconds++; // add 1 second to "seconds"
          f=seconds%10; // float the %
          g=int (f); // print the % first "seconds" digit

          h=seconds/10; // divide the seconds by 10 to get the tens of seconds
          i = int (h); // print the tens of seconds digit
        }

        //------------------------------ Minutes (60) below

        if( seconds == 60) {
          g=0; // clear the "seconds" digit
          i=0; // clear the "tens" of seconds digit

          seconds=0; // reset the seconds
          minutes++; // add 1 minute to "minutes"
          j=minutes%10; // float the %
          k=int (j); // print the % first "minute" digit

          l=minutes/10; // divid the minutes by 10 to get the tens of minutes
          m = int (l); // print the tens of minutes digit

        }
        //------------------------------

        if( minutes == 60) {
          k=0; // clear the "minutes" digit
          m=0; // clear the "tens" of minutes digit
          minutes=0; // reset the minutes
        }
[glow]// counters are all updated now, just do the shiftout one time here:[/glow]
        digitalWrite(latchpin, LOW); // send the digits down to the shift registers!
        shiftOut(datapin, clockpin, MSBFIRST, segdisp[c]); // print the % first "hundredths" digit
        shiftOut(datapin, clockpin, MSBFIRST, segdisp[e]); // print the tens of hundredths digit
        shiftOut(datapin, clockpin, MSBFIRST, segdisp[g]); // print the % first "seconds" digit
        shiftOut(datapin, clockpin, MSBFIRST, segdisp[i]); // print the tens of seconds digit
        shiftOut(datapin, clockpin, MSBFIRST, segdisp[k]); // print the % first "minute" digit
        shiftOut(datapin, clockpin, MSBFIRST, segdisp[m]); // print the tens of minutes digit
        digitalWrite(latchpin, HIGH);

  } // end if time to be updated

} // end void loop

Hi Robert… your a star!! I have it all working and took out alot of that code that wasn’t needed. It is now running almost accurately… I have highlighted in the code if( hundredths == 100) because I can make the time go faster or slower by entering 99 or 100. 99 is too fast and 100 is too slow?? How can this be edited?
After 11mins 30secs it’s almost 5 seconds slow.

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

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

int c = 0;
int e = 0;
int g = 0;
int i = 0;
int k = 0;
int m = 0;

int seconds;
int minutes;
int hundredths;

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

int time_update = 0;// added new flag
void setup()
{
  pinMode(latchpin, OUTPUT);
  pinMode(clockpin, OUTPUT);
  pinMode(datapin, OUTPUT);
}

void loop()
{
  currentmillis = millis();  // read the time.
  if (currentmillis - previousmillis >= interval) // 10 milliseconds have gone by
  {
    previousmillis  = currentmillis;  // save the time for the next comparison
    hundredths = hundredths +1;
  
 time_update = 1;  }  // 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 below
      {
        c=hundredths%10; // find the remainder of dividing hundredths by 10, this will be the right-hand digit
        e=hundredths/10; // divide hundredths by 10 - the whole number value will be the left-hand digit
      
      }
        //------------------------------ Ten of Seconds (60) below

        [glow]if( hundredths == 100) [/glow]{
         
          hundredths=0; // reset the timer
          seconds++; // add 1 second to "seconds"
         
            g=seconds%10; // 
          i=seconds/10; // divide the seconds by 10 to get the tens of seconds
         
        }

        //------------------------------ Minutes (60) below

        if( seconds == 60) {
          g=0; // clear the "seconds" digit
          i=0; // clear the "tens" of seconds digit

          seconds=0; // reset the seconds
          minutes++; // add 1 minute to "minutes"
          k=minutes%10; // 
          m=minutes/10; // divid the minutes by 10 to get the tens of minutes
        
        }
        //------------------------------

        if( minutes == 60) {
          k=0; // clear the "minutes" digit
          m=0; // clear the "tens" of minutes digit
          minutes=0; // reset the minutes
        }
// 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[c]); // print the % first "hundredths" digit
        shiftOut(datapin, clockpin, MSBFIRST, segdisp[e]); // print the tens of hundredths digit
        shiftOut(datapin, clockpin, MSBFIRST, segdisp[g]); // print the % first "seconds" digit
        shiftOut(datapin, clockpin, MSBFIRST, segdisp[i]); // print the tens of seconds digit
        shiftOut(datapin, clockpin, MSBFIRST, segdisp[k]); // print the % first "minute" digit
        shiftOut(datapin, clockpin, MSBFIRST, segdisp[m]); // print the tens of minutes digit
        digitalWrite(latchpin, HIGH);

  } // end if time to be updated

} // end void loop

Try simplifying it - maybe the divisions & ints & floats is introducing some roundover type errors?

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

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

int ones_seconds = 0;
int tens_seconds = 0;
int ones_minutes = 0;
int tens_minutes = 0;
int tenths = 0;
int 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

int time_update = 0;// added new flag
void setup()
{
  pinMode(latchpin, OUTPUT);
  pinMode(clockpin, OUTPUT);
  pinMode(datapin, OUTPUT);
}

void loop()
{
  currentmillis = millis();  // read the time.
  if (currentmillis - previousmillis >= interval) // 10 milliseconds have gone by
  {
    previousmillis  = currentmillis;  // save the time for the next comparison

    time_update = 1;  
  }  // 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;
    }

    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

Cheers Robert.. I will try this now. :)


That code works fine.. although after 5 minutes it still looses around 2 seconds??

This is what I have now;

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

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

int ones_seconds = 0;
int tens_seconds = 0;
int ones_minutes = 0;
int tens_minutes = 0;
int tenths = 0;
int 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

int time_update = 0;// added new flag
void setup()
{
  pinMode(latchpin, OUTPUT);
  pinMode(clockpin, OUTPUT);
  pinMode(datapin, OUTPUT);
}

void loop()
{
  currentmillis = millis();  // read the time.
  if (currentmillis - previousmillis >= interval) // 10 milliseconds have gone by
  {
    previousmillis  = currentmillis;  // save the time for the next comparison
  
  
 time_update = 1;  }  // 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;
    }

    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

Is this way supposed to be as in-accurate as this or would I have to fit a RTC clock or something?? As a stopwatch/lap time it is going to need to be accurate for at least 5 minutes for short circuit and road race events.

Hi Robert, Just a quick note to let you know I have applied a fix to the timer. (see code below) I added 7 x 100ths to the 'hundredths' each loop. Now it's almost accurate to an hour.. just got to tweak it a little more. :) Really pleased with the whole thing and can't thank you enough for your help with the code. I am now trying to work with the buttons.. start, stop, lap/pause with background restart.. then resume. Using de-bounce I should be able to work something out?? I will of course keep you updated.

 if (ones_seconds == 10){
      ones_seconds = 0;
      [glow]hundredths = hundredths +7;[/glow]
tens_seconds = tens_seconds +1;
    }

Wow, I didn't think it would lose that much time. I wonder if you will see that change with temperature.

As for debouncing, just add reading of switches in your loop as well. If the state of the button is normally high (say a switch on a pin with internal pullup that gets connected to ground when pressed), then take action on the first read of 0, set a flag, and wait for 5 hundreths or a tenth to elapse before you allow it to be read again.

The other thing to try is replace millis() with micros()

http://arduino.cc/en/Reference/Micros

Change interval to 10000, 10,000uS = 10mS

I added 7 x 100ths to the 'hundredths' each loop. Now it's almost accurate to an hour.. just got to tweak it a little more.

Don't do that! There's a flaw in your Sketch that needs to be fixed. Fixing the flaw will very likely correct the timing error.

Do you want hints so you can try to figure out the problem on your own or do you want a straight-up full description?

I’d like the full-up please, as I have been helping him & I am stumped as to why it would be so inaccurate. I have a 10 minute countdown timer, which I have not timed for accuracy, but works on similar principal (only rolling backwards required a lot more current state checking to decide if the digits should roll or not).