Multi-setting countdown timer - Newbie help needed

Morning all:

First of all, I’m a total newbie to arduino and to this level of programming. I’ve done some PLC ladder logic stuff before but I’m having issues comprehending this language. I’ve done or gone through most to the examples so I do understand the basics.

Project purpose:
I want to make a multi-input countdown timer (4x7 segment). Each input will have a time associated with it. When you press a button for that input, the timer sets itself to that pre-specified value and starts counting down to zero. I would like to allow any of the timer inputs to interrupt the current count at any timer.

In the end, what I’m trying to do is make a lap timer for a mountain bike course. You will press the appropriate button for the appropriate track that you are on and it will start counting down you last know best lap time (which for now you have to input by updating the program). This way I will have a reference to push myself harder to finish the course faster than the last time I rode it.

The code:
This is the base code for my seven segment display (i like it because of the PWM feature for segment brightness). I’ve attempted to interrupt the count with the inputs but although it seems to do something it does not do what i want it to do.

//THIS PROGRAM ALLOWS YOU TO PUSH A BUTTON TO START A PRE-DETERMINED COUNTDOWN TIMER.
//YOU CAN PROGRAM UP TO 6 INPUT TIMES.

int digit1 = 11; //PWM Display pin 12
int digit2 = 10; //PWM Display pin 9
int digit3 = 9; //PWM Display pin 8
int digit4 = 6; //PWM Display pin 6
int segA = A1; //Display pin 11
int segB = 3; //Display pin 7
int segC = 4; //Display pin 4
int segD = 5; //Display pin 2
int segE = A0; //Display pin 1
int segF = 7; //Display pin 10
int segG = 8; //Display pin 5

const int lap1 = 0; //Add name of lap or course
const int lap2 = 1; //Add name of lap or course
const int lap3 = 12; //Add name of lap or course
const int lap4 = 13; //Add name of lap or course
const int lap5 = A2; //Add name of lap or course
const int lap6 = A3; //Add name of lap or course

int start_num = 100;  // Number to countdown from

unsigned long time;

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(lap1, INPUT);
  pinMode(lap2, INPUT);
  pinMode(lap3, INPUT);
  pinMode(lap4, INPUT);
  pinMode(lap5, INPUT);
  pinMode(lap6, INPUT);

}

void loop()
{
  if (digitalRead(lap4) == HIGH) {
   int (start_num = 10); 
   time=millis()/1000;
   displayNumber(start_num -((millis()/1000))); 
  
//  if((millis()/1000) < start_num){
//    displayNumber(start_num -(millis()/1000));
  }  
//}
  else {
    // reached zero, flash the display
    time=millis();
    while(millis() < time+200) {
      displayNumber(0);  // display 0 for 0.2 second
    }
    time=millis();    
    while(millis() < time+200) {
      lightNumber(10);  // Turn display off for 0.2 second
     }
  }  
}

void displayNumber(int toDisplay) {
#define DISPLAY_BRIGHTNESS  100
#define DIGIT_ON  LOW
#define DIGIT_OFF  HIGH

  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  HIGH
#define SEGMENT_OFF LOW

  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;
  }
}

Sounds like a great project!

For the moment, I would recommend delaying the development of the 7-seg display code, not to further polish your code on display. Instead, just do a print out on serial port. Developing this display code only complicates things. Focus on the buttons logic instead. Sparkfun has serial 7-seg displays so you can simply replace your serial monitor with one of those.

Right now, you are not understanding “button push”. A button push is not a HIGH status, instead, it is a transition from LOW to HIGH. You need a variable to store status of button. Next time you read it, compare with the stored status. If stored is low and now it is high, it’s pressed, then do your thing after button press. Right now you will set and set a clock over and over if you hang on to a button for even one millisecond, which is not right. I’ll see if I can find some tutorials on buttons for you.

If you want to preset lap time, you may use a keypad and then store them on Arduino’s EEPROM. But you are running out of pins. You can worry about this after you get the buttons to work. There’s plenty of solutions.

This logic is NOT right:

int (start_num = 10);
time=millis()/1000;
displayNumber(start_num -((millis()/1000)));

You will get a negative number since start_num is only 10 and millis()/1000 depends on how long your arduino has been powered on. Explain what you intend to do.

Thanks liudr:

At least is sounds like I was originally going the right direction. This was just the latest code I was experimenting with, an earlier revision of my code I did have some variables that were set to HIGH once the bottom was pressed but I was not sure if I was going the right direction and I was not getting any changes on to my display. Probably just not doing it right.

I think I will follow your advice and remove the complexity of the display and just do Serial.print for now.

Not trying to input any data yet, too complex for me. I have a Mega so inputs are not a problem but my plan is to use a ProMini for package size. I eventually also will use a display shield to reduce outputs and increase availability of in/outputs. For now baby steps.

As far as that line of code you quoted, the reason for was so I had a 10 second counter for testing purposes. It actually kind of worked but not really as intended (had to hold the button, the display looked strange, it did count down but then it did some strange backwards turning off of the segments).

Let's further remove difficulty and only focus on one button. Once you make it work, you can expand to all buttons. Essentially if I understand correctly, regardless of the status of the count-down timer, pressing a button will make it count down using that preset value, right? This means keep reading all buttons (or one for now), update display if a second has elapsed, decide which one has been pushed, load pre-set value, restart timer. Once you have this logic, other features are easy to add on, such as setting up values.

pseudo code:

void loop()
{
  check_buttons();
  if button is pressed load timer value
  if timer expired, do something
}

Look for online tutorials for sensing button press first. I've been putting off doing a tutorial on this subject but maybe now is a good time for it.

Liudr, your suggestion of removing complexity and later adding features is pure brilliance.... every problem solving thread should start like that.

Back on point, I switched over to the Mega so I would not have to undo what I had wired up on the ProMini. I also changed some of the inputs for cleaner wiring on my breadboard. The sketch bellow does exactly what I want it to do... all be it not displayed on a 7 segment and not running on a real clock... just a delay.... that for my needs may be enough.

Tomorrow I will probably add constant integers for the times that will be updating... so any editing happens at the top of he code. Also I need to add some pull down resistors because sometimes the value would not start counting down as soon as I stopped pressing the button.

Next step... how to get the "starttime" value to be represented on my 4x7 segment display.

//THIS PROGRAM ALLOWS YOU TO PUSH A BUTTON TO START A PRE-DETERMINED COUNTDOWN TIMER.
//YOU CAN PROGRAM UP TO 6 INPUT TIMES.

const int lap1 = A1; //Add name of lap or course
const int lap2 = A2; //Add name of lap or course
const int lap3 = A3; //Add name of lap or course
const int lap4 = A4; //Add name of lap or course
const int lap5 = A5; //Add name of lap or course
const int lap6 = A6; //Add name of lap or course

int starttime;  // Number to countdown from

int button1 = 0;
int button2 = 0;
int button3 = 0;
int button4 = 0;
int button5 = 0;
int button6 = 0;

void setup() 
{                
  pinMode(lap1, INPUT);
  pinMode(lap2, INPUT);
  pinMode(lap3, INPUT);
  pinMode(lap4, INPUT);
  pinMode(lap5, INPUT);
  pinMode(lap6, INPUT);
  
  Serial.begin(9600);
}

void loop()
{
  button1 = digitalRead(lap1);
  button2 = digitalRead(lap2);
  button3 = digitalRead(lap3);
  button4 = digitalRead(lap4);
  button5 = digitalRead(lap5);
  button6 = digitalRead(lap6);
  
  if (button1 == HIGH) {
   int (starttime = 10);
  }
  if (button2 == HIGH) {
   int (starttime = 20);
  }
  if (button3 == HIGH) {
   int (starttime = 30);
  }
  if (button4 == HIGH) {
   int (starttime = 40);
  }
  if (button5 == HIGH) {
   int (starttime = 50);
  }
  if (button6 == HIGH) {
   int (starttime = 60);
  } 
  if (starttime > 0) {
  starttime = starttime - 1;  
  }
  Serial.print("Start Time: ");
  Serial.println(starttime);
//  Serial.print("Lap1: ");
//  Serial.println(button1);
//  Serial.print("Lap2: ");
//  Serial.println(button2);
//  Serial.print("Lap3: ");
//  Serial.println(button3);
//  Serial.print("Lap4: ");
//  Serial.println(button4);
//  Serial.print("Lap5: ");
//  Serial.println(button5);
//  Serial.print("Lap6: ");
//  Serial.println(button6);
  
  delay(1000);
}

Code is basic but looks good. Now you can think of ways to replace values such as 60 with user changeable values.

liudr:
Code is basic but looks good. Now you can think of ways to replace values such as 60 with user changeable values.

I did a timer where the time is set via dip switch. I used the analog inputs because all of my digital inputs were being used elsewhere in the project. I used a 10K resistor to hold each analog input HIGH and used the dip switches to switch the input low.

int val; //reads value of the Analog Inputs
int m; // Time in minutes
int AnalogPin0 = 0; // Analog 0 INPUT - adds 1 minute to the timer
int AnalogPin1 = 1; // Analog 1 INPUT - adds 2 minutes to the timer
int AnalogPin2 = 2; // Analog 2 INPUT - adds 4 minutes to the timer
int AnalogPin3 = 3; // Analog 3 INPUT - adds 8 minutes to the timer
int AnalogPin4 = 4; // Analog 4 INPUT - adds 16 minutes to the timer
int AnalogPin5 = 5; // Analog 5 INPUT - adds 32 minutes to the timer

void setup()
{
  pinMode(A0, INPUT);//Dip Switch Inputs
  pinMode(A1, INPUT);//Dip Switch Inputs
  pinMode(A2, INPUT);//Dip Switch Inputs
  pinMode(A3, INPUT);//Dip Switch Inputs
  pinMode(A4, INPUT);//Dip Switch Inputs
  pinMode(A5, INPUT);//Dip Switch Inputs
  val = analogRead(AnalogPin0);
    if (val < 500)
  {m = m +1;}
  val = analogRead(AnalogPin1);
    if (val < 500)
    {m = m +2;}
  val = analogRead(AnalogPin2);  
    if (val < 500)
  {m = m +4;}
   val = analogRead(AnalogPin3);
    if (val < 500)
  {m = m +8;}
   val = analogRead(AnalogPin4);
    if (val < 500)
  {m = m +16;}
   val = analogRead(AnalogPin5);
    if (val < 500)
  {m = m +32;}
}

Rokkit,

If you are running out of pins, see if this will help:

http://www.inmojo.com/store/liudr-arduino-and-physics-gadgets/item/serial-lcd-back-pack---phi-panel/

This saves 12 pins if you are using character lcd and 4x4 keypad.

Ok, getting dangerously close to having this sketch do what I want it to do.

The issues I have right now are:

  1. The code starts counting down as soon as the processor boots. So if I wait 5 seconds after boot, and press a button that should give me a 15 second count down, the display starts counting down from 10. I’m using the mills function to count down. How can I make it start a new count as soon as a button gets pressed?

  2. Also, once the countdown finishes, it does not go back to blinking zeros, it flashes zero, then it starts doing a binary regression only using zeros. So it turns off the first zero, then ten seconds later it turns off the 2nd zero, then the first zero flashes every 10 seconds until 100 seconds and the third zero flashes. I’m sure its because the display number is negative but I have not figured out the fix.

//THIS PROGRAM ALLOWS YOU TO PUSH A BUTTON TO START A PRE-DETERMINED COUNTDOWN TIMER.
//YOU CAN PROGRAM UP TO 6 INPUT TIMES.

const int time1 = 5;  //Track 1, input course time
const int time2 = 10;  //To Y Tech, input course time
const int time3 = 15;  //FG 4, input course time
const int time4 = 20;  //Isley Trail, input course time
const int time5 = 25;  //BBQ Run, input course time
const int time6 = 30;  //New Bowl With A Twist, input course time

int digit1 = 11; //PWM Display pin 12
int digit2 = 10; //PWM Display pin 9
int digit3 = 9; //PWM Display pin 8
int digit4 = 6; //PWM Display pin 6
int segA = A1; //Display pin 11
int segB = 3; //Display pin 7
int segC = 4; //Display pin 4
int segD = 5; //Display pin 2
int segE = A0; //Display pin 1
int segF = 7; //Display pin 10
int segG = 8; //Display pin 5

const int lap1 = 2;
const int lap2 = 12;
const int lap3 = 13;
const int lap4 = A2;
const int lap5 = A3;
const int lap6 = A4;

int start_num = 0;  // Number to countdown from
unsigned long time;
int brightness = 200;

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(lap1, INPUT);
  pinMode(lap2, INPUT);
  pinMode(lap3, INPUT);
  pinMode(lap4, INPUT);
  pinMode(lap5, INPUT);
  pinMode(lap6, INPUT);
  
  Serial.begin(9600);
}

void loop()
{
  if (digitalRead(lap1) ==  HIGH) {
     int (start_num = time1);
  }
  if (digitalRead(lap2) ==  HIGH) {
     int (start_num = time2);
  }
  if (digitalRead(lap3) == HIGH) {
     int (start_num = time3);
  }
  if (digitalRead(lap4) ==  HIGH) {
     int (start_num = time4);
  }
  if (digitalRead(lap5) ==  HIGH) {
     int (start_num = time5);
  }
  if (digitalRead(lap6) ==  HIGH) {
     int (start_num = time6);
  }
  
  if (start_num > 0) {
   time=millis()/1000;
   displayNumber(start_num - time); 
    }  
   else {
    time=millis(); // reached zero, flash the display
    while(millis() < time+200) {
      displayNumber(0);  // display 0 for 0.2 second
    }
    time=millis();    
    while(millis() < time+200) {
      lightNumber(10);  // Turn display off for 0.2 second
     }
  Serial.println(time);
   }  
}

void displayNumber(int toDisplay) {
#define DISPLAY_BRIGHTNESS (brightness)
#define DIGIT_ON  LOW
#define DIGIT_OFF  HIGH

  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  HIGH
#define SEGMENT_OFF LOW

  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;
  }
}

liudr:
Rokkit,

If you are running out of pins, see if this will help:

Page Not Found

This saves 12 pins if you are using character lcd and 4x4 keypad.

Interesting - I will keep it in mind for future reference. I do in fact have another project that I’m working on - 4 independently running timers. And the display has 4 lines… Coincidence? 8)

bushman98,

This logic is wront:

  if (start_num > 0) {
   time=millis()/1000;
   displayNumber(start_num - time); 
    }

What you should do is to display start_number-(time-time0), well, bad naming so try these:

count_ms, instead of start)num: usage, store the counter's value after a preset is pressed, in milliseconds, change your presets into milliseconds. Your seconds tick could miss a whole second. start_ms, instead of time: usage, store the millisecond tick when the timer starts to count down. This gets assigned after a button down is detected. Like below:

  if (digitalRead(lap1) ==  HIGH) {
     count_ms=lap1_preset_ms; //time1
     start_ms=millis();
  }

Then you should display (count_ms-(millis()-start_ms))/1000 When the above value reaches zero or less, then you do the flashing or blinking thing, which you can fix after you fix the timer and counter.

Remember to add some _s or _ms postfixes to the variables so you don't confuse units. Try to calculate seconds tick before calculation but keep everything in milliseconds.

Rokkit,

That sounds like a good fit with my phi-panel :)

Luidr:

Once more your suggestion is what I needed. Made it so that the moment the button is pressed a value is set to what ever the millis() happen to be at that time and then they get subtracted accordingly. The countdown part of the sketch works great now. There is still a little bug with what happens when it reaches zero. I'm trying to figure out how to jump out of the countdown loop and go to the "else" routine where it blinks zeros. Tried some "if" statements and some "while" statements but I'll work on it for a few more days before I post an updated code.

Post the code when you are ready. You are making good progress.

OK, so sketch is done, but I still need answers.

Fixed the regressive count and figured out why it was happening.

What the sketch was doing was: press button once, count down, no problem. Press the button again, counts down again, no problem. Do it a third time… nothing happens, its stuck on flashing zeros.

So I decided to do some serial monitoring. The value COUNT always does what it supposed to, count backwards one unit per second. The MILLIS always displays a ever increasing count, internal to the processor. The START_MS is the one that screws up after the 2nd cycle. First time it matches the current MILLIS count, the second time it does the same, the third time it usually goes to -50 but not always, sometimes its -32, if I hold the button down, it will sometimes be -16 and start doing a regressive count… but not always.

So I took a wild guess at it and figured the variable was “being overrun/over filled” by the very large MILLIS value. I don’t know if the last sentence made any sense to anybody else. Point being that I divided the MILLIS value by 1000 when equating it to the START_MS. Tada!!! problem fixed. Code works like a charm.

Now, someone explained to me what I did and why it worked… cause I have no ideal. How long can the processor be on before the MILLIS value is to large (even divided by 1000) to “fit” in the START_MS variable?

Next step is lay out my boards, wiring and switches and design the enclosure.

Thanks for all the help.

I trimmed the sketch to only show whats important.

void loop()
{
  if (digitalRead(lap1) ==  HIGH) {
     int (start_num = time1);
     start_ms = millis()/1000;
  }
 .
.
.
count = (start_num - ((millis()/1000)- start_ms));

  if (count > 0) {
     displayNumber(count); 
  } 
  else {
  time=millis(); // reached zero, flash the display
    while(millis() < time+200) {
      displayNumber(0);  // display 0 for 0.2 second
    }
    time=millis();    
    while(millis() < time+200) {
      lightNumber(10);  // Turn display off for 0.2 second
     }
  }  
}

Post complete code!

I suspect you defined start_ms as integer, which has 32767 to -32768 range. It overruns in 32 seconds so if you are quick about resetting your 10 second timer, you will overrun it during your 3rd try, good observation! Define all millis() related variables as unsigned long:

unsigned long start_ms=0;

This will overrun in 49.7 days, which can be corrected if you always take millis()-start_ms and use it to do decisions, not other formats.