4 Digit Seven Segment Display Countdown Timer - Minutes to

Hey guys, I'm an indie filmmaker designing a "bomb countdown timer" to be a prop in a short film I'm producing.

I've built a timer using the wiring instructions & code here:

The timer is working as it should according to the instructions, but the only problem is it counts down in seconds, not minutes and seconds (e.g."110" instead of "1:50"), which is the norm for the bomb timers on film/tv.

I am totally new to both Arduino and electronics in general and I feel like I have jumped in at the deep end. If anyone could have a look at the code and make any suggestions as to how I might change the output on the display to minutes & seconds instead of just seconds that would be a massive help.

Thanks, (and pre-emptive apologies if I am asking for way more help than a newbie is entitled to)

Scott

Code & Wiring:

/*
 6-13-2011
 Spark Fun Electronics 2011
 Nathan Seidle
 
 This code is public domain but you buy me a beer if you use this and we meet 
 someday (Beerware license).
 
 4 digit 7 segment display:
 http://www.sparkfun.com/products/9483
 Datasheet: 
 http://www.sparkfun.com/datasheets/Components/LED/7-Segment/YSD-439AR6B-35.pdf

 This is an example of how to drive a 7 segment LED display from an ATmega
 without the use of current limiting resistors. This technique is very common 
 but requires some knowledge of electronics - you do run the risk of dumping 
 too much current through the segments and burning out parts of the display. 
 If you use the stock code you should be ok, but be careful editing the 
 brightness values.
 
 This code should work with all colors (red, blue, yellow, green) but the 
 brightness will vary from one color to the next because the forward voltage 
 drop of each color is different. This code was written and calibrated for the 
 red color.

 This code will work with most Arduinos but you may want to re-route some of 
 the pins.

 7 segments
 4 digits
 1 colon
 =
 12 pins required for full control 
 
 */

int digit1 = 11; //PWM Display pin 1
int digit2 = 10; //PWM Display pin 2
int digit3 = 9; //PWM Display pin 6
int digit4 = 6; //PWM Display pin 8

//Pin mapping from Arduino to the ATmega DIP28 if you need it
//http://www.arduino.cc/en/Hacking/PinMapping
int segA = A1; //Display pin 14
int segB = 3; //Display pin 16
int segC = 4; //Display pin 13
int segD = 5; //Display pin 3
int segE = A0; //Display pin 5
int segF = 7; //Display pin 11
int segG = 8; //Display pin 15

void setup() {                
  pinMode(segA, OUTPUT);
  pinMode(segB, OUTPUT);
  pinMode(segC, OUTPUT);
  pinMode(segD, OUTPUT);
  pinMode(segE, OUTPUT);
  pinMode(segF, OUTPUT);
  pinMode(segG, OUTPUT);

  pinMode(digit1, OUTPUT);
  pinMode(digit2, OUTPUT);
  pinMode(digit3, OUTPUT);
  pinMode(digit4, OUTPUT);
  
  pinMode(13, OUTPUT);
}

void loop() {
  
  //long startTime = millis();

  displayNumber(millis()/1000);

  //while( (millis() - startTime) < 2000) {
  //displayNumber(1217);
  //}
  //delay(1000);  
}

//Given a number, we display 10:22
//After running through the 4 numbers, the display is left turned off

//Display brightness
//Each digit is on for a certain amount of microseconds
//Then it is off until we have reached a total of 20ms for the function call
//Let's assume each digit is on for 1000us
//Each digit is on for 1ms, there are 4 digits, so the display is off for 16ms.
//That's a ratio of 1ms to 16ms or 6.25% on time (PWM).
//Let's define a variable called brightness that varies from:
//5000 blindingly bright (15.7mA current draw per digit)
//2000 shockingly bright (11.4mA current draw per digit)
//1000 pretty bright (5.9mA)
//500 normal (3mA)
//200 dim but readable (1.4mA)
//50 dim but readable (0.56mA)
//5 dim but readable (0.31mA)
//1 dim but readable in dark (0.28mA)

void displayNumber(int toDisplay) {
#define DISPLAY_BRIGHTNESS  500

#define DIGIT_ON  HIGH
#define DIGIT_OFF  LOW

  long beginTime = millis();

  for(int digit = 4 ; digit > 0 ; digit--) {

    //Turn on a digit for a short amount of time
    switch(digit) {
    case 1:
      digitalWrite(digit1, DIGIT_ON);
      break;
    case 2:
      digitalWrite(digit2, DIGIT_ON);
      break;
    case 3:
      digitalWrite(digit3, DIGIT_ON);
      break;
    case 4:
      digitalWrite(digit4, DIGIT_ON);
      break;
    }

    //Turn on the right segments for this digit
    lightNumber(toDisplay % 10);
    toDisplay /= 10;

    delayMicroseconds(DISPLAY_BRIGHTNESS); 
    //Display digit for fraction of a second (1us to 5000us, 500 is pretty good)

    //Turn off all segments
    lightNumber(10); 

    //Turn off all digits
    digitalWrite(digit1, DIGIT_OFF);
    digitalWrite(digit2, DIGIT_OFF);
    digitalWrite(digit3, DIGIT_OFF);
    digitalWrite(digit4, DIGIT_OFF);
  }

  while( (millis() - beginTime) < 10) ; 
  //Wait for 20ms to pass before we paint the display again
}

//Given a number, turns on those segments
//If number == 10, then turn off number
void lightNumber(int numberToDisplay) {

#define SEGMENT_ON  LOW
#define SEGMENT_OFF HIGH

  switch (numberToDisplay){

  case 0:
    digitalWrite(segA, SEGMENT_ON);
    digitalWrite(segB, SEGMENT_ON);
    digitalWrite(segC, SEGMENT_ON);
    digitalWrite(segD, SEGMENT_ON);
    digitalWrite(segE, SEGMENT_ON);
    digitalWrite(segF, SEGMENT_ON);
    digitalWrite(segG, SEGMENT_OFF);
    break;

  case 1:
    digitalWrite(segA, SEGMENT_OFF);
    digitalWrite(segB, SEGMENT_ON);
    digitalWrite(segC, SEGMENT_ON);
    digitalWrite(segD, SEGMENT_OFF);
    digitalWrite(segE, SEGMENT_OFF);
    digitalWrite(segF, SEGMENT_OFF);
    digitalWrite(segG, SEGMENT_OFF);
    break;

  case 2:
    digitalWrite(segA, SEGMENT_ON);
    digitalWrite(segB, SEGMENT_ON);
    digitalWrite(segC, SEGMENT_OFF);
    digitalWrite(segD, SEGMENT_ON);
    digitalWrite(segE, SEGMENT_ON);
    digitalWrite(segF, SEGMENT_OFF);
    digitalWrite(segG, SEGMENT_ON);
    break;

  case 3:
    digitalWrite(segA, SEGMENT_ON);
    digitalWrite(segB, SEGMENT_ON);
    digitalWrite(segC, SEGMENT_ON);
    digitalWrite(segD, SEGMENT_ON);
    digitalWrite(segE, SEGMENT_OFF);
    digitalWrite(segF, SEGMENT_OFF);
    digitalWrite(segG, SEGMENT_ON);
    break;

  case 4:
    digitalWrite(segA, SEGMENT_OFF);
    digitalWrite(segB, SEGMENT_ON);
    digitalWrite(segC, SEGMENT_ON);
    digitalWrite(segD, SEGMENT_OFF);
    digitalWrite(segE, SEGMENT_OFF);
    digitalWrite(segF, SEGMENT_ON);
    digitalWrite(segG, SEGMENT_ON);
    break;

  case 5:
    digitalWrite(segA, SEGMENT_ON);
    digitalWrite(segB, SEGMENT_OFF);
    digitalWrite(segC, SEGMENT_ON);
    digitalWrite(segD, SEGMENT_ON);
    digitalWrite(segE, SEGMENT_OFF);
    digitalWrite(segF, SEGMENT_ON);
    digitalWrite(segG, SEGMENT_ON);
    break;

  case 6:
    digitalWrite(segA, SEGMENT_ON);
    digitalWrite(segB, SEGMENT_OFF);
    digitalWrite(segC, SEGMENT_ON);
    digitalWrite(segD, SEGMENT_ON);
    digitalWrite(segE, SEGMENT_ON);
    digitalWrite(segF, SEGMENT_ON);
    digitalWrite(segG, SEGMENT_ON);
    break;

  case 7:
    digitalWrite(segA, SEGMENT_ON);
    digitalWrite(segB, SEGMENT_ON);
    digitalWrite(segC, SEGMENT_ON);
    digitalWrite(segD, SEGMENT_OFF);
    digitalWrite(segE, SEGMENT_OFF);
    digitalWrite(segF, SEGMENT_OFF);
    digitalWrite(segG, SEGMENT_OFF);
    break;

  case 8:
    digitalWrite(segA, SEGMENT_ON);
    digitalWrite(segB, SEGMENT_ON);
    digitalWrite(segC, SEGMENT_ON);
    digitalWrite(segD, SEGMENT_ON);
    digitalWrite(segE, SEGMENT_ON);
    digitalWrite(segF, SEGMENT_ON);
    digitalWrite(segG, SEGMENT_ON);
    break;

  case 9:
    digitalWrite(segA, SEGMENT_ON);
    digitalWrite(segB, SEGMENT_ON);
    digitalWrite(segC, SEGMENT_ON);
    digitalWrite(segD, SEGMENT_ON);
    digitalWrite(segE, SEGMENT_OFF);
    digitalWrite(segF, SEGMENT_ON);
    digitalWrite(segG, SEGMENT_ON);
    break;

  case 10:
    digitalWrite(segA, SEGMENT_OFF);
    digitalWrite(segB, SEGMENT_OFF);
    digitalWrite(segC, SEGMENT_OFF);
    digitalWrite(segD, SEGMENT_OFF);
    digitalWrite(segE, SEGMENT_OFF);
    digitalWrite(segF, SEGMENT_OFF);
    digitalWrite(segG, SEGMENT_OFF);
    break;
  }
}

As a hardware, that's a poorway to run a display.

"This is an example of how to drive a 7 segment LED display from an ATmega
without the use of current limiting resistors. This technique is very common
but requires some knowledge of electronics - you do run the risk of dumping
too much current through the segments and burning out parts of the display.
If you use the stock code you should be ok, but be careful editing the
brightness values."

I would rather see you add current limiting resistors and not damage your arduino.

As for the counting down in minutes/seconds, here is the method I use to determine the digits:

Your start time is defined at the beginning, say 10:00:
byte tens_minutes = 10;
byte ones_minutes = 0;
byte tens_seconds = 0;
byte ones_seconds = 0;

I'll paste in the code I've written for counting down. Basically decrement the ones_seconds by 1, when it hits 0 decrement the tens seconds, when that hits zero decrement the one_minutes, when that hits 0 decrement the tens_minutes.
Add some if statements to rollover the digits back up to 5 or 9 as needed.

Hitting the road, will post that in an hour or so.

I might use the Time library, has variables, functions, etc. that make handling dates and time simple, Arduino Playground - Time

//countdown timer
#include <Time.h>         //http://www.arduino.cc/playground/Code/Time

time_t t;
tmElements_t tm;
int seconds, minutes;

void setup(void)
{
    Serial.begin(115200);

    //initialize the starting time to 3 minutes and 0 seconds.
    //the rest of the elements (hours, etc., don't matter much but should 
    //at least be set to something that makes sense.
    tm.Second = 0;
    tm.Minute = 3;
    tm.Day = 1;
    tm.Month = 4;
    tm.Year = CalendarYrToTm(2012);
    
    t = makeTime(tm);
}

void loop(void)
{
    seconds = second(t);
    minutes = minute(t);
    
    if (minutes < 10) Serial.print('0');    //leading zero
    Serial.print(minutes, DEC);    
    Serial.print(':');
    if (seconds < 10) Serial.print('0');    //leading zero
    Serial.println(seconds, DEC);
    --t;                                    //subtract a second
    if (seconds + minutes == 0) {
        Serial.println("BOOM!");
        while (1);                          //infinite loop, press reset to restart
    }
    delay(100);                             //10x normal speed for demo purposes
}

Here's my time checking & digit update code.
It also flashes some Colon LEDs on/off at 1/4 second intervals so have immediate visual feedback that it's running. Watching 1 second pass with nothing happening is really boring...

void loop()
{
  // check if time needs updating
  if (time_running == 1)  // time is counting down
  {
    unsigned long currentMillis = millis();  // see how long its been

    if (currentMillis - previousMillis >= interval) // more than our quarter second interval?
    {
      // save the last time we okayed time updates 
      previousMillis = currentMillis; 
      quarter_interval = quarter_interval+1;
      // cycle the colon state
      if (colon == 0x80)
      {
        colon = 0x00;
      }
      else
      {
        colon = 0x80;
      }
      update_time = 1;   //  enable time display to be updated

      if (quarter_interval == 4) // we hit the one second update time
      {
        quarter_interval = 0;
        // update the time digits
        // cases: 
        // 0:01, final second - stop time, disable touch lights, sound buzzer
        // Tens of seconds rollover: time = x:50, x:40, x:30, x:20, x:10: decrement tens of seconds, rollover seconds to 9
        // Minutes rollover: time = 9:00, 8:00, etc. 2:00, 1:00: decrement ones of minutes, rollover tens of 
        // seconds to 5, ones of seconds to 9
          // 10:00: Roll all the digits over
        // otherwise: just roll over the seconds

        // Case: Final Second
        if ((minutes_ones == 0) && (seconds_tens == 0) && (seconds_ones == 1)) // don't need minutes_tens, can't have 10:01
        {
          time_running = 0;  // stop time running
          seconds_ones = 0;  // clear the last second
          updated = 1;  // fake a Case complete flag      

          if ((time_running == 1) && (period>0) && (period<9)) { //  update period counter if was fencing time, not 1:00 or 10:00 break
            period = period +1;
            update_period=1;  // enable period display to be updated
          }
        }  // end of  if final second

        // Case: x:50, x:40, x:30, x:20, x:10
        if ((seconds_tens >0) && (seconds_ones == 0))  // case for the last tens of seconds 
        {
          seconds_tens = seconds_tens - 1;  // decrement the tens
          seconds_ones = 9;  // rollover the ones
          updated = 1;
        }  // end of if 10 of seconds rollover

        // Case: 9:00, 8:00, etc 2:00, 1:00
        if ((minutes_ones > 0) && (seconds_tens == 0) && (seconds_ones == 0)) // case for the last ones of minutes
        { 
          minutes_tens = 0x00;  //
          minutes_ones = minutes_ones - 1;  // decrement the minutes
          seconds_tens = 5;  // rollover the tens of seconds;
          seconds_ones = 9;  // rollover the ones of seconds;
          updated = 1;
        } // end of if minutes rollover

        // Case: starting from 10:00
        if (minutes_tens == 0x01)  // roll over all digits
        {
          minutes_tens = 0x00;  // rollover the tens of minutes
          minutes_ones = 9;  // rollover the ones of mints;
          seconds_tens = 5;  // rollover the tens of seconds;
          seconds_ones = 9;  // rollover the ones of seconds; 
          updated = 1;
        } // end of if 10:00 rollover

        // General Case: just decrement the seconds
        if (updated == 0)  // nothing else updated - but don't decrement if = 0.
        {
          seconds_ones = seconds_ones - 1;
        }
        updated = 0;  // reset for next pass thru
      } // end of if quarter_interval
    } // end of reaching our interval
  } // end of if time_running

if (updated == 1){
// update the time display
updated = 0; // reset for next pass
}

Then I have another section that checks if updated == 1 and updates the display.
I use a MAX7221 to control my digits, the sparkfun code does it segment by segment.
This board here uses 4 high current shift registers to drive the segments with no multiplexing. I can sell you a bareboard for $4.50 and you can build it up without the SD card and RS232 parts.

Thanks for the help, I'm still having trouble, CrossRoads are you saying that I won't be able to achieve the minutes & seconds without the board you posted?

Again, sorry for my lack of understanding.

No, you certainly can.
The design you started with I believe works by lighting up one segment of each digit one at a time, cycling thru the 4 digits.
My code gives you the means to count down the time as you requested.

Hi Crossroads

Does your board take the TPIC6B595 shift registers? If so, are you willing to ship one to me? (obviously for the cost and shipping!)

The reason I ask is that I have been tasked with creating a countdown timer for my FIL's train club. They essentially want a 30 min countdown timer for some efficiency runs with a large (>2") digit display. I have been putting things together and came across this post. If it does use the TPIC6B595 it would be an ideal carrier as I will be using 4 of them to run the digits, as they need 9-12v, and it would save me a lot of time with breadboards etc.

I can also crib most of your code :slight_smile: as it seems to be mostly there.

Thanks

Dave

Yes, uses TCIP6B595, nice chip for driving higher voltage digits.
I have to check to see if I have any left.
You need a bare board that you populate yourself? Or a fully populated board?

I would definitely avoid the Sparkfun module, it's a piece of filth.

Filmie, is this the sort of thing you're after? If so, you can have my code under the Beerware licence :wink: Although I think Crossroads is probably doing things in a similar way to me, regarding timekeeping variables etc.

CrossRoads:
Yes, uses TCIP6B595, nice chip for driving higher voltage digits.
I have to check to see if I have any left.
You need a bare board that you populate yourself? Or a fully populated board?

I'd be happy with either - fully populated is one less soldering job but bare is fine as I have the chips already so would just need to buy the discretes.

Thanks

Dave

Ok, I'll see I have any left, or if it's time to order some more.
What's your timeframe?

It's not particularly urgent as they have been after one for some time. It's as much of an intellectual exercise for me as for the finished product.

Dave

Ok. I don't have any left. Will order, have them in 3 weeks.

Oh, you may be in luck! I've ordered more boards, and at the same time tracked down some previously delivered boards that hadn't been built up yet.
Hopefully will have one mailed back to me on Saturday, can send to you Tuesday/Wednesday after it arrives.
You can get parts for it here inexpensively:
16 MHz xtal, two 22pf caps
7805
two 10uf caps for power filter
eight 0.1uF caps for decoupling
'328P if you need one
5mm screw terminals
10k reset resistor
current limit resistors for LEDs
Header pins for programming -
ICSP if needed,
FTDI if needed,
Header pins & 2 jumpers to select FTDI interface if needed
None needed if you program off board and put the 328 in a socket.
Pain in the ass for debugging - preferable to at least put a bootloaded part in a socket, then use FTDI Basic, or FTDI cable, or CP2102 module with adapter cale for downloading sketches on to the board.

Can leave off the SD socket, 3.3V regulator & 2 caps, 3.3V-5V signal buffer & decoupling cap.
Can leave off MAX232 & 4 caps (for +/-10V generation) & DB9 connector.

There are 6 pins labelled Remote - you have +5, Gnd, and 4 input pins there. Can use internal pullups, and NO switches to Gnd for buttons to start your timer, etc. Will send a schematic with the board.

I'm guessing I can program the 328 on my current board (has a socket'ed 328) and just put in to your board for testing? OK, a bit of messing about but it still makes for a neat solution.

Sounds good to me.

Once you confirm I'll get a list of parts ordered ready for when it arrives (the shift registers should be here today or tomorrow). Admittedly, a populated board would be simpler but happy to have a proper board (as was going to use breadboard for final solution).

Thanks

Dave

Preprogramming is one way to go.
I find it a lot easier to plug one of these on, download, and pull it off again.
No chance to damage pins that way.

I made up a little pcb that I use for 7 seg displays, it is stand alone ( program the 328 on your arduino, then plug it in the board)
I have put some 10 pin idc headers on it, 4 for the first 4 digits ( as in a clock ), and one on the right of the board to carry on to more numbers if needed ( each digit has a TPIC6B595 high power latch driver that can drive massive digits )
The headers have 7 pins for segments a-g, and 3 pins for the LED supply.

There is another header on the left for gen purpose I/O to some of the pins of the micro. I use these for connecting to wireless / push buttons/ GPS / whatever.

There is also provision for a couple of power fets for switching other LEDs, horn , motor etc.

The board has its own 5v regulator, I generally supply 12v ( depending on the number of LEDs in series for each segment )

I can post the gerber files if anyone wants to make these, or I could perhaps supply the boards if anyone is interested.

I have a a simple sketch for the countdown bomb, with a couple of push buttons to preset the start time, and a run/pause button.

Sorry Crossroads,

I didnt see the pic of your one, its a lot more versatile than my simple one ! I will probably buy some boards from you next time ( I have just ordered another load of mine )

Looks good Boffin. I was going to have separate boards (arduino plus driver board) but it looks like you both have good single board options whihc is much neater.

I'd love a copy of the countdown sketch as that is exactly what I am looking to do (will save me many hours of programming\head-scratching XD ).

Dave

Heres a v22 sketch for the " Bollywood Bomb " that I have scratched up from another project of mine. I havn't tested this version, I dont have time to connect up the switches and display at the moment, but it should basically work, but if you try it we can debug any problems.

You could swap the pin numbers to work on Crossroads allsinging serial board.

For some reason it won't compile without the VirtualWire library , so I left it in.

Connect four pushbuttons to negative for the run pause plus and minus setting buttons.

It drives 4 x TPIC6B595 serial register/drivers using shiftout, I have made comments about which pins go to which LED segments.
the " spare" output of the TPIC for minutes units connects to the two dots between the mins and secs, which stays on while counting down, and flashes when paused ( you could swap it round if you ant the opposite effect.)
I have put in a " bombPin " output that you could drive an LED to light for 2 seconds ( or a sounderwhatever ) when countdown reaches zero.

// Boffin1's  countdown " bomb " timer with preset up down run and pause
//   connect dots  to spare TPIC output on minute units chip, on when counting down, flash when paused
#include <VirtualWire.h>
#define latchPin 19  // rck
#define clockPin 18  // sck
#define dataPin 16   // ser in

int tile [4];
//  bitmap for which leds segements ( TPIC pins ) are lit for numbers 0 - 9, first bit for dots
// this pattern will depend on how the segments are wired up
//       this pattern is for  sequence   =   dots,  e,  d,  c,  g,  b,  f,  a
const byte digitTable [10] = { 
  B01110111, B00010100, B01101101, B00111101, B00011110, B00111011, B01111011, B00010101, B01111111,B00111111 } 
;   

const byte blanked = B00000000; 
int dotState;
int pause = HIGH;
int blank = HIGH;
int mintens = 0;
int minunits = 0;
int sectens = 0;
int secunits = 0;
int timeleft = 0;              
unsigned long previousdotMillis = 0;  
unsigned long previousMillis = 0;     
int mintendisp; 
int minunitsdisp;
int sectensdisp;
int secunitsdisp;  
int plusPin = 4;
int minusPin = 5;
int runPin = 6;
int pausePin = 7;
int running;
int bombPin = 8;

//******************************************************        
void setup()
{
  Serial.begin(9600);	
  blank == HIGH;
  Serial.println("setup");
  pinMode ( latchPin, OUTPUT);
  pinMode ( clockPin, OUTPUT);
  pinMode ( dataPin, OUTPUT); 
  pinMode ( plusPin, INPUT); 
  digitalWrite(plusPin, HIGH); // set pullups
  pinMode ( minusPin, INPUT); 
  digitalWrite(minusPin, HIGH);
  pinMode ( runPin, INPUT); 
  digitalWrite (runPin, HIGH);
  pinMode ( pausePin, INPUT); 
  digitalWrite(pausePin, HIGH);

  digitalWrite(latchPin, LOW);      // blanking all displays
  for ( int k=0; k<=3; k++ ){
    shiftOut(dataPin, clockPin, LSBFIRST, blank); 
    delay (5);
  }
  digitalWrite(latchPin, HIGH);  
  pinMode ( bombPin, INPUT); 
  digitalWrite(bombPin, LOW);
}
//********************************************************************
void loop () 
{  

  checktime();

  if ( mintens + minunits + sectens + secunits  >= 1 ){ 
    timeleft = HIGH;
  }    // check again after countdown
  else 
  { 
    timeleft = LOW ; 
    pause = HIGH;   
  }     //  flashing dots
  unsigned long currentdotMillis = millis();
  if(currentdotMillis - previousdotMillis > 500) {
    previousdotMillis = currentdotMillis;    
    if (dotState == LOW)
    {
      dotState = HIGH;
    }    
    else     { 
      dotState = LOW;
    }  
    showtime ();
  }
  if ( pause == LOW ) { 
    dotState = HIGH ;
  }

  

  checkbutton ();    


}//  end of loop


void checktime () {
  if ( mintens + minunits + sectens + secunits  >= 1 )  //  if time still left on countdown
  { 
    timeleft = HIGH;
  } 
  else { 
    timeleft = LOW ; 
    pause = HIGH; 
  }

  if (timeleft == HIGH ) {
    if ( pause == LOW ) {  //  which means its counting down   i.e. not paused in countdown          
      static unsigned long previousMillis;
      if(millis() > previousMillis)
      { 
        previousMillis = millis() + 1000; 
        secunits -- ;             // countdown 1 sec 
        if ( secunits  < 0 ){ 
          secunits = 9;  
          sectens -- ;
        }
        if ( sectens   < 0 ){ 
          sectens = 5;  
          minunits -- ;
        }
        if ( minunits  < 0 ){ 
          minunits = 9;  
          mintens -- ;
        } 
        // mintens cant get to -1 or it would have to have been 0000 and paused
        Serial.print(mintens);  
        Serial.print(minunits);  
        Serial.print(" : "); 
        Serial.print(sectens);  
        Serial.println(secunits); 
        showtime ();

        if ( mintens + minunits + sectens + secunits  >= 1 ){ 
          timeleft = HIGH;
        } 
        else { 
          digitalWrite( bombPin, HIGH ) ; 
          timeleft = LOW ; 
          pause = HIGH ;
                // milliseconds bombPin goes high
          delay ( 2000 ); 
        } 
        digitalWrite( bombPin, LOW );

      } 
      dotState = HIGH; 
    } // keeps dots on while countdown 
    else 
      if ( blank == LOW ) {
      flashdots ();
    }

  }
} // END OF CHECKTIME

void checkbutton ()
{   
  int plus = digitalRead( plusPin );
  if ( plus == LOW ) {     
    secunits ++;  
  }  

  if ( secunits > 9 ){       
    secunits = 0 ;       
    sectens ++;    
  } 
  if ( sectens >5 ) {      
    sectens = 0;      
    minunits ++;    
  }
  if ( minunits > 9 ){      
    minunits=0;       
    mintens ++;    
  }
  if ( mintens >5 ){       
    mintens = 0 ;    
  }   

  int minus = digitalRead( minusPin );
  if ( minus == LOW ) {  
    secunits --; 
  }

  if ( secunits  < 0 ){       
    secunits = 9;        
    sectens -- ;    
  }
  if ( sectens   < 0 ){       
    sectens = 5;       
    minunits -- ;    
  }
  if ( minunits  < 0 ){       
    minunits = 9;        
    mintens -- ;    
  }  
  if ( mintens < 0 ){        
    mintens =5 ;     
  }

  //  CHANGE THIS DELAY TO SET COUNTSPEED WHEN + or - BUTTON HELD IN
  if ( plus || minus == LOW ){  
    delay ( 100 ) ;     
    showtime ();      
  }  


  // when run button pressed release pause
  int runbutton = digitalRead( runPin );
  if ( runbutton == LOW ) { 
    pause = LOW ; 
  } 


  // when pause button pressed  set pause
  int pausebutton  = digitalRead( pausePin );  
  if ( pausebutton == LOW ) { 
    pause = HIGH ; 
  } 



}  // end of checkbutton function 

void flashdots () { 
  unsigned long currentdotMillis = millis();
  if(currentdotMillis - previousdotMillis > 500) {
    previousdotMillis = currentdotMillis;    
    if (dotState == LOW)
    {
      dotState = HIGH;
    }
    else  { 
      dotState = LOW;
    }     
    showtime ();  
  }
  if ( pause == LOW ) { 
    dotState = HIGH ;
  }  
} //  end of flashdots routins 

void showtime ()   //  DISPLAY ROUTINE 
{   
  int mintendisp = (mintens) ? digitTable [ mintens ] : 0;  //  zero blanking tens minutes
  int minunitsdisp = digitTable [ minunits ];
  int sectensdisp = digitTable [ sectens ];
  int secunitsdisp = digitTable [ secunits ];
  if ( dotState == HIGH ){

    minunitsdisp = minunitsdisp|10000000 ; 
  }      //   adds msb to minunit to light dots when dotState high

  digitalWrite(latchPin, LOW); 

  shiftOut(dataPin, clockPin, LSBFIRST, mintendisp);
  shiftOut(dataPin, clockPin, LSBFIRST, minunitsdisp);
  shiftOut(dataPin, clockPin, LSBFIRST, sectensdisp); 
  shiftOut(dataPin, clockPin, LSBFIRST, secunitsdisp);

  digitalWrite(latchPin, HIGH);
}