Push-button - Pressed vs. Held

Total n00b here, my apologies. I was wondering how do i get the arduino to recognize wether a button was pressed or is being held down. Basically a modification to the "Reading a push-button" tutorial. In this tutorial If you hold down the push button as it goes through the loop the arduino will see it as a new input everytime. How do I get it to recognize that it is being held from the first LED blink and not to blink the LED again until the button has been released and pushed again? My head just hasn't gotten wrapped around the logic yet.

Thanks!

An interrupt might help:

modified from: http://www.arduino.cc/en/Reference/AttachInterrupt
(put your button between pin 2 and ground)

int pin = 13;
volatile int state = LOW;

void setup()
{
pinMode(pin, OUTPUT);
digitalWrite(2,HIGH); //turn on pullup resistor
attachInterrupt(0, blink, CHANGE); //listen to change on PIN 2
}

void loop()
{
digitalWrite(pin, state);
}

void blink()
{
state = !state;
}

Two loops !
One loops until the button is pressed.
Then you do something.
Then the next loop waits until the button is released.
Then undo something
Go back to the start
:wink:

1 Like

I do this quite simply with an nested if statement. You do need another variable to store the state of the input pin. Vaguely:

if (inputpin == HIGH)
{

  if (buttonstate == 0) {
    do_stuff();
  }

  buttonstate = 1;

} else {
  
  buttonstate = 0;

}

Normally you would put this in the loop() section or someplace else that can poll your inputs. You can see that if the input is high and the buttonstate variable is zero, it will execute the desired function once. Then the button state is set to 1. The next loop around, if the input is still high, buttonstate is still 1, and the desired function won't be executed again. If you loop around and the input is now low, it will set buttonstate to zero. Next time around, if the input goes high again, it will execute the desired function exactly once.

Have we talked about debounce in this thread yet? Don't forget to handle debounce, or your code is going to behave strangely.

-j

Debounce is a modification of my above approach...instead of setting the buttonstate to 1, increment it with bounds checking. Then change the value of the if statement to the desired level of debouncing.

In this case, if a super response speed isn't required you could just use macegr's code with delays of ~10 ms between each loop. It's a very kludgey debounce, but it works with most of push buttons.

You could use either

void loop(){
  [macegr's code]
  delay(10);
}

or if you want other code to run in the background:

long lastCheck = 0;

void loop(){
  if (millis() + 10 > lastCheck){
    [macegr's code]
    lastCheck = millis();
  }
  [other code here]
}

External interrupts require some good debouncing routine with an RC filter and a Schmitt trigger. Not good to jump in that right away for a beginner.

Thanks all for the quick response. Handi and Macegr, I was able to get it to work right with a bit of modifcation to your input.

// Declare Global Variables 
int SolenoidA=3;// choose the pins for the Solenoids
int SolenoidB=2;
int SwitchPin=6;// choose the input pin (for a pushbutton)
int CheckSwitch=1;// variable for reading the current SwitchPin status
int LastCheck=1;// variable for keeping track of SwitchPin

void setup() {
  pinMode(SolenoidA, OUTPUT);// declare Solenoids as output
  pinMode(SolenoidB, OUTPUT);
  pinMode(SwitchPin, INPUT);// declare pushbutton as input
}

void loop(){
CheckSwitch=digitalRead(SwitchPin);
  
if (CheckSwitch == LOW)
{
  if (LastCheck == 1) {
    digitalWrite(SolenoidA,HIGH);
    delay(500);
    digitalWrite(SolenoidA,LOW);
  }
  LastCheck = 0;
} else {
  LastCheck = 1;
} 
delay(250);
}