Go Down

Topic: Stopwatch with Pause/Lap  6 digit 7 seg LED. HELP! (Read 186938 times) previous topic - next topic

warrenreeve

#75
Jan 02, 2011, 12:41 am Last Edit: Jan 02, 2011, 12:54 am by warrenreeve Reason: 1
Lovely.. that's done it!!  ;D Great.. thank you again.
The only thing now is that.. say, after 35 when I pause the time for the 5000 (5 secs) when the time comes back it shows 40 secs and continues to count whereas I wanted the time to restart.

Also, this pause feature pauses for a pre-defined time.. is there not a way of pausing for a 'said' amount of time and returning only after a button press?


EDIT:
***ALMOST MIDNIGHT HERE ROBERT.. IM GOING FOR SOME ZZZzzz's.. CATCH UP TOMORROW***  :)

CrossRoads

Good morning!

No problem, you can make the button do whatever you want, or add more buttons.
> Start/Stop
> Pause display, keep time running.
> Start new lap time, keep overall time running

Can also add some more code to store the laptimes after each pause, when all done press a button to cycle thru & display them.
etc.

For this request, just reset the individual counters to 0 when you press the pause button:

byte tens_hours = 0;  // not sure if you are using this
byte ones_hours = 0; // not sure if you are using this
byte tens_minutes = 0;
byte ones_minutes = 0;
byte tens_seconds = 0;
byte ones_seconds = 0;
byte tenths = 0;
byte hundredths = 0;

Add some more code to change the paused state:
if (paused ==1){  // sitting in paused state now
pause_button_state = digitalRead (pause_button);
if (pause_button_state == 0){
paused = 0;}  // back to  unpaused
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

warrenreeve

Hi Robert,
I have been looking at the code for a couple of hours now and switching things up down back and forward without success.
It's great that I can set the interval to make it reset and it is great that it returns to a true time instead of my 'delay' approach but i can't seem to get it to pause on a button and then return when I hit the button again.. it just returns after the set interval of 5000 (5 secs).
I've tried to do something with it but in reality I am not experienced enough with code and especially where these little fella's "} & {" go, as it can freeze a programme if they're in the wrong place..  :o
Anyway, what I need is to 'pause' with a button and return at any random time with the same button and have that time added to the initial pause time. Same as now only the user would chose the interval via the button.
I tried various idea's but it didn't seem to pay any attention until the interval had passed. Do you have any idea's on this?
Sorry to be a pain Robert.. once I get this part sorted it should be really easy to get a start and stop worked out and then I can move on to the larger digits etc.  :)

warrenreeve

Hi Robert, well I think my eyes are about to go square reading this screen.. lol  ;D.
Anyway, I have been reading up on a simple on off switch/button and it doesn't seem as simple as it sounds.  :-/
I can connect a wire and a light comes on and when I disconnect it goes out.. that is really simple.. but if I want to use a push button which basically switches on/off then it does the same as above.
I am thinking the best way around this 'button' thing is a button like the top of a pen.. when I press it, it would stay in until I released it again??? 8-)
I'm not sure if this is the correct approach but it's the only thing I can think off at the minute. Would this be the best way to achieve my goal?? I don't want to be governed by the interval amount. :question

CrossRoads

Please define better what you want to do.
We were set up to pause the display and keep the main time running, then you said you wanted it to reset the main time to 0, now you want to pause & unpause & keep something running, I am not sure at this point what the functions are you want to do.
So, come up with a clean list, with the behavior of time for each button defined.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

CrossRoads

Try this.  I didn't run it, my arduino is currently all set up as a fencing scoring machine while I work out the layout I want to build up.
You can leave out the first hightlighted section, that's my test method to see that its counting.
The second highlighted section should manually unpause the display after it is paused, give you that pen-click kind of action.
You can add similar code to start/stop counting - I would put at the top of the void loop, don't start counting until the start/stop button is pushed; then check if time is running, and if the button is pushed a 2nd time counting stops.
Maybe use the pause button to clear the display if time is stopped, or add a third button read for that.


Code: [Select]

   if (paused == 0){
     // not paused, update the display

     // 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);
[glow]      if (tenths == 0 && hundredths == 0){
       Serial.print (tens_hours, DEC);
       Serial.print (ones_hours, DEC);      
       Serial.print (":");
       Serial.print ( tens_minutes, DEC);
       Serial.print (ones_minutes, DEC);
       Serial.print (":");
       Serial.print (tens_seconds, DEC);
       Serial.print(ones_seconds, DEC);
       Serial.print (".");
       Serial.print (tenths, DEC);
       Serial.println (hundredths, DEC);[/glow]      }
     // after the shifouts,  read the pause button, set a flag if pressed, capture the time it was pressed
     pause_button_state = digitalRead(pause_button);
     if (pause_button_state == 0){
       paused = 1;
       Serial.println ("paused");
       start_pausetime =  millis();
     }
   }
[glow]    if (paused ==1){  // sitting in paused state now
     pause_button_state = digitalRead (pause_button);
     if (pause_button_state == 0){
       paused = 0;// back to unpaused
       Serial.println ("unpaused");
     }  
   }[/glow]

 } // end if time to be updated

} // end void loop

Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

warrenreeve

Quote
Please define better what you want to do.

I am so sorry Robert.. I thought I had always made it clear that it needed to pause showing the lap while resetting in the background. I apologise if I gave the wrong impression.  :-[ I understand how frustrating it must be trying to help some one with such a complex subject.

Quote
I am not sure at this point what the functions are you want to do.
So, come up with a clean list, with the behavior of time for each button defined.

1. Switch the unit on/ numbers at 00:00:00.
2. Race starts/ timer starts using 'LAP' button.
3. Competitor approaches at the end of lap 1. I press the 'LAP' button at a set point on the track/circuit approx 5 to 10 seconds before he/she reaches our point. During which time the lap is frozen for the competitor to read as they approach/pass. Meanwhile in the background the lap time for the second lap has been zeroed and restarted.
4. Press the 'LAP' button again to resume with lap 2 showing on the display.
5. Do it all again for the next passing.

The new code does not do anything at all, not even pause??
Hope this helps.

CrossRoads

Warren,
Almost there. Pause, unpause seems to be working now. I have a crappy button apparently, need to limit presses to no quicker than 1/2 second apart.
Can't for the life of me figure out how to reset the time to 0:00.
I clearly have all the counter set to 0 when pause is recognized, yet it still keeps the time going.
Robert

Code: [Select]
unsigned long currentmicros = 0;
unsigned long previousmicros = 0;
unsigned long interval = 10000;
unsigned long elapsedmicros = 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 hundredths= 0;
byte tenths = 0;
byte ones_seconds = 0;
byte tens_seconds = 0;
byte ones_minutes = 0;
byte tens_minutes = 0;
byte ones_hours = 0;
byte tens_hours = 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 pause_button_state = 0;
byte pause_button = 6;
byte paused = 0;
byte started = 0;
unsigned long start_pausetime = 0;   // start_pausetime, end_pausetime used for button debounce
unsigned long end_pausetime = 0;
unsigned long elapsed_pausetime = 0;

byte time_update = 0;// added new flag
void setup()
{
 pinMode(latchpin, OUTPUT);
 pinMode(clockpin, OUTPUT);
 pinMode(datapin, OUTPUT);
 pinMode(pause_button, INPUT);
 digitalWrite (pause_button, HIGH); // enable pullup
 Serial.begin(57600);
 Serial.println ("Waiting to Start");
}

void loop()
{

 // If not started, read the pause button, set started flag once pressed
 pause_button_state = digitalRead (pause_button);
 if (pause_button_state == 0 & started == 0){
   Serial.println ("Started!");
   started = 1;
   start_pausetime = millis(); // start_pausetime, end_pausetime used for button debounce
 }

 // when started flag is pressed, start counting in 10mS increments  
 if (started == 1){
   currentmicros = micros();  // read the time.
   elapsedmicros = currentmicros - previousmicros;

   if (elapsedmicros >= interval) // 10 milliseconds have gone by
   {
     previousmicros  = previousmicros + elapsedmicros;  // save the time for the next comparison
     time_update = 1; // set flag to shift out the new time
   }

   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;
       ones_hours = ones_hours +1;  // not used in actual application, only here for stability test over longer time periods
     }
     if (ones_hours == 13){  // not used in actual application, only here for stability test over longer time periods
       ones_hours = 0;
       tens_hours = tens_hours +1;
     }
     if (paused == 0){
       // not paused, update the display

       // 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 hundredths digit
       shiftOut(datapin, clockpin, MSBFIRST, segdisp[tenths]);     // print the tenths digit
       shiftOut(datapin, clockpin, MSBFIRST, segdisp[ones_seconds]); // print the lower seconds digit
       shiftOut(datapin, clockpin, MSBFIRST, segdisp[tens_seconds]); // print the upper seconds digit
       shiftOut(datapin, clockpin, MSBFIRST, segdisp[ones_minutes]); // print the lower sinutes digit
       shiftOut(datapin, clockpin, MSBFIRST, segdisp[tens_minutes]); // print the upper minutes digit
       digitalWrite(latchpin, HIGH);
       if (tenths == 0 && hundredths == 0){ // update on screen once a second
         Serial.print ("Elapsed time: ");
         Serial.print (tens_hours, DEC);
         Serial.print (ones_hours, DEC);      
         Serial.print (":");
         Serial.print ( tens_minutes, DEC);
         Serial.print (ones_minutes, DEC);
         Serial.print (":");
         Serial.print (tens_seconds, DEC);
         Serial.print(ones_seconds, DEC);
         Serial.print (".");
         Serial.print (tenths, DEC);
         Serial.println (hundredths, DEC);
       }  // end of 1 second check
     } // end of time update is not paused
   }  // end if time to be updated

   // read the pause button, set a flag if pressed, capture the time it was pressed, reset the lap time
   end_pausetime = millis();
   if (paused == 0 & (end_pausetime - start_pausetime > 500)){  // not paused, debounced if had been (long time used due to crappy button)
     pause_button_state = digitalRead(pause_button);
     if (pause_button_state == 0){
       paused = 1;
       Serial.println ("paused");
       start_pausetime =  end_pausetime;

       currentmicros = micros();  // read the time.
       previousmicros = currentmicros;
       elapsedmicros = currentmicros - previousmicros;
       Serial.println("time should be reset to 00:00:00.00 now");
       Serial.print("currentmicros ");
       Serial.println (currentmicros,DEC);
       Serial.print ("previousmicros ");
       Serial.println (previousmicros,DEC);
       Serial.print ("elapsedmicros ");
       Serial.println (elapsedmicros,DEC);

       byte hundredths= 0;
       byte tenths = 0;
       byte ones_seconds = 0;
       byte tens_seconds = 0;
       byte ones_minutes = 0;
       byte tens_minutes = 0;
       byte ones_hours = 0;
       byte tens_hours = 0;
       Serial.print ("counters are set to: ");
       Serial.print (tens_hours, DEC);
       Serial.print (ones_hours, DEC);      
       Serial.print (":");
       Serial.print ( tens_minutes, DEC);
       Serial.print (ones_minutes, DEC);
       Serial.print (":");
       Serial.print (tens_seconds, DEC);
       Serial.print(ones_seconds, DEC);
       Serial.print (".");
       Serial.print (tenths, DEC);
       Serial.println (hundredths, DEC);
     }
   }

   // read the pause button; unpause to let time display be shown
   end_pausetime = millis();
   if (paused ==1 & (end_pausetime - start_pausetime >500)){  // sitting in paused state now, is debounced
     pause_button_state = digitalRead (pause_button);
     if (pause_button_state == 0){
       paused = 0;// back to unpaused
       start_pausetime = end_pausetime;
       Serial.println ("unpaused");
     }  
   }

 }  // end of if-started
} // end void loop

Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

CrossRoads

#83
Jan 05, 2011, 07:02 am Last Edit: Jan 05, 2011, 07:03 am by CrossRoads Reason: 1
Warren - got it!
In this section, remove the extra 'byte' declaration; they were already declared as 'byte' type in the pre-setup code.  I had just copied it in without thinking.
I think it does what you were after now, try it (the previous post, with the extra 'bytes' removed) and let me know.  You can take out all the serial.print's I had thrown in trying to find out why time wasn't getting cleared.

Robert

Code: [Select]

   end_pausetime = millis();
   if (paused == 0 & (end_pausetime - start_pausetime > 500)){  // not paused, debounced if had been (long time used due to crappy button)
     pause_button_state = digitalRead(pause_button);
     if (pause_button_state == 0){
       paused = 1;
       Serial.println ("paused");
       start_pausetime =  end_pausetime;

       currentmicros = micros();  // read the time.
       previousmicros = currentmicros;
       elapsedmicros = currentmicros - previousmicros;
       Serial.println("time should be reset to 00:00:00.00 now");
       Serial.print("currentmicros ");
       Serial.println (currentmicros,DEC);
       Serial.print ("previousmicros ");
       Serial.println (previousmicros,DEC);
       Serial.print ("elapsedmicros ");
       Serial.println (elapsedmicros,DEC);

       [glow]byte[/glow] hundredths= 0;
       [glow]byte[/glow] tenths = 0;
       [glow]byte[/glow] ones_seconds = 0;
       [glow]byte[/glow] tens_seconds = 0;
       [glow]byte[/glow] ones_minutes = 0;
       [glow]byte[/glow] tens_minutes = 0;
       [glow]byte[/glow] ones_hours = 0;
       [glow]byte[/glow] tens_hours = 0;
       Serial.print ("counters are set to: ");
       Serial.print (tens_hours, DEC);
       Serial.print (ones_hours, DEC);
       Serial.print (":");
       Serial.print ( tens_minutes, DEC);
       Serial.print (ones_minutes, DEC);
       Serial.print (":");
       Serial.print (tens_seconds, DEC);
       Serial.print(ones_seconds, DEC);
       Serial.print (".");
       Serial.print (tenths, DEC);
       Serial.println (hundredths, DEC);
     }
   }

Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

warrenreeve

[smiley=tekst-toppie.gif] Absolutely perfect!!! Huge thumbs up to you Robert! Thank you again for your help and expertise.

Re: My other post.  :-[
Robert I hope I did not offend you by posting it up again. I am taking this idea of the large stopwatch to a business advisor tomorrow and hoping to go forward with funding in the coming months. I love to learn and love being taught but I hate to be a burden to anyone (or a pain in the butt! ::)). I thought that maybe I had overstayed my welcome and should move on and I know how some people could just sit there and let others do the hard.. maybe I am too sensitive  :-/??  it's just that I have never been a user and would hate to think someone thought that.

On a plus side like I said above it seems to be working perfectly! I absolutely love it..  ;D
I think I just need to add a 'reset' button and it's ready for the big display numbers.

Would my set up be able to run these digits from SparFun?;

http://proto-pic.co.uk/products/7%252dSegment-Red-6.5%22-Display.html
I wouldn't be sure if these can be run through the 595 shifters I'm using (think I read that somewhere??).

CrossRoads

Not a problem Warren, we all get a little busy with too many things going on at times.

Now that you see how easy it us to read a button, let me know how you make out with reading a reset button & clearing the digits.

If you are using the tpic6b595 open drain shift register we discussed in this very thread(!), then yes. This LED display requires 12V. If you mean some more generic 74hc595 type shift register, then no. They are only good for 5V, maybe 6V.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

warrenreeve

Ah.. in that case I shall have to get some tpic6b595 type ordered.
I have been researching loads of things and I thought I saw a comment somewhere that the 74hc595 wouldn't do.

I've been busy with other things tonight but will have a go at a reset button later, I think I will be ok and I'll post up the results.
:)

warrenreeve

Hi Robert, I've just been thinking about your last post and that the large LED's will need 12v :-?.. how am I going to power those?? Will I be able to make the system rechargeable or will it need an external power source? Keep in mind I will be running 6 off them.
Cheers
Warren

CrossRoads

I don't know, I don't recall you saying what you had in mind for power.
The LEDs take 12v, but still just 20-30mA per segment. So for the #8, 7 segments on, say 200mA for a nice round number. 6 digits, all showing 8 at the same time, 1200mA. Say another 100 for the arduino and shift registers.
How long do you need to run for? 4 hrs? 8 hrs? Take the worse-case current draw and multiply by the hours that you want to run for, and give yourself a little margin.
You could certainly make it rechargeable.  

Then there are different ways to get the higher voltage.  Generally I would recommend a
switching boost regulator like this, or a european equivalent:
http://www.pololu.com/catalog/product/799
Then you could make up whatever battery pack/charger combination you wanted for the price point you are after, have one of these to put out 12V and a 2nd to put out 5V for the arduino & shift registers.
Or maybe use a small motorcycle battery that is 12V to start after recharging, with a stepdown regulator for the 5V.
The battery has to go in the sign that someone will be picking up & down like a soccer/football sign when they change players (saw that at World Cup games)? Then maybe smaller LiPO batteries would be better.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

David_Rudla

Hi all, it could be used also ULN 2804 behind 595...

Go Up