switch detection or timing(?) problem

Guys

In a sketch I have written, I use 4 switches to determine both the game level and # of players.
There is a 5 sec window to make the selections. If I press, say, button 1, that sets level 1 & 1 player. Further presses, up to 4, increments the # of players; button 3, sets game level 3 with addition presses increasing # of players.

No matter how I tried, pressing any of the 4 buttons caused it to rip through and select the game level correctly, and immediately selects 2, then 3, then 4 players.

Switch bounce? Checked with the DSO, and the worst was <10uS. That should not have caused a problem, as the s/w flip-flop would block that.

Started to include Serial.println to monitor what the hell was going on. Doing a print out of the Serial Monitor data showed it working correctly. It only incremented the players when the switch was pressed.

Commented out the Serial.prints and it did everything on the first press, once again.

I tried delay(20) immediately after the first button press, to see if that did anything. No difference.

Here is the code, with the Serial,prints commented out.

const byte switchpin[] = {2, 4, 6, 8};
const byte leds[] = {3, 5, 7, 9};

byte Players = 0;
byte Game_Level = 0;

byte First_Button_Pressed_Flag = 0;
byte button_count_Flag = 0;
byte Start_Flag = 0;

bool currentbuttonstate = true;
bool previousbuttonstate = true;

unsigned long Test_Millis = 0;
unsigned long LED_Millis = 0;

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

  pinMode(switchpin[0], INPUT_PULLUP);
  pinMode(switchpin[1], INPUT_PULLUP);
  pinMode(switchpin[2], INPUT_PULLUP);
  pinMode(switchpin[3], INPUT_PULLUP);
  pinMode(leds[0], OUTPUT);
  pinMode(leds[1], OUTPUT);
  pinMode(leds[2], OUTPUT);
  pinMode(leds[3], OUTPUT);
  //      LED_Millis = millis();
}

void loop()
{
  if (Start_Flag == 0)
  {
    digitalWrite(leds[0], HIGH);
    for (int i = 0; i <= 3; i++) digitalWrite(leds[i], HIGH);
    Start_Flag = 1;
    Test_Millis = millis();
  }
  if (millis() - Test_Millis <= 5000ul)
  {

    for (byte i = 0; i < 4; i++)
    {
      if ((digitalRead(switchpin[i]) == LOW) && (currentbuttonstate == true))                         // If a button is pressed
      {
//             Delay(20);
/*            Serial.println("Here1");
              Serial.print("i = ");
              Serial.println(i);
              Serial.println("Button pressed");
              Serial.print(currentbuttonstate);
              Serial.print("  ");
              Serial.print(previousbuttonstate);
              Serial.println("  ");                        */
        if (First_Button_Pressed_Flag == 0)                      // Have I been here
        {
          Game_Level = i;                                 // This gives me the Select Game Level #, 0-3
          First_Button_Pressed_Flag = 1;                     // I've been here
/*           Serial.println("Here2");
            Serial.print("i = ");
            Serial.println(i);
            Serial.print(currentbuttonstate);
            Serial.print("  ");
            Serial.print(previousbuttonstate);
            Serial.println("  ");                     */
        }

        currentbuttonstate = digitalRead(switchpin[i]);
        delay(10);
/*             Serial.println("Here3");
            Serial.print("i = ");
            Serial.println(i);
            Serial.print(currentbuttonstate);
            Serial.print("  ");
            Serial.print(previousbuttonstate);
            Serial.println("  ");                  */

        if (currentbuttonstate == 0 && previousbuttonstate == 1)          //%%%%%%
        {
          //                                 Serial.println("Flip");
          Players++;
          Serial.print("Players = ");
          Serial.println(Players);
          Serial.print("Game Level = ");
          Serial.println(Game_Level);
          Serial.println();
          Serial.println();
          previousbuttonstate = 0;
          //                                 delay(50);
          if (Players >= 4)
          {
            Serial.println("Here at end");
            while (1);
          }
/*                Serial.println("Here4");
                Serial.print("i = ");
                Serial.println(i);
                Serial.print(currentbuttonstate);
                Serial.print("  ");
                Serial.print(previousbuttonstate);
                Serial.println("  ");                  */

        }                                                              //%%%%%%%%%
      }

      if ((digitalRead(switchpin[i]) == HIGH) && (previousbuttonstate == false))                         // If a button is released
      {
        currentbuttonstate = digitalRead(switchpin[i]);
        previousbuttonstate = 1;
/*                Serial.println("Here5");
                 Serial.print("i = ");
                 Serial.println(i);
                 Serial.println("Button pressed");
                 Serial.print(currentbuttonstate);
                 Serial.print("  ");
                 Serial.print(previousbuttonstate);
                 Serial.println("  ");                     */
      }
/*                  Serial.println("Here6");
                  Serial.print("i = ");
                  Serial.println(i);
                  Serial.print(currentbuttonstate);
                  Serial.print("  ");
                  Serial.print(previousbuttonstate);
                  Serial.println("  ");                     */
    }

  }
}

Any ideas as to why it only works while the Serial.print lines are in?

TIA

Fof

Amended the title.

The Serial.print(...) lines slow this code down sufficiently so that it seems to work correctly.

You need to detect when a switch changes from released to pressed (or changes from pressed to released), not detecting that the switch is pressed.

See the Arduino IDE for the "File | Examples | 02.Digital | StateChangeDetection" example. Learn from it.

@vaj4088

Both switch states are checked

if ((digitalRead(switchpin[i]) == LOW) && (currentbuttonstate == true))          // If a button is pressed

and

if ((digitalRead(switchpin[i]) == HIGH) && (previousbuttonstate == false))      // If a button is released

As you say, the Serial.prints slow things down so that it works, but WHY won't it do things correctly without them?
Fof

Because when the loop function repeats you haven't got your finger off the button yet and it is treating that as a second press. You need to look at the example cited in reply #1 and code so that you only react ONCE to each press of the button and don't react to the button being pressed again until you've seen it being unpressed.

There is a difference between these two lines that goes beyond the LOW and HIGH and beyond the peculiar comments:

      if ((digitalRead(switchpin[i]) == LOW) && (currentbuttonstate == true))                         // If a button is pressed
        if (currentbuttonstate == 0 && previousbuttonstate == 1)          //%%%%%%

If you have an array called switchpin, then you need another array (perhaps called previousbuttonstate) to keep the previous state of each button. You do not want the previous state of a button to affect what happens with some other button. (Actually, I would be tempted to use an array of struct but that is a more advanced topic.) Variable names are usually camel case (that means that all words are capitalized except the first), so "currentbuttonstate" should be "currentButtonState" and "switchpin" should be "switchPin" and "previousbuttonstate" should be "previousButtonState".

The condition "x==true" has the same effect as the condition "x".

It is somewhat confusing that
sometimes LOW and HIGH are used (which are the only documented values for digitalRead(...)),
sometimes 0 and 1 are used, and
sometimes true and false are used.
0, 1, true, and false currently work but that is not how the documentation shows to do it.

@vaj4088 & DeltaG

Thanks guys.

Yes the example works, as one would expect :slight_smile: .
Now to shoe-horn my stuff into it.

I was sure I had closed all the doors behind me. Will have to revisit my attempt and see what door I left ajar.

Regards

Fof