2-Digit 7-segment display counter with button help!

I'm new in the Arduino world and I want to make a counter with two common anode 7-segment displays. The wiring for the pushbutton I'm using is with pull-up resistors. The wiring I'm using is shown in the images. The wiring is fine, no problem with that, but I need help with the programming.

For this program, I used the code from section 5.3 of the Arduino Cookbook for the debounce function and the code from secction 7.11 of the same Cookbook. Everything went fine, the project can count from 00 to 99, but I wanted to count with every push, but it only counts when I press the button for certain time. I want that if I press the button, no matter how long, it only counts one time. If I press the button 5 times, it counts five times, no matter how fast I push the button. I've been trying a lot with the code, but I can't seem to make it right. I will really appreaciate the help. The code I'm using is below:

/*

  • SevenSegmentMpx sketch
  • Shows numbers ranging from 0 through 99 on a two-digit display
    */
    // bits representing segments A through G (and decimal point) for numerals 0-9

int value = 0;
const int inputPin = 12; // the number of the input pin
const int ledPin = 13; // the number of the output pin
const int debounceDelay = 100;
const int numeral[10] = {
//ABCDEFG /dp
B11111100, // 0
B01100000, // 1
B11011010, // 2
B11110010, // 3
B01100110, // 4
B10110110, // 5
B00111110, // 6
B11100000, // 7
B11111110, // 8
B11100110, // 9
};
// pins for decimal point and each segment
// dp,G,F,E,D,C,B,A
const int segmentPins[] = { 4,7,8,6,5,3,2,9};
const int nbrDigits= 2; // the number of digits in the LED display
//dig 1 2 3 4
const int digitPins[nbrDigits] = {10, 11};

boolean debounce(int pin)
{
boolean state;
boolean previousState;
previousState = digitalRead(pin); // store switch state
for(int counter=0; counter < debounceDelay; counter++)
{
delay(1); // wait for 1 millisecond
state = digitalRead(pin); // read the pin
if( state != previousState)
{
counter = 0; // reset the counter if the state changes
previousState = state; // and save the current state
}
}
// here when the switch state has been stable longer than the debounce period

if(state == LOW) // LOW means pressed (because pull-ups are used)
return true;
else
return false;

return state;
}

void setup()
{
for(int i=0; i < 8; i++)
pinMode(segmentPins*, OUTPUT); // set segment and DP pins to output*
for(int i=0; i < nbrDigits; i++)
pinMode(digitPins*, OUTPUT);*
pinMode(inputPin, INPUT);
pinMode(ledPin, OUTPUT);
}
void loop()
{
//int value = analogRead(0);
if ( digitalRead(12) == LOW)
{

* if(debounce(inputPin))*
* {*
* value = value++;*

* }*
* while(digitalRead(12)==HIGH){*
* showNumber(value);*
* }*

}
showNumber(value);
}
void showNumber( int number)
{
if(number == 0)
showDigit( 0, nbrDigits-1) ; // display 0 in the rightmost digit
else
{
// display the value corresponding to each digit
// leftmost digit is 0, rightmost is one less than the number of places
for( int digit = nbrDigits-1; digit >= 0; digit--)
{
if(number > 0)
{
showDigit( number % 10, digit) ;
number = number / 10;
}
}
}
}
// Displays given number on a 7-segment display at the given digit position
void showDigit( int number, int digit)
{
* delay(5);*
* digitalWrite( digitPins[digit], HIGH );*
* for(int segment = 1; segment < 8; segment++)*
* {*
* boolean isBitSet = bitRead(numeral[number], segment);*
* // isBitSet will be true if given bit is 1*
* isBitSet = ! isBitSet; // remove this line if common cathode display*
* digitalWrite( segmentPins[segment], isBitSet);*
* }*
* delay(5);*
* digitalWrite( digitPins[digit], LOW );*
}
Pull up.png
counter.png

// here when the switch state has been stable longer than the debounce period

if(state == LOW) // LOW means pressed (because pull-ups are used)
return true;
else
return false;

return state;
}

The third return statement will never be executed.

You need to look at the state change detection example. Your code cares that the switch IS pressed, rather than that the switch BECOMES pressed. Big difference.

At least, that 's what I think your incorrectly posted code is doing. I'm sure your real code looks nothing like that.

That part of the code is given in the Arduino Cookbook, I didn't change thar part of the code, but I just modified this part of the code:

void loop()
{
//int value = analogRead(0);


 if ( digitalRead(12) == HIGH)
{ 
  
  if(debounce(inputPin))
  {
     value = value++; 
     
   
  }
  while(digitalRead(12)==LOW){
     showNumber(value);
   }
     
}

}

With this modification, it counts with every push of the button, but when I let the button go, the number disappears, but it keeps count of the pushes. What do I do to keep showing the number when I let go the button?

Start by posting ALL of the code PROPERLY and maybe we can help.

What do I do to keep showing the number when I let go the button?

Make the code to display the value unconditional. Currently, whether the function is called, or not, depends on the state of a switch.

This is all the code:

int value = 0;
const int inputPin = 12; // the number of the input pin
const int ledPin = 13; // the number of the output pin
const int debounceDelay = 50;
const int numeral[10] = {
//ABCDEFG /dp
B11111100, // 0
B01100000, // 1
B11011010, // 2
B11110010, // 3
B01100110, // 4
B10110110, // 5
B00111110, // 6
B11100000, // 7
B11111110, // 8
B11100110, // 9
};
// pins for decimal point and each segment
// dp,G,F,E,D,C,B,A
const int segmentPins[] = { 4,7,8,6,5,3,2,9};
const int nbrDigits= 2; // the number of digits in the LED display
//dig 1 2 3 4
const int digitPins[nbrDigits] = {10, 11};

boolean debounce(int pin)
{
boolean state;
boolean previousState;
previousState = digitalRead(pin); // store switch state
for(int counter=0; counter < debounceDelay; counter++)
{
delay(1); // wait for 1 millisecond
state = digitalRead(pin); // read the pin
if( state != previousState)
{
counter = 0; // reset the counter if the state changes
previousState = state; // and save the current state
}
}
// here when the switch state has been stable longer than the debounce period

if(state == LOW) // LOW means pressed (because pull-ups are used)
return true;
else
return false;

return state;
}

void setup()
{
for(int i=0; i < 8; i++)
pinMode(segmentPins[i], OUTPUT); // set segment and DP pins to output
for(int i=0; i < nbrDigits; i++)
pinMode(digitPins[i], OUTPUT);
pinMode(inputPin, INPUT);
pinMode(ledPin, OUTPUT);
}
void loop()
{
//int value = analogRead(0);


 if ( digitalRead(12) == HIGH)
{ 
  
  if(debounce(inputPin))
  {
     value = value++; 
     
   
  }
  while(digitalRead(12)==LOW){
     showNumber(value);
   }
   
  
}




}
void showNumber( int number)
{
if(number == 0)
showDigit( 0, nbrDigits-1) ; // display 0 in the rightmost digit
else
{
// display the value corresponding to each digit
// leftmost digit is 0, rightmost is one less than the number of places
for( int digit = nbrDigits-1; digit >= 0; digit--)
{
if(number > 0)
{
showDigit( number % 10, digit) ;
number = number / 10;
}
}
}
}
// Displays given number on a 7-segment display at the given digit position
void showDigit( int number, int digit)
{
  delay(2);
  digitalWrite( digitPins[digit], HIGH );
  for(int segment = 1; segment < 8; segment++)
  {
    boolean isBitSet = bitRead(numeral[number], segment);
    // isBitSet will be true if given bit is 1
    isBitSet = ! isBitSet; // remove this line if common cathode display
    digitalWrite( segmentPins[segment], isBitSet);
  }
  delay(2);
  digitalWrite( digitPins[digit], LOW );
}

Now run it through the Auto Format tool (Ctrl + T in the IDE) and re-post it to fix the indenting.

int value = 0;
const int inputPin = 12; // the number of the input pin
const int ledPin = 13; // the number of the output pin
const int debounceDelay = 50;
const int numeral[10] = {
  //ABCDEFG /dp
  B11111100, // 0
  B01100000, // 1
  B11011010, // 2
  B11110010, // 3
  B01100110, // 4
  B10110110, // 5
  B00111110, // 6
  B11100000, // 7
  B11111110, // 8
  B11100110, // 9
};
// pins for decimal point and each segment
// dp,G,F,E,D,C,B,A
const int segmentPins[] = { 
  4,7,8,6,5,3,2,9};
const int nbrDigits= 2; // the number of digits in the LED display
//dig 1 2 3 4
const int digitPins[nbrDigits] = {
  10, 11};

boolean debounce(int pin)
{
  boolean state;
  boolean previousState;
  previousState = digitalRead(pin); // store switch state
  for(int counter=0; counter < debounceDelay; counter++)
  {
    delay(1); // wait for 1 millisecond
    state = digitalRead(pin); // read the pin
    if( state != previousState)
    {
      counter = 0; // reset the counter if the state changes
      previousState = state; // and save the current state
    }
  }
  // here when the switch state has been stable longer than the debounce period

  if(state == LOW) // LOW means pressed (because pull-ups are used)
    return true;
  else
    return false;

  return state;
}

void setup()
{
  for(int i=0; i < 8; i++)
    pinMode(segmentPins[i], OUTPUT); // set segment and DP pins to output
  for(int i=0; i < nbrDigits; i++)
    pinMode(digitPins[i], OUTPUT);
  pinMode(inputPin, INPUT);
  pinMode(ledPin, OUTPUT);
}
void loop()
{
  //int value = analogRead(0);


  if ( digitalRead(12) == HIGH)
  { 

    if(debounce(inputPin))
    {
      value = value++; 


    }
    while(digitalRead(12)==LOW){
      showNumber(value);
    }


  }




}
void showNumber( int number)
{
  if(number == 0)
    showDigit( 0, nbrDigits-1) ; // display 0 in the rightmost digit
  else
  {
    // display the value corresponding to each digit
    // leftmost digit is 0, rightmost is one less than the number of places
    for( int digit = nbrDigits-1; digit >= 0; digit--)
    {
      if(number > 0)
      {
        showDigit( number % 10, digit) ;
        number = number / 10;
      }
    }
  }
}
// Displays given number on a 7-segment display at the given digit position
void showDigit( int number, int digit)
{
  delay(2);
  digitalWrite( digitPins[digit], HIGH );
  for(int segment = 1; segment < 8; segment++)
  {
    boolean isBitSet = bitRead(numeral[number], segment);
    // isBitSet will be true if given bit is 1
    isBitSet = ! isBitSet; // remove this line if common cathode display
    digitalWrite( segmentPins[segment], isBitSet);
  }
  delay(2);
  digitalWrite( digitPins[digit], LOW );
}
  return state;

This will never get called. Why is it STILL here?

I want that if I press the button, no matter how long, it only counts one time.

Then, you need to determine when the switch is now pressed and was not pressed last time. Just like in the state change detection example, as has already been mentioned.

Now that the code is readable, you need to summarize what it is doing that you don't want, or not doing that you do want, after removing all the issues that you've been told how to address.

I made another modification and now it counts onu time for press, like I wanted and it shows the number when I let go the button, but the number flickers when I don't press the button.

int value = 0;
const int inputPin = 12; // the number of the input pin
const int ledPin = 13; // the number of the output pin
const int debounceDelay = 50;
const int numeral[10] = {
  //ABCDEFG /dp
  B11111100, // 0
  B01100000, // 1
  B11011010, // 2
  B11110010, // 3
  B01100110, // 4
  B10110110, // 5
  B00111110, // 6
  B11100000, // 7
  B11111110, // 8
  B11100110, // 9
};
// pins for decimal point and each segment
// dp,G,F,E,D,C,B,A
const int segmentPins[] = { 
  4,7,8,6,5,3,2,9};
const int nbrDigits= 2; // the number of digits in the LED display
//dig 1 2 3 4
const int digitPins[nbrDigits] = {
  10, 11};

boolean debounce(int pin)
{
  boolean state;
  boolean previousState;
  previousState = digitalRead(pin); // store switch state
  for(int counter=0; counter < debounceDelay; counter++)
  {
    delay(1); // wait for 1 millisecond
    state = digitalRead(pin); // read the pin
    if( state != previousState)
    {
      counter = 0; // reset the counter if the state changes
      previousState = state; // and save the current state
    }
  }
  // here when the switch state has been stable longer than the debounce period

  if(state == LOW) // LOW means pressed (because pull-ups are used)
    return true;
  else
    return false;

}

void setup()
{
  for(int i=0; i < 8; i++)
    pinMode(segmentPins[i], OUTPUT); // set segment and DP pins to output
  for(int i=0; i < nbrDigits; i++)
    pinMode(digitPins[i], OUTPUT);
  pinMode(inputPin, INPUT);
  pinMode(ledPin, OUTPUT);
}
void loop()
{
  //int value = analogRead(0);


  if ( digitalRead(12) == HIGH)
  { 

    if(debounce(inputPin))
    {
      value = value++; 


    }
    while(digitalRead(12)==LOW){
      showNumber(value);
    }
    showNumber(value);

  }


}
void showNumber( int number)
{
  if(number == 0)
    showDigit( 0, nbrDigits-1) ; // display 0 in the rightmost digit
  else
  {
    // display the value corresponding to each digit
    // leftmost digit is 0, rightmost is one less than the number of places
    for( int digit = nbrDigits-1; digit >= 0; digit--)
    {
      if(number > 0)
      {
        showDigit( number % 10, digit) ;
        number = number / 10;
      }
    }
  }
}
// Displays given number on a 7-segment display at the given digit position
void showDigit( int number, int digit)
{
  delay(2);
  digitalWrite( digitPins[digit], HIGH );
  for(int segment = 1; segment < 8; segment++)
  {
    boolean isBitSet = bitRead(numeral[number], segment);
    // isBitSet will be true if given bit is 1
    isBitSet = ! isBitSet; // remove this line if common cathode display
    digitalWrite( segmentPins[segment], isBitSet);
  }
  delay(2);
  digitalWrite( digitPins[digit], LOW );
}
if ( digitalRead(12) == HIGH)
  { 
    if(debounce(inputPin))
    {
      value = value++; 
    }
    while(digitalRead(12)==LOW)
    {
      showNumber(value);
    }
    showNumber(value);
  }

After deleting the useless blank lines, and putting all the { on their own lines, this is what you have in loop(). The while loop will only be called if the pin state is HIGH. It does nothing if the pin state is not LOW. Why, therefore, is the while loop even there.

value++ is equivalent to value = value + 1, so value = value++ is equivalent to value = value = value + 1, which clearly looks silly.

Showing the number ought to have NOTHING to do with determining what number to show. I think that when you divorce the two, you'll find that flickering ceases to be an issue.

You might want to comment on how the switch is actually wired, too.

If I take out the while loop, the number shown flickers and it doesn't count some presses. Right now the only issue I have is that when I let go the button, the number dissapears, although it keeps the counting good.
I did my wiring following the diagrams in the first post, now I post a picture of my circuit.

This is my code right now:

int value = 0;
const int inputPin = 12; // the number of the input pin
const int ledPin = 13; // the number of the output pin
const int debounceDelay = 50;
const int numeral[10] = {
  //ABCDEFG /dp
  B11111100, // 0
  B01100000, // 1
  B11011010, // 2
  B11110010, // 3
  B01100110, // 4
  B10110110, // 5
  B00111110, // 6
  B11100000, // 7
  B11111110, // 8
  B11100110, // 9
};
// pins for decimal point and each segment
// dp,G,F,E,D,C,B,A
const int segmentPins[] = { 
  4,7,8,6,5,3,2,9};
const int nbrDigits= 2; // the number of digits in the LED display
//dig 1 2 3 4
const int digitPins[nbrDigits] = {
  10, 11};

boolean debounce(int pin)
{
  boolean state;
  boolean previousState;
  previousState = digitalRead(pin); // store switch state
  for(int counter=0; counter < debounceDelay; counter++)
  {
    delay(1); // wait for 1 millisecond
    state = digitalRead(pin); // read the pin
    if( state != previousState)
    {
      counter = 0; // reset the counter if the state changes
      previousState = state; // and save the current state
    }
  }
  // here when the switch state has been stable longer than the debounce period

  if(state == LOW) // LOW means pressed (because pull-ups are used)
    return true;
  else
    return false;

}

void setup()
{
  for(int i=0; i < 8; i++)
    pinMode(segmentPins[i], OUTPUT); // set segment and DP pins to output
  for(int i=0; i < nbrDigits; i++)
    pinMode(digitPins[i], OUTPUT);
  pinMode(inputPin, INPUT);
  pinMode(ledPin, OUTPUT);
}
void loop()
{
  //int value = analogRead(0);


  if ( digitalRead(12) == HIGH)
  { 
    if(debounce(inputPin))
    {
      value = value++; 
    }
    while(digitalRead(12)==LOW){
      showNumber(value);
    }
  }
}



void showNumber( int number)
{
  if(number == 0)
    showDigit( 0, nbrDigits-1) ; // display 0 in the rightmost digit
  else
  {
    // display the value corresponding to each digit
    // leftmost digit is 0, rightmost is one less than the number of places
    for( int digit = nbrDigits-1; digit >= 0; digit--)
    {
      if(number > 0)
      {
        showDigit( number % 10, digit) ;
        number = number / 10;
      }
    }
  }
}
// Displays given number on a 7-segment display at the given digit position
void showDigit( int number, int digit)
{
  delay(2);
  digitalWrite( digitPins[digit], HIGH );
  for(int segment = 1; segment < 8; segment++)
  {
    boolean isBitSet = bitRead(numeral[number], segment);
    // isBitSet will be true if given bit is 1
    isBitSet = ! isBitSet; // remove this line if common cathode display
    digitalWrite( segmentPins[segment], isBitSet);
  }
  delay(2);
  digitalWrite( digitPins[digit], LOW );
}

And forgive me if I'm being slow with this topic, I'm new with the Arduino and his programming and english is not my first language.

This is my actual circuit following the diagrams.

Debouncing a pin and detecting the change in state are two completely separate activities. You are only doing one. You MUST do both.

  if ( digitalRead(12) == HIGH)
  { 
    if(debounce(inputPin))
    {
      value = value++; 
    }
    while(digitalRead(12)==LOW){
      showNumber(value);
    }
  }

You should be calling showNumber() on every pass through loop() UNCONDITIONALLY.

Maybe is a dumb question, but when you say that are you refering to this?:

void loop()
{
  showNumber(value);
  if ( digitalRead(12) == HIGH)
  { 
    if(debounce(inputPin))
    {
      value = value++;       
    }
  }  
}

If is that what you mean, well, the numbers flicker when I let the button go.

If is that what you mean, well, the numbers flicker when I let the button go.

Does this cause flicker, or not:

void loop()
{
  showNumber(47);
}

If not, then the problem is with the debounce() function. If so, then the problem is with the showNumber() function.

It doesn't flicker that way, so the problem is the debounce function. what should I fix? :disappointed_relieved: