1

I'm using JChristensen's Button Library to debounce my buttons and provide extra functionality. I'm trying to use his press & hold function to do something if the button is pressed and held for greater than 2 seconds. If it is just pressed momentarily it should do something else. His example use switch cases, and I couldn't get it to work. Here is my example that currently doesn't work.

    #include <Button.h>
    #include <SPI.h>
    #include <printf.h>

    // Keypress state setup
    byte clearPin = 16; // Clear pin

    #define PULLUP true
    #define INVERT true // Since the pullup resistor will keep the pin high  unless the
    #define DEBOUNCE_MS 20 // A debounce time of 20 milliseconds usually works well for tactile button switches.
    #define LONG_PRESS 2000 // We define a "long press" to be 2000 milliseconds.
    unsigned long ms; // The current time from millis()
    Button clearBtn(clearPin, PULLUP, INVERT, DEBOUNCE_MS); // Declare the button
    int score=1;

void setup () 
{
  pinMode(16, INPUT_PULLUP); // Pin for clear button
  Serial.begin(9600); // Radio Setup
}    

void loop()
{
 clearScore(); // sets both home and away scores to 0 or enters settings menu
}

void clearScore()
{
  ms = millis(); //record the current time
  clearBtn.read(); // Read the button

  if (clearBtn.pressedFor(2000)) {
    // Enter settings menu
     Serial.println("Settings Menu");
     while (clearBtn.read()!=1) {

     } // End While
   return; // Hopefully not proceed down to the next if
  }
  if (clearBtn.wasReleased() && !clearBtn.pressedFor(2000)) {
    score=0;
    Serial.println("Clearing Scores");
    delay(50); 
  }

}

Can anyone help please? My serial output repeats "Settings Menu" over and over. Once I let go of the button variable1 always gets set to 0.

  • No it was an example of what my code was. I was hoping for someone to write something generic and I'd learn and adapt from it. In any event, I have included the full code now. – Meretrix Oct 17 '15 at 2:55
  • user1229925, I edited the question (selected code and pressed ctrl-k to code-format it; changed word 'Entering' to 'Setting' after the code; crossed out variable1, not knowing what it should be. Does the "Clearing Scores" msg ever appear? – James Waldby - jwpat7 Oct 17 '15 at 3:12
  • So it's supposed to work like this: 1) hold button down for 2 seconds to enter settings menu. While in settings menu ill code other stuff. STAY in settings menu until the clear button is pressed momentarily again. Once you press clear button again from being in the settings menu, the score should NOT be reset, and it should just return to the main loop. 2) if the clear button was not pressed for more than 2 seconds, just clear the score. Does that help @jwpat7 ? – Meretrix Oct 17 '15 at 13:43
  • My earlier comment about the action of the code had numerous incorrect parts, so I deleted it. See my answer below. – James Waldby - jwpat7 Oct 17 '15 at 15:43
0

The loop() and clearScore() code that you have is like the following.

void loop() {
  clearScore(); // sets both home and away scores to 0 or enters settings menu
}
void clearScore() {
  ms = millis(); //record the current time
  clearBtn.read(); // Read the button
  if (clearBtn.pressedFor(2000)) {
    // Enter settings menu
    Serial.println("Settings Menu");
    while (clearBtn.read()!=1) {
      // do stuff
    } // End While
    return; // Don't proceed to next if
  }
  if (clearBtn.wasReleased() && !clearBtn.pressedFor(2000)) {
    score=0;
    Serial.println("Clearing Scores");
    delay(50); 
  }
}

When you reset the Arduino and then hold down the clearBtn, clearScore() will be called repeatedly. clearBtn.pressedFor(2000) will not be satisfied during the first two seconds of holding the button down, and clearBtn.wasReleased() will not be satisfied either, so clearScore() will do nothing during the first two seconds.

After the first two seconds, "Settings Menu" will be sent repeatedly: clearBtn.pressedFor(2000) is true, so the first if succeeds each time clearScore() runs, and it will run repeatedly because it is called from loop(). The while test, clearBtn.read()!=1 [which in more-idiomatic C would be written as !clearBtn.read()] fails until the clearBtn is released, so the while loop does nothing. Also, clearBtn.wasReleased() will be false, so the other if does nothing.

When the button finally is released, clearBtn.pressedFor(2000) goes false, so the first if fails and the second executes one time.

Here is some code that should act more like what you want, as expressed in your comment,

It's supposed to work like this: 1) hold button down for 2 seconds to enter settings menu. While in settings menu I'll code other stuff. Stay in settings menu until the clear button is pressed momentarily again. Once you press clear button again from being in the settings menu, the score should NOT be reset, and it should just return to the main loop. 2) if the clear button was not pressed for more than 2 seconds, just clear the score.

void clearScore() {
  ms = millis(); //record the current time

  while (clearBtn.read()) {
    if (clearBtn.pressedFor(2000)) {
      Serial.println("Settings Menu"); // Announce Settings menu
      while (clearBtn.read()) {}       // Await button release
      while (!clearBtn.read()) {       // Await button press
        // do  Settings menu stuff here
        // (possibly wait for clearBtn release, to 
        // avoid immediately clearing score again)
      }
    }
    return;
  }

  if (clearBtn.wasReleased()) { // See if released, after short press
    score=0;
    Serial.println("Clearing Scores");
    delay(50); 
  }
}

Edit edit: To avoid resetting the score at every settings exit, in the above code replace

        // (possibly wait for clearBtn release, to 
        // avoid immediately clearing score again)
      }
    }

with

      }
    }
    while (clearBtn.read()) {} // wait for the settings-exit clearBtn release
    clearBtn.read(); // Do another read to avoid clearing score on next clearScore()

That is, right before the return, wait for clearBtn release, and read it again to be sure later reads won't register a release. The latter read might not be needed, because clearScore() does a read when it tests the first while condition; you could experiment.

  • I think 2 seconds is way too long; half a second might be a more reasonable transition from ordinary press to long press. – James Waldby - jwpat7 Oct 17 '15 at 15:56
  • Wow. This works great! Thank you for the thoughtful explanation next to everything. It unfortunately resets the score every time you exit settings, but other than that I'm much closer then before. How do I ever repay you. – Meretrix Oct 18 '15 at 11:51
  • See edit about avoiding that reset. Feel free to accept answer (click some green button) and upvote. – James Waldby - jwpat7 Oct 18 '15 at 20:12
  • That edit at the end didn't end up working. Can I paypal you to help finish? – Meretrix Oct 19 '15 at 2:50
  • I'm too busy to accept more work at the moment. I imagine the problem at the end was the two lines being before } } instead of after; see re-edit. – James Waldby - jwpat7 Oct 19 '15 at 14:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.