Touchy Program - How do I fix?

I'm pretty new to programming in C, so I tried to write a program to use with a 7 segment display, and the following is what I came up with. the only problem is that it is pretty touchy, and doesn't quite do what the button presses should be telling it to do every time, although sometimes it works with 1 to 3 button presses. Any suggestions would be greatly appreciated.

/*While button2 is pressed (HIGH), the program counts
the presses (HIGH) of button, then displays the count
number with a 7 Segment Display*/

//Button Count Variables
int state = LOW;
int lastState = LOW;
int count = 10;

//7 Segment Display Pins
int segF = 4;
int segG = 5;
int segE = 6;
int segD = 7;
int segA = 8;
int segB = 9;
int segC = 10;

//Button Pins
int button = 11;
int button2 = 12;

void setup()
  {
    Serial.begin(9600);
    pinMode(button, INPUT);
    pinMode(button2, INPUT);
    state = digitalRead(button);
    pinMode(segA, OUTPUT);
    pinMode(segB, OUTPUT);
    pinMode(segC, OUTPUT);
    pinMode(segD, OUTPUT);
    pinMode(segE, OUTPUT);
    pinMode(segF, OUTPUT);
    pinMode(segG, OUTPUT);
    
  }

void loop()
  {
    while(digitalRead(button2) == HIGH)
    {
          
    if (state == HIGH && lastState == LOW)
    {
      count++;
    }
    
    lastState = state;
    state = digitalRead(button);
    }
    
    switch (count)
    {
  case 1:
    //Turns on and off the LEDs on the 7seg to display "1"
    digitalWrite(segA, LOW);
    digitalWrite(segB, HIGH);
    digitalWrite(segC, HIGH);
    digitalWrite(segD, LOW);
    digitalWrite(segE, LOW);
    digitalWrite(segF, LOW);
    digitalWrite(segG, LOW);
    break;
  case 2:
    /*Same as 1, but this displays "2", and so on for the
    rest of these*/
    digitalWrite(segA, HIGH);
    digitalWrite(segB, HIGH);
    digitalWrite(segC, LOW);
    digitalWrite(segD, HIGH);
    digitalWrite(segE, HIGH);
    digitalWrite(segF, LOW);
    digitalWrite(segG, HIGH);
    break;
  case 3:
    digitalWrite(segA, HIGH);
    digitalWrite(segB, HIGH);
    digitalWrite(segC, HIGH);
    digitalWrite(segD, HIGH);
    digitalWrite(segE, LOW);
    digitalWrite(segF, LOW);
    digitalWrite(segG, HIGH);
    break;
  case 4:
    digitalWrite(segA, LOW);
    digitalWrite(segB, HIGH);
    digitalWrite(segC, HIGH);
    digitalWrite(segD, LOW);
    digitalWrite(segE, LOW);
    digitalWrite(segF, HIGH);
    digitalWrite(segG, HIGH);
    break;
  case 5:
    digitalWrite(segA, HIGH);
    digitalWrite(segB, LOW);
    digitalWrite(segC, HIGH);
    digitalWrite(segD, HIGH);
    digitalWrite(segE, LOW);
    digitalWrite(segF, HIGH);
    digitalWrite(segG, HIGH);
    break;
  case 6:
    digitalWrite(segA, HIGH);
    digitalWrite(segB, LOW);
    digitalWrite(segC, HIGH);
    digitalWrite(segD, HIGH);
    digitalWrite(segE, HIGH);
    digitalWrite(segF, HIGH);
    digitalWrite(segG, HIGH);
    break;
  case 7:
    digitalWrite(segA, HIGH);
    digitalWrite(segB, HIGH);
    digitalWrite(segC, HIGH);
    digitalWrite(segD, LOW);
    digitalWrite(segE, LOW);
    digitalWrite(segF, LOW);
    digitalWrite(segG, LOW);
    break;
  case 8:
    digitalWrite(segA, HIGH);
    digitalWrite(segB, HIGH);
    digitalWrite(segC, HIGH);
    digitalWrite(segD, HIGH);
    digitalWrite(segE, HIGH);
    digitalWrite(segF, HIGH);
    digitalWrite(segG, HIGH);
    break;
  case 9:
    digitalWrite(segA, HIGH);
    digitalWrite(segB, HIGH);
    digitalWrite(segC, HIGH);
    digitalWrite(segD, HIGH);
    digitalWrite(segE, LOW);
    digitalWrite(segF, HIGH);
    digitalWrite(segG, HIGH);
    break;
  case 10:
    digitalWrite(segA, HIGH);
    digitalWrite(segB, HIGH);
    digitalWrite(segC, HIGH);
    digitalWrite(segD, HIGH);
    digitalWrite(segE, HIGH);
    digitalWrite(segF, HIGH);
    digitalWrite(segG, LOW);
    break;
  default:
    break;
    }
    
    count = 0;
  }

The circuit you have connected to the 'button' pins would help. Are you using a pulldown resistor ?

I have a 10k resistor connected from ground to the button pins, and the buttons connected to 5v, so when it is pressed, it returns (HIGH), and unpressed returns (LOW).

Is the intended behaviour that nothing happens until the first button is pressed and then the 2nd button increments the number displayed ? So you have to press both buttons to increment the count (the number displayed ?

@pluggy, Yes. When the one button is pressed, it goes into the While loop, while it then counts the button presses of the other button. And when the first button is let go, it should display the number of times I pressed the second button. But it is very touchy, and only seems to work semi-consistently with 1 to 3.

while(digitalRead(button2) == HIGH)
    {
    if (state == HIGH && lastState == LOW)
    {
      count++;
    }
    
    lastState = state;
    state = digitalRead(button);
    }

Do you have an idea how many times this while loop gets executed while you are holding the button2 pin switch down? There is no debouncing of either button happening, so the random results you are seeing are not surprising.

I hadn't though about the number of times affecting how it works, but it aside from interference, it shouldn't count any more or less than what I am pressing, right? I was thinking that a better way of doing this could be to use interrupts, and basically use one button to count, while the second button actually changes the displayed number to the correct number of presses. so that instead of cycling, a desired number of presses could be achieved, and then displayed.

Here is the program rewritten and modified with interrupts. The first button (interrupt 0) counts how many times it is pressed, and stores that to the variable countPress. Then when the second button (interrupt 1) is pressed, it should display the correct number of presses on the first button. The buttons do not have to be pressed at the same time at all.

int countPress = 0;

//7 Segment Display Pins
int segF = 4;
int segG = 5;
int segE = 6;
int segD = 7;
int segA = 8;
int segB = 9;
int segC = 10;

//Button Pins
int button = 2;
int button2 = 3;

void setup()
  {
    Serial.begin(9600);
    attachInterrupt(0, count, RISING);
    attachInterrupt(1, disp, RISING);
    pinMode(segA, OUTPUT);
    pinMode(segB, OUTPUT);
    pinMode(segC, OUTPUT);
    pinMode(segD, OUTPUT);
    pinMode(segE, OUTPUT);
    pinMode(segF, OUTPUT);
    pinMode(segG, OUTPUT);
    
  }

void loop()
  {
    
  }

void count()
  {
    countPress = ++countPress;
  }

void disp()
  {
    switch (countPress)
    {
  case 1:
    //Turns on and off the LEDs on the 7seg to display "1"
    digitalWrite(segA, LOW);
    digitalWrite(segB, HIGH);
    digitalWrite(segC, HIGH);
    digitalWrite(segD, LOW);
    digitalWrite(segE, LOW);
    digitalWrite(segF, LOW);
    digitalWrite(segG, LOW);
    break;
  case 2:
    /*Same as 1, but this displays "2", and so on for the
    rest of these*/
    digitalWrite(segA, HIGH);
    digitalWrite(segB, HIGH);
    digitalWrite(segC, LOW);
    digitalWrite(segD, HIGH);
    digitalWrite(segE, HIGH);
    digitalWrite(segF, LOW);
    digitalWrite(segG, HIGH);
    break;
  case 3:
    digitalWrite(segA, HIGH);
    digitalWrite(segB, HIGH);
    digitalWrite(segC, HIGH);
    digitalWrite(segD, HIGH);
    digitalWrite(segE, LOW);
    digitalWrite(segF, LOW);
    digitalWrite(segG, HIGH);
    break;
  case 4:
    digitalWrite(segA, LOW);
    digitalWrite(segB, HIGH);
    digitalWrite(segC, HIGH);
    digitalWrite(segD, LOW);
    digitalWrite(segE, LOW);
    digitalWrite(segF, HIGH);
    digitalWrite(segG, HIGH);
    break;
  case 5:
    digitalWrite(segA, HIGH);
    digitalWrite(segB, LOW);
    digitalWrite(segC, HIGH);
    digitalWrite(segD, HIGH);
    digitalWrite(segE, LOW);
    digitalWrite(segF, HIGH);
    digitalWrite(segG, HIGH);
    break;
  case 6:
    digitalWrite(segA, HIGH);
    digitalWrite(segB, LOW);
    digitalWrite(segC, HIGH);
    digitalWrite(segD, HIGH);
    digitalWrite(segE, HIGH);
    digitalWrite(segF, HIGH);
    digitalWrite(segG, HIGH);
    break;
  case 7:
    digitalWrite(segA, HIGH);
    digitalWrite(segB, HIGH);
    digitalWrite(segC, HIGH);
    digitalWrite(segD, LOW);
    digitalWrite(segE, LOW);
    digitalWrite(segF, LOW);
    digitalWrite(segG, LOW);
    break;
  case 8:
    digitalWrite(segA, HIGH);
    digitalWrite(segB, HIGH);
    digitalWrite(segC, HIGH);
    digitalWrite(segD, HIGH);
    digitalWrite(segE, HIGH);
    digitalWrite(segF, HIGH);
    digitalWrite(segG, HIGH);
    break;
  case 9:
    digitalWrite(segA, HIGH);
    digitalWrite(segB, HIGH);
    digitalWrite(segC, HIGH);
    digitalWrite(segD, HIGH);
    digitalWrite(segE, LOW);
    digitalWrite(segF, HIGH);
    digitalWrite(segG, HIGH);
    break;
  case 10:
    digitalWrite(segA, HIGH);
    digitalWrite(segB, HIGH);
    digitalWrite(segC, HIGH);
    digitalWrite(segD, HIGH);
    digitalWrite(segE, HIGH);
    digitalWrite(segF, HIGH);
    digitalWrite(segG, LOW);
    break;
  default:
    break;
    }
    
    countPress = 0;
  }

countPress should be declared volatile, so that its value is fetched every time.

    countPress = ++countPress;

As opposed to just countPress++;? Why?

disp() does nothing but reset countPress is countPress is greater than 10. Is that reasonable?

Since there is no debouncing of the buttons, a bounce could cause the interrupt to be fired again before the ISR has finished. Since countPress is an integer, it is possible for it to become corrupted if the ISR fires and suspends the ISR that is running.

This couldn't happen if countPress were a byte. The ISR could fire while the ISR is still running, but it wouldn't corrupt countPress.

In disp(), before you turn any segments on, you should turn them all off. Otherwise, displaying 4 after displaying 3 will look like a 9.

Otherwise, it looks good.

Of course, using interrupts to catch humans pressing buttons is silly. The Arduino loops often enough to catch every button press, no matter how quickly a human presses and releases a button. After all, at 16,000,000 instructions a second, you'd have to be awfully darn fast to get a switch pressed and released before the Arduino noticed.

I recently found out about the debounce library, implemented it, and now I have a program that works the way that the interrupt version should have worked, but this doesn't use interrupts. Here is my code:

#include <Bounce.h>

//Button Count Variable
int count = 0;

//7 Segment Display Pins
int segF = 4;
int segG = 5;
int segE = 6;
int segD = 7;
int segA = 8;
int segB = 9;
int segC = 10;

//Button Pins
int button = 11;
int button2 = 12;

//Bounce Objects
Bounce bouncer = Bounce(button, 25);
Bounce bouncer2 = Bounce(button2, 25);

void setup()
  {
    Serial.begin(9600);
    pinMode(button, INPUT);
    pinMode(button2, INPUT);
    pinMode(segA, OUTPUT);
    pinMode(segB, OUTPUT);
    pinMode(segC, OUTPUT);
    pinMode(segD, OUTPUT);
    pinMode(segE, OUTPUT);
    pinMode(segF, OUTPUT);
    pinMode(segG, OUTPUT);
    
    digitalWrite(segA, HIGH);
    digitalWrite(segB, HIGH);
    digitalWrite(segC, HIGH);
    digitalWrite(segD, HIGH);
    digitalWrite(segE, HIGH);
    digitalWrite(segF, HIGH);
    digitalWrite(segG, LOW);
  }

void loop()
  {
    bouncer.update();  //Updates bouncer
    int value = bouncer.risingEdge();
    
    if (value == HIGH)
      {
        count++;
      }
    
    bouncer2.update();  //Updates bouncer2
    int value2 = bouncer2.risingEdge();
    
    if (value2 == HIGH)
    {
    switch (count)
    {
  case 1:
    //Turns on and off the LEDs on the 7seg to display "1"
    digitalWrite(segA, LOW);
    digitalWrite(segB, HIGH);
    digitalWrite(segC, HIGH);
    digitalWrite(segD, LOW);
    digitalWrite(segE, LOW);
    digitalWrite(segF, LOW);
    digitalWrite(segG, LOW);
    break;
  case 2:
    /*Same as 1, but this displays "2", and so on for the
    rest of these*/
    digitalWrite(segA, HIGH);
    digitalWrite(segB, HIGH);
    digitalWrite(segC, LOW);
    digitalWrite(segD, HIGH);
    digitalWrite(segE, HIGH);
    digitalWrite(segF, LOW);
    digitalWrite(segG, HIGH);
    break;
  case 3:
    digitalWrite(segA, HIGH);
    digitalWrite(segB, HIGH);
    digitalWrite(segC, HIGH);
    digitalWrite(segD, HIGH);
    digitalWrite(segE, LOW);
    digitalWrite(segF, LOW);
    digitalWrite(segG, HIGH);
    break;
  case 4:
    digitalWrite(segA, LOW);
    digitalWrite(segB, HIGH);
    digitalWrite(segC, HIGH);
    digitalWrite(segD, LOW);
    digitalWrite(segE, LOW);
    digitalWrite(segF, HIGH);
    digitalWrite(segG, HIGH);
    break;
  case 5:
    digitalWrite(segA, HIGH);
    digitalWrite(segB, LOW);
    digitalWrite(segC, HIGH);
    digitalWrite(segD, HIGH);
    digitalWrite(segE, LOW);
    digitalWrite(segF, HIGH);
    digitalWrite(segG, HIGH);
    break;
  case 6:
    digitalWrite(segA, HIGH);
    digitalWrite(segB, LOW);
    digitalWrite(segC, HIGH);
    digitalWrite(segD, HIGH);
    digitalWrite(segE, HIGH);
    digitalWrite(segF, HIGH);
    digitalWrite(segG, HIGH);
    break;
  case 7:
    digitalWrite(segA, HIGH);
    digitalWrite(segB, HIGH);
    digitalWrite(segC, HIGH);
    digitalWrite(segD, LOW);
    digitalWrite(segE, LOW);
    digitalWrite(segF, LOW);
    digitalWrite(segG, LOW);
    break;
  case 8:
    digitalWrite(segA, HIGH);
    digitalWrite(segB, HIGH);
    digitalWrite(segC, HIGH);
    digitalWrite(segD, HIGH);
    digitalWrite(segE, HIGH);
    digitalWrite(segF, HIGH);
    digitalWrite(segG, HIGH);
    break;
  case 9:
    digitalWrite(segA, HIGH);
    digitalWrite(segB, HIGH);
    digitalWrite(segC, HIGH);
    digitalWrite(segD, HIGH);
    digitalWrite(segE, LOW);
    digitalWrite(segF, HIGH);
    digitalWrite(segG, HIGH);
    break;
  case 10:
    digitalWrite(segA, HIGH);
    digitalWrite(segB, HIGH);
    digitalWrite(segC, HIGH);
    digitalWrite(segD, HIGH);
    digitalWrite(segE, HIGH);
    digitalWrite(segF, HIGH);
    digitalWrite(segG, LOW);
    break;
  default:
    break;
    }
    
    count = 0;
    }
  }