Help with Countdown Timer (scoreboard)

what am I missing.

Code tags.

  pinMode(minutesButtonPin, INPUT);
  pinMode(secondsButtonPin, INPUT);
  pinMode(startButtonPin, INPUT);

Using the internal pullup is so much simpler...

 timeRemaining = minutesToGo * 100 + secondsToGo;

How long would that be?

  minutesButtonState = digitalRead(minutesButtonPin);
  secondsButtonState = digitalRead(secondsButtonPin);
 startButtonState = digitalRead(startButtonPin);

 
  if (minutesButtonState != lastButtonStateMinutes) {

Why do all the reads together? Do them where you use the data.

  if (minutesButtonState != lastButtonStateMinutes) {
   
    if (minutesButtonState == HIGH) {
     
      minutesToGo++;
      delay(50);
    }
  lastButtonStateMinutes = minutesButtonState;

Putting the { on the line with the statement ONLY makes sense if you are trying to save screen real-estate. You look like a doofus when you then follow that with a blank line.

Why is there a delay in there? If your switches REALLY bounce that long, get some better switches.

  if(startButtonState != lastButtonStateStart){
    if(startButtonPin == HIGH){
      timeRemaining--;
      delay(1000);
    }
  }
}

So, unless the start switch changes state, don't decrease the time remaining?

The variable timeRemaining is ONLY for display purposes. You increment secondsToGo and/or minutesToGo, if the appropriate switch is pressed, but you never decrement them.

On EVERY pass through loop, you need delay(1000) and to decrement some count of seconds.

On EVERY pass through loop(), you need to calculate minutesToGo and secondsToGo, from that count of seconds, if the timer is to be running.

On every pass through loop(), you need to see if the start switch has become pressed, and, if has, set the flag that says the timer is running.

The best thing you can do is put the code that deals with the minutes up switch and the seconds up switch in a function. Put the code to deal with the start switch in a function. Put the code to display a value on the matrix in a function.

Then, we can debug and discuss each function separately, and debug and discuss the calls to the functions separately.

ok so i added some tags with a tag down at the botton of the sketch explaining where i am stuck the most. Currently with the code below i can set the display time and press a button to begin a countdown. however the problem is with converting it to a time format as i explain in the tag below.
also i did my best at putting everything into what i believe you were talking about when you said put them into functions. i will try to attach a photo also. of my test board currently i have the colon turned off but that is an easy fix.

#include <Wire.h>

#include <Adafruit_GFX.h>
#include <gfxfont.h>

#include <Adafruit_LEDBackpack.h>
Adafruit_7segment matrix = Adafruit_7segment();
const int minutesButtonPin = 2; // connected to button to set minutes
const int secondsButtonPin = 3; // connected to button to set seconds
const int startButtonPin = 4; // start button for countdown
int startButtonState = 0; // current state of start button at begining of script
int lastButtonStateStart = 0; // to monitor state change
int minutesButtonState = 0; // current state of minutes button at begining of script
int lastButtonStateMinutes = 0; // to monitor state change
int secondsButtonState = 0; // current state of seconds button at begining of script
int lastButtonStateSeconds = 0; // to monitor state change
int minutesToGo = 0; // starts minutes at zero waiting for user input
int secondsToGo = 0; // starts seconds at zero waiting for user input

int timeRemaining = 0; // used for displaying time on the adafruit ht16k33 4 digit 7 segment display backpack

void setup() {

pinMode(minutesButtonPin, INPUT); // sets pin 2 as input for minutes pushbutton
pinMode(secondsButtonPin, INPUT); // sets pin 3 as input for seconds pushbutton
pinMode(startButtonPin, INPUT); // sets pin 4 as input for start pushbutton

matrix.begin(0x70); // address for communication to the 7 segment display
timeRemaining = minutesToGo * 100 + secondsToGo; // sets the initial display for start up. shows zero until user enters minutes and seconds
matrix.print(timeRemaining); // used for display on 7 segment
matrix.writeDisplay(); // used for display on 7 segment

}
void loop()
{
displayTimeRemaining(); //calls the display function
minutesUp(); // calls the minutes input function
secondsUp(); // calls the seconds input function
startUp(); // calls the start button function

}

void displayTimeRemaining()
{
timeRemaining = minutesToGo * 100 + secondsToGo;
matrix.print(timeRemaining);
matrix.writeDisplay();
}

void minutesUp()
{
minutesButtonState = digitalRead(minutesButtonPin); // gets button state
if (minutesButtonState != lastButtonStateMinutes) { // checks it against last state
if (minutesButtonState == HIGH) { // if user is pressing button increase the minutes by one which in turn shows 1:00 on the display
minutesToGo++;
}
lastButtonStateMinutes = minutesButtonState; // sets button state

}
}

void secondsUp()
{
secondsButtonState = digitalRead(secondsButtonPin); // gets button state
if (secondsButtonState != lastButtonStateSeconds) { // checks it against last state
if(secondsButtonState == HIGH) { // if user is pressing button increase the seconds by one
secondsToGo++;
if(secondsToGo == 60){ // stops at six and sets seconds to 0 and adds one to minutes. ie: 5:59 hit the button one more time and display shows 6:00
secondsToGo = 0;
minutesToGo++;
}
}
lastButtonStateSeconds = secondsButtonState; // sets button state

}
}
void startUp()
{
startButtonState = digitalRead(startButtonPin); // gets button state
if(startButtonState != lastButtonStateStart){ // checks it against last state
if(startButtonState = HIGH){ // if user pressed button
timer(); // calls timer function
}

}
lastButtonStateStart = startButtonState; //sets button state
}

void timer() // this is where i am stuck currently when i press the start button the timer will begin
{ // counting down however and i know there needs to be a conversion done but i cant figure out how or where in order
secondsToGo--; // to get the display to go from say 4:00 to 3:59 instead of whats happening now which would be 4:00 to 3:99
delay(1000);
}

board photo

ok so i added some tags

Then why does the f**king block still say Quote?

You still do not have a single variable that contains the number of seconds to count down. I'm going to step out of this thread if you do not define one.

Paul thank you for your help up until this point. I originally thought I had a variable defined as secondstoplay but I was having a hard time implementing it into the sketch because as I stated in the beginning I have zero programming experience and am trying to teach myself this with some help from those like yourself. I removed it from this sketch I recently posted and did not place it back. My oversight. But your probably right it's time to step out. You have clearly lost patience which I get it is tough to help someone from the other side of the country. So thanks for the help you have given.
Regards
Tim

with a lot of reading i have gotten to the point of where i can keep track of scores for two players and start and stop the play clock. however i cannot figure out where to put the command to stop the clock and sound a buzzer once the clock hits zero. i have placed the if statement at the end of the loop and many other different places within the code. however everytime the clock hits zero it just keeps counting down and show -1,-2,-3 etc etc. Anyone have any hints as to where im going wrong. thanks
oh and i know i can increase a counter by one with a button press. example buttoncounter++. but is there a way to increase it by 10 or even 100. i have tried. buttoncounter + 10 and it does not work.
Thanks again

#include <Wire.h>

#include <Adafruit_GFX.h>
#include <gfxfont.h>

#include <Adafruit_LEDBackpack.h>

#include "TimerOne.h"
Adafruit_7segment matrix = Adafruit_7segment();
#define DATA1 8 // -
#define LATCH1 9 // ---handles the shift registers for player one score
#define CLOCK1 10 // -
#define DATA2 11 //
#define LATCH2 12 //---- handles the shift registers for player two score
#define CLOCK2 13 //
int timeRemaining = 0;
int minutesToGo = 0;
int secondsToGo = 0;
int timeLine = 300; //start with 5minutes
int homeScore=0;
int awayScore=0;
int buttonState = 0;
int buttonState2 = 0;
int buttonStateDec = 0;
int buttonStateDec2 = 0;
int lastButtonState = 0;
int lastButtonState2 = 0;
int lastButtonStateDec = 0;
int lastButtonStateDec2 = 0;
int digits[] = {2, 158, 36, 12, 152, 72, 64, 30, 0, 24, 16, 0, 98, 2, 96, 112,}; /// used for displaying player one score
int digits2[] = {2, 158, 36, 12, 152, 72, 64, 30, 0, 24, 16, 0, 98, 2, 96, 112,}; /// used for displaying player two score

bool paused=1; // start in a paused state

//button functions
// 2 Reset score and time (and waits for buttone 3 to start)
// 3 Pause/Resume (in paused state timer stops going down)
// 4 Increment Home Score
// 5 Reduce Home Score
// 6 Increase Away Score
// 7 Reduce Away Score

void setup()
{

pinMode(LATCH1, OUTPUT);
pinMode(DATA1, OUTPUT);
pinMode(CLOCK1, OUTPUT);
player1displayNumber(homeScore);
pinMode(LATCH2, OUTPUT);
pinMode(DATA2, OUTPUT);
pinMode(CLOCK2, OUTPUT);
player2displayNumber(awayScore);

matrix.begin(0x70);
int n;
for (n=2;n<8;n++){
pinMode(n,INPUT_PULLUP);
Serial.begin(9600);
Timer1.initialize();
Timer1.attachInterrupt(updateTimeline);

}
}

//set by interrupt routine to signal display need updating
bool timeUpdated=true;
void loop()
{

int n;
bool debounce=false;

//first look for any input
for (n=2;n<8;n++){
if(digitalRead(n)==LOW)
{
debounce=true;
switch(n)
{
case 2://reset
timeLine=300;//start with 3minutes
homeScore=0;
awayScore=0;
paused=true;
break;

case 3://pause-restart
paused=!paused;

break;

case 4://increment home
player1();
break;
case 5://decrement home score
player1Sub();

break;
case 6://increment away score
player2();
break;
case 7://decrement home score
player2Sub();

break;
}
}
}
//Now update display (but only if updateTime has executed since last time)
if(timeUpdated){
updateDisplay();
}
if(debounce){
delay(400);
}

}

void updateDisplay()
{
boolean drawDots = true;
minutesToGo = timeLine / 60;
secondsToGo = timeLine % 60;
timeRemaining = minutesToGo * 100 + secondsToGo;
matrix.print(timeRemaining);
matrix.drawColon(drawDots);
matrix.writeDisplay();

}

void updateTimeline()
{
if(!paused){

timeLine--;
}
timeUpdated=true;

}
void player1() ////// increases player one score
{
int n;

buttonState = digitalRead(n);
if(buttonState != lastButtonState)
{
if (buttonState = HIGH){
homeScore++;
player1displayNumber(homeScore);
delay(25);

}
}
if (homeScore == 100){
homeScore = 0;
}

}

void player1Sub() ///// decreases player one score
{
int n;

buttonStateDec = digitalRead(n);
if(buttonStateDec != lastButtonStateDec)
{
if (buttonStateDec = HIGH){
homeScore--;
player1displayNumber(homeScore);
delay(25);

}
}
if (homeScore == 100){
homeScore = 0;
}

}
void player1displayNumber(int n)
{
int left, right=0;
if (n < 10)
{
digitalWrite(LATCH1, LOW);
shiftOut(DATA1, CLOCK1, LSBFIRST, digits[n]);
shiftOut(DATA1, CLOCK1, LSBFIRST, 2);
digitalWrite(LATCH1, HIGH);
}
else
{
right = n % 10;
left = n / 10;
digitalWrite(LATCH1, LOW);
shiftOut(DATA1, CLOCK1, LSBFIRST, digits);
shiftOut(DATA1, CLOCK1, LSBFIRST, digits);
digitalWrite(LATCH1, HIGH);
}
}

void player2() ///// increases player two score
{
int n;

buttonState2 = digitalRead(n);
if(buttonState2 != lastButtonState2)
{
if (buttonState2 = HIGH){
awayScore++;
player2displayNumber(awayScore);
delay(25);

}
}
if (homeScore == 100){
homeScore = 0;
}

}

void player2Sub() ///// decreases player two score
{
int n;

buttonStateDec2 = digitalRead(n);
if(buttonStateDec2 != lastButtonStateDec2)
{
if (buttonStateDec2 = HIGH){
awayScore--;
player2displayNumber(awayScore);
delay(25);

}
}
if (homeScore == 100){
homeScore = 0;
}

}

void player2displayNumber(int n)
{
int left, right=0;
if (n < 10)
{
digitalWrite(LATCH2, LOW);
shiftOut(DATA2, CLOCK2, LSBFIRST, digits[n]);
shiftOut(DATA2, CLOCK2, LSBFIRST, 2);
digitalWrite(LATCH2, HIGH);
}
else
{
right = n % 10;
left = n / 10;
digitalWrite(LATCH2, LOW);
shiftOut(DATA2, CLOCK2, LSBFIRST, digits2);
shiftOut(DATA2, CLOCK2, LSBFIRST, digits2);
digitalWrite(LATCH2, HIGH);
}
}

if (buttonState2 = HIGH){

Assigning a value to a variable in an if statement is rarely useful.

I believe this should read if( buttonState2 == High) correct?
what I am confused about is why is the program working properly if it is written wrong. Is it because the moment that specific button is pressed it is assigning the value high rather than checking to see if it is high?

I believe this should read if( buttonState2 == High) correct?

Yes.

Is it because the moment that specific button is pressed it is assigning the value high rather than checking to see if it is high?

Yes.

Just trying to help here: :slight_smile:

How to post your code in the Arduino forum:

After you have typed your message, start the Arduino IDE if not already running and load or type in your code.
Right click in the editor window then left click [Select All].
Right click again then left click [Copy].
In the forum [New Topic] or [Reply] page, click the

</>

code symbol in the upper left.
Right click in the box that appears then left click [Paste].

Or type:

[code]

Type or
paste your
code here
[/code]

Assigning a value to a variable in an if statement is rarely useful.

I changed the error in the coding. See the code changes below.

Just trying to help here: :slight_smile:

outsider I'm sure PaulS will be happy now as well that I FINALLY figured out how to properly post my code. Sorry Paul.

If you guys could help me out as to why I cannot get the timer to stop counting that would be awesome.
just for testing purposes I have used the following to see if I can get the timer to stop counting.

if(timeLine == 0)
{
exit;
}

I have placed it in the loop with no luck I have also placed it in the updatedisplay area as well with no luck. what simple step am I missing? they exit command as you will see is not in the below code. basically because I have no idea where to put it at this point.

#include <Wire.h>

#include <Adafruit_GFX.h>
#include <gfxfont.h>

#include <Adafruit_LEDBackpack.h>

#include "TimerOne.h"
Adafruit_7segment matrix = Adafruit_7segment();
#define DATA1 8      // -
#define LATCH1 9      // ---handles the shift registers for player one score
#define CLOCK1 10   //  -
#define DATA2 11    //
#define LATCH2 12    //---- handles the shift registers for player two score
#define CLOCK2 13  //
int timeRemaining = 0;
int minutesToGo = 0;
int secondsToGo = 0;
int timeLine = 10;      //start with 5minutes
int homeScore=0;
int awayScore=0;
int buttonState = 0;      
int buttonState2 = 0;
int buttonStateDec = 0;
int buttonStateDec2 = 0;
int lastButtonState = 0;
int lastButtonState2 = 0;
int lastButtonStateDec = 0;
int lastButtonStateDec2 = 0;
int digits[] = {2, 158, 36, 12, 152, 72, 64, 30, 0, 24, 16, 0, 98, 2, 96, 112,};    /// used for displaying player one score
int digits2[] = {2, 158, 36, 12, 152, 72, 64, 30, 0, 24, 16, 0, 98, 2, 96, 112,};   /// used for displaying player two score

bool paused=1;       // start in a paused state



//button functions
//  2 Reset score and time (and waits for buttone 3 to start)
//  3 Pause/Resume (in paused state timer stops going down)
//  4 Increment Home Score
//  5 Reduce Home Score
//  6 Increase Away Score
//  7 Reduce Away Score


void setup()
{
  
  pinMode(LATCH1, OUTPUT);
  pinMode(DATA1, OUTPUT);
  pinMode(CLOCK1, OUTPUT);
  player1displayNumber(homeScore);
  pinMode(LATCH2, OUTPUT);
  pinMode(DATA2, OUTPUT);
  pinMode(CLOCK2, OUTPUT);
  player2displayNumber(awayScore);
  
  matrix.begin(0x70);
  int n;
  for (n=2;n<8;n++){
    pinMode(n,INPUT_PULLUP);
  Serial.begin(9600);
    Timer1.initialize();
  Timer1.attachInterrupt(updateTimeline);
  
  
  }
}

//set by interrupt routine to signal display need updating
bool timeUpdated=true;
void loop()
{

int n;
  bool debounce=false;

//first look for any input
  for (n=2;n<8;n++){
    if(digitalRead(n)==LOW)
    {
      debounce=true;
      switch(n)
      {
      case 2://reset
        timeLine=300;//start with 3minutes
        homeScore=0;
        awayScore=0;
        paused=true;
        break;

      case 3://pause-restart
        paused=!paused;
     
        break;

      case 4://increment home
       player1();
        break;
      case 5://decrement home score
      player1Sub();
        
        break;
      case 6://increment away score
        player2();
        break;
      case 7://decrement home score
        player2Sub();

        
        break;   
      }
    }
  }
  //Now update display (but only if updateTime has executed since last time)
  if(timeUpdated){
    updateDisplay();
  }
 
  if(debounce){
    delay(400);
}


}

void updateDisplay()
{
   boolean drawDots = true;
  minutesToGo = timeLine / 60;
  secondsToGo = timeLine % 60;
  timeRemaining = minutesToGo * 100 + secondsToGo;
  matrix.print(timeRemaining);
  matrix.drawColon(drawDots);
  matrix.writeDisplay();



}

void updateTimeline()
{
  if(!paused){
  
    timeLine--;
  }
  timeUpdated=true;

}
void player1()           //////  increases player one score
{
  int n;

  buttonState = digitalRead(n);
  if(buttonState != lastButtonState)
  {
    if (buttonState == HIGH){
      homeScore++;
      player1displayNumber(homeScore);
      delay(25);
     
    }
  }
  if (homeScore == 100){
    homeScore = 0;
  }

}

void player1Sub()                /////  decreases player one score
{
  int n;

  buttonStateDec = digitalRead(n);
  if(buttonStateDec != lastButtonStateDec)
  {
    if (buttonStateDec == HIGH){
      homeScore--;
      player1displayNumber(homeScore);
      delay(25);
     
    }
  }
  if (homeScore == 100){
    homeScore = 0;
  }

}
void player1displayNumber(int n)
{
  int left, right=0;
  if (n < 10)
  {
    digitalWrite(LATCH1, LOW);
    shiftOut(DATA1, CLOCK1, LSBFIRST, digits[n]);
    shiftOut(DATA1, CLOCK1, LSBFIRST, 2);
    digitalWrite(LATCH1, HIGH);
  }
  else
  {
    right = n % 10;
    left = n / 10;
    digitalWrite(LATCH1, LOW);
    shiftOut(DATA1, CLOCK1, LSBFIRST, digits[right]);
    shiftOut(DATA1, CLOCK1, LSBFIRST, digits[left]);
    digitalWrite(LATCH1, HIGH);
  }
}

void player2()                             /////  increases player two score
{
  int n;

  buttonState2 = digitalRead(n);
  if(buttonState2 != lastButtonState2)
  {
    if (buttonState2 == HIGH){
      awayScore++;
      player2displayNumber(awayScore);
      delay(25);
     
    }
  }
  if (homeScore == 100){
    homeScore = 0;
  }

}

void player2Sub()                              /////  decreases player two score
{
  int n;

  buttonStateDec2 = digitalRead(n);
  if(buttonStateDec2 != lastButtonStateDec2)
  {
    if (buttonStateDec2 == HIGH){
      awayScore--;
      player2displayNumber(awayScore);
      delay(25);
     
    }
  }
  if (homeScore == 100){
    homeScore = 0;
  }

}

void player2displayNumber(int n)                             
{
  int left, right=0;
  if (n < 10)
  {
    digitalWrite(LATCH2, LOW);
    shiftOut(DATA2, CLOCK2, LSBFIRST, digits[n]);
    shiftOut(DATA2, CLOCK2, LSBFIRST, 2);
    digitalWrite(LATCH2, HIGH);
  }
  else
  {
    right = n % 10;
    left = n / 10;
    digitalWrite(LATCH2, LOW);
    shiftOut(DATA2, CLOCK2, LSBFIRST, digits2[right]);
    shiftOut(DATA2, CLOCK2, LSBFIRST, digits2[left]);
    digitalWrite(LATCH2, HIGH);
  }
}

What do you think that

exit;

is doing?

Try this, instead:

if(timeLine == 0)
{
   47;
}

Do you see any difference? I doubt that you will.

Now, if you tried:

if(timeLine == 0)
{
   exit();
}

you might see a difference.

But, stopping the processor because the time expired is hardly useful. Not decrementing the time remaining is different. Not showing the time remaining is different.

if(timeLine == -1)
{
  timeLine = 300;               //timer set to 5 minutes
  paused = true;                // pauses timer
  homeScore = 0 ;             // resets home score
  awayScore =0;               // resets away score
  player1displayNumber(homeScore);    // refreshes the display
  player2displayNumber(awayScore);    //  refreshes the display
}

this is what I have put into the sketch to get the results I was looking for.

now im working on trying to control the timeLine with a push button. so that when I press the button it will increase by 100. what I have thought of is creating a counter and using a set of if statements to control the timeLine. counter starts at 0 and every time I press a button the counter goes up by one and the time line is set. I will include a rough code below. I know its not the best way but its the only way I can think of. Am I on the right path?

void setPeriodLength()           //////  increases period
{
  int buttonStatePeriod;               
  int lastButtonStatePeriod;
  int Periodcounter = 0;

  buttonStatePeriod = digitalRead(8);   ///button connected to pin 8
  if(buttonStatePeriod != lastButtonStatePeriod)
  {
    if (buttonStatePeriod == HIGH){
      Periodcounter++;
      if(Periodcounter == 1)
      {
        timeLine = 100;
      }
      if(Periodcounter == 2)
      {
        timeLine = 200;
      }
      if(Periodcounter == 3)
      {
        timeLine = 300;
      }
      if(Periodcounter == 4)
      {
        timeLine = 400;
      }
      if(Periodcounter == 5)
      {
        timeLine = 500;
      }
      if(Periodcounter == 6)
      {
        timeLine = 600;
      }
      if(Periodcounter == 7)
      {
        timeLine = 700;
      }
      if(Periodcounter == 8)
      {
        timeLine = 800;
      }
      if(Periodcounter == 9)
      {
        timeLine = 900;
      }
      if(Periodcounter == 10)
      {
        timeLine = 1000;
      }
      if(Periodcounter == 11)
      {
        return();
      }
      
      
     
    }
  }

}

So, unless PeriodCounter is 11, timeLine is 100 * PeriodCounter. How many lines of code does it REALLY take to say that?