Changing a button from push on/push off to on only when button is pressed

I’m back and have another newb question. I have found this program http://arduino.cc/forum/index.php/topic,14479.0.html and think it will work perfectly for my push button truck starter. But I need “ledPin3” to come on after the “holdEvent” but I need “ledPin3” to go off after I release the button.

Oh and I plan on changing the labels from what they are currently to ones that fit my application, ie…“ledPin3” will become “starter” but I just want to make it work first. Thanks Scott Brown.

Is anyone else addicted to these mircorprocessors yet overwhelmed at the amount of info/ideas out there?

Redneckgearhead:
I’m back and have another newb question. I have found this program http://arduino.cc/forum/index.php/topic,14479.0.html and think it will work perfectly for my push button truck starter. But I need “ledPin3” to come on after the “holdEvent” but I need “ledPin3” to go off after I release the button.

Oh and I plan on changing the labels from what they are currently to ones that fit my application, ie…“ledPin3” will become “starter” but I just want to make it work first. Thanks Scott Brown.

Was there a question? If not, go for it, you have our blessing to modify your code as you see fit.

Redneckgearhead:
I’m back and have another newb question. I have found this program http://arduino.cc/forum/index.php/topic,14479.0.html and think it will work perfectly for my push button truck starter. But I need “ledPin3” to come on after the “holdEvent” but I need “ledPin3” to go off after I release the button.

Oh and I plan on changing the labels from what they are currently to ones that fit my application, ie…“ledPin3” will become “starter” but I just want to make it work first. Thanks Scott Brown.

**Is anyone else addicted to these mircorprocessors yet overwhelmed at the amount of info/ideas out there? **

No. No one has ever stated that before in the history of this forum. :smiley:

Lefty

I don't know whether your switch is active-HIGH or active-LOW, so you may need to swap HIGH and LOW below. It's possible to contract this code down to a single statement using the ternary operator, but I think that spelling it out explicitly like this makes the logic more obvious.

if(digitalRead(buttonPin) == HIGH)
{
    digitalWrite(ledPin3, HIGH);
}
else
{
    digitalWrite(ledPin3, LOW);
}

Wow, I need to re-read my posts before posting. There was supposed to be a question in there but I didn't convey it very well. Currently the function in question looks like this

void holdEvent() { ledVal3 = !ledVal3; digitalWrite(ledPin3, ledVal3);

I want to use the "holdEvent" to turn the led on, and have it go off when I release the button. Does that make sense?

Hold the button down, the assigned time passes "holdEvent" and output goes "high" release the button output goes "low"

I've tried to add "if" and "else" but I haven't found anything that will do what I want. Guys I really appreciate the help. I know how frustrating it can be trying to help someone that's clueless.

Simple button latch.

byte buttonPin = 2;
byte LED = 13;

byte buttonState;
byte latch;
byte lastState;

void setup(){
  Serial.begin(9600);
  pinMode(buttonPin, INPUT);
  pinMode(LED, OUTPUT);
}

void loop() {
  buttonState = digitalRead(buttonPin); // read the state of the button

  if(buttonState && buttonState != lastState){ //See if the button state is HIGH, and does not equal the last state
    latch = !latch; // flip the state of the LED
    digitalWrite(LED, latch ? HIGH : LOW); // state of LED according to latch state
    Serial.println(latch); // visual of latch state
  }
  lastState = buttonState; // update last state 
}

HazardsMind: Simple button latch.

byte buttonPin = 2;
byte LED = 13;

byte buttonState; byte latch; byte lastState;

void setup(){   Serial.begin(9600);   pinMode(buttonPin, INPUT);   pinMode(LED, OUTPUT); }

void loop() {   buttonState = digitalRead(buttonPin); // read the state of the button

  if(buttonState && buttonState != lastState){ //See if the button state is HIGH, and does not equal the last state     latch = !latch; // flip the state of the LED     digitalWrite(LED, latch ? HIGH : LOW); // state of LED according to latch state     Serial.println(latch); // visual of latch state   }   lastState = buttonState; // update last state }

Thanks but that latches the output high even after I let up the button, which is what its doing now. I want the "holdEvent" to time out then the output stay high only as long as the input is high?

/* 4-Way Button: Click, Double-Click, Press+Hold, and Press+Long-Hold Test Sketch
By Jeff Saltzman
Oct. 13, 2009

To keep a physical interface as simple as possible, this sketch demonstrates generating four output events from a single push-button.
1) Click: rapid press and release
2) Double-Click: two clicks in quick succession
3) Press and Hold: holding the button down
4) Long Press and Hold: holding the button down for a long time 
*/

#define buttonPin 19 // analog input pin to use as a digital input
#define ledPin1 17 // digital output pin for LED 1
#define ledPin2 16 // digital output pin for LED 2
#define ledPin3 15 // digital output pin for LED 3
#define ledPin4 14 // digital output pin for LED 4

// LED variables
boolean ledVal1 = false; // state of LED 1
boolean ledVal2 = false; // state of LED 2
boolean ledVal3 = false; // state of LED 3
boolean ledVal4 = false; // state of LED 4

//=================================================

void setup() 
{
// Set button input pin
pinMode(buttonPin, INPUT);
digitalWrite(buttonPin, HIGH );
// Set LED output pins
pinMode(ledPin1, OUTPUT);
digitalWrite(ledPin1, ledVal1);
pinMode(ledPin2, OUTPUT);
digitalWrite(ledPin2, ledVal2);
pinMode(ledPin3, OUTPUT); 
digitalWrite(ledPin3, ledVal3);
pinMode(ledPin4, OUTPUT); 
digitalWrite(ledPin4, ledVal4);
}

void loop()
{
// Get button event and act accordingly
int b = checkButton();
if (b == 1) clickEvent();
if (b == 2) doubleClickEvent();
if (b == 3) holdEvent();
if (b == 4) longHoldEvent();
}

//=================================================
// Events to trigger by click and press+hold

void clickEvent() {
ledVal1 = !ledVal1;
digitalWrite(ledPin1, ledVal1);
}

void doubleClickEvent() {
ledVal2 = !ledVal2;
digitalWrite(ledPin2, ledVal2);
}

void holdEvent() {
ledVal3 = !ledVal3;
digitalWrite(ledPin3, ledVal3);
}

void longHoldEvent() {
ledVal4 = !ledVal4;
digitalWrite(ledPin4, ledVal4);
}

Page 2 of code…

/*
MULTI-CLICK: One Button, Multiple Events

Oct 12, 2009
Run checkButton() to retrieve a button event:
Click
Double-Click
Hold
Long Hold
*/

// Button timing variables
int debounce = 20; // ms debounce period to prevent flickering when pressing or releasing the button
int DCgap = 250; // max ms between clicks for a double click event
int holdTime = 2000; // ms hold period: how long to wait for press+hold event
int longHoldTime = 5000; // ms long hold period: how long to wait for press+hold event

// Other button variables
boolean buttonVal = HIGH; // value read from button
boolean buttonLast = HIGH; // buffered value of the button's previous state
boolean DCwaiting = false; // whether we're waiting for a double click (down)
boolean DConUp = false; // whether to register a double click on next release, or whether to wait and click
boolean singleOK = true; // whether it's OK to do a single click
long downTime = -1; // time the button was pressed down
long upTime = -1; // time the button was released
boolean ignoreUp = false; // whether to ignore the button release because the click+hold was triggered
boolean waitForUp = false; // when held, whether to wait for the up event
boolean holdEventPast = false; // whether or not the hold event happened already
boolean longHoldEventPast = false;// whether or not the long hold event happened already

int checkButton()
{ 
int event = 0;
// Read the state of the button
buttonVal = digitalRead(buttonPin);
// Button pressed down
if (buttonVal == LOW && buttonLast == HIGH && (millis() - upTime) > debounce) {
downTime = millis();
ignoreUp = false;
waitForUp = false;
singleOK = true;
holdEventPast = false;
longHoldEventPast = false;
if ((millis()-upTime) < DCgap && DConUp == false && DCwaiting == true) DConUp = true;
else DConUp = false;
DCwaiting = false;
}
// Button released
else if (buttonVal == HIGH && buttonLast == LOW && (millis() - downTime) > debounce) { 
if (not ignoreUp) {
upTime = millis();
if (DConUp == false) DCwaiting = true;
else {
event = 2;
DConUp = false;
DCwaiting = false;
singleOK = false;
}
}
}
// Test for normal click event: DCgap expired
if ( buttonVal == HIGH && (millis()-upTime) >= DCgap && DCwaiting == true && DConUp == false && singleOK == true) {
event = 1;
DCwaiting = false;
}
// Test for hold
if (buttonVal == LOW && (millis() - downTime) >= holdTime) {
// Trigger "normal" hold
if (not holdEventPast) {
event = 3;
waitForUp = true;
ignoreUp = true;
DConUp = false;
DCwaiting = false;
//downTime = millis();
holdEventPast = true;
}
// Trigger "long" hold
if ((millis() - downTime) >= longHoldTime) {
if (not longHoldEventPast) {
event = 4;
longHoldEventPast = true;
}
}
}
buttonLast = buttonVal;
return event;
}

Redneckgearhead: I want the "holdEvent" to time out then the output stay high only as long as the input is high?

When the hold event is detected, record the current time and turn the LED on.

Turn the LED off if the elapsed since since the last hold event exceeds your timeout threshold and the input is no longer high.

I also have this.

const byte buttonPin = 2;     
//const byte ledPin =  11;

int buttonState = 0;
int lastReading = 0;
long onTime=0;
long ResetTime = 1000;
int count, lastcount = 0;

void setup() { 
  //pinMode(ledPin, OUTPUT);      
  pinMode(buttonPin, INPUT);
  Serial.begin(9600);  
}

void loop(){ 
  buttonState = digitalRead(buttonPin);

  if (buttonState == HIGH && lastReading == LOW) {
    onTime = millis();
    count++;
  }

  //Button held
  if (buttonState == HIGH && lastReading == HIGH) { 
    if ((millis() - onTime) > 500 ) {
      delay(200);
      count++;
      lastReading = LOW;
    } 
  }
  
  if(buttonState == LOW && millis() - onTime > ResetTime) count = 0; // reset count after 1 second
  if(count != lastcount) Serial.println(count); // this will ensure only one number gets displayed at once
  
  lastReading = buttonState;
  lastcount = count;
}

HazardsMind: I also have this.

const byte buttonPin = 2;     
//const byte ledPin =  11;

int buttonState = 0; int lastReading = 0; long onTime=0; long ResetTime = 1000; int count, lastcount = 0;

void setup() {   //pinMode(ledPin, OUTPUT);        pinMode(buttonPin, INPUT);   Serial.begin(9600);  }

void loop(){   buttonState = digitalRead(buttonPin);

  if (buttonState == HIGH && lastReading == LOW) {     onTime = millis();     count++;   }

  //Button held   if (buttonState == HIGH && lastReading == HIGH) {     if ((millis() - onTime) > 500 ) {       delay(200);       count++;       lastReading = LOW;     }   }     if(buttonState == LOW && millis() - onTime > ResetTime) count = 0; // reset count after 1 second   if(count != lastcount) Serial.println(count); // this will ensure only one number gets displayed at once     lastReading = buttonState;   lastcount = count; }

how would I integrate this into the program I post above?

Case statements. If count = 5, short hold, and if count = 10 AND buttonState not equal LOW (button was kept held down), long hold.

HazardsMind: Case statements. If count = 5, short hold, and if count = 10 AND buttonState not equal LOW (button was kept held down), long hold.

That aspect works as it should, I hold the button down 2 seconds, the led comes on and stays on after I release the button. Well I don't want it to stay on after I release the button. That is the trouble I am having. It seems like every time I get that one to do what I want, it messes up the rest of the program and the others do not work.

Post your code. Are you using a default case? You can have that turn the led off when nothing is pressed.

Added: My code returns the counter to zero when the button is not pressed, so then you should have a case 0: that set everything off.

HazardsMind: Post your code. Are you using a default case? You can have that turn the led off when nothing is pressed.

Added: My code returns the counter to zero when the button is not pressed, so then you should have a case 0: that set everything off.

/* 4-Way Button:  Click, Double-Click, Press+Hold, and Press+Long-Hold Test Sketch

By Jeff Saltzman
Oct. 13, 2009

To keep a physical interface as simple as possible, this sketch demonstrates generating four output events from a single push-button.
1) Click:  rapid press and release
2) Double-Click:  two clicks in quick succession
3) Press and Hold:  holding the button down
4) Long Press and Hold:  holding the button for a long time 
*/

#define buttonPin 19        // analog input pin to use as a digital input
#define ledPin1 17          // digital output pin for LED 1
#define ledPin2 16          // digital output pin for LED 2
#define ledPin3 15          // digital output pin for LED 3
#define ledPin4 14          // digital output pin for LED 4

// LED variables
boolean ledVal1 = false;    // state of LED 1
boolean ledVal2 = false;    // state of LED 2
boolean ledVal3 = false;    // state of LED 3
boolean ledVal4 = false;    // state of LED 4

//=================================================

void setup() {
    // Set button input pin
    pinMode(buttonPin, INPUT);
    digitalWrite(buttonPin, HIGH );
    // Set LED output pins
    pinMode(ledPin1, OUTPUT);
    digitalWrite(ledPin1, ledVal1);
    pinMode(ledPin2, OUTPUT);
    digitalWrite(ledPin2, ledVal2);
    pinMode(ledPin3, OUTPUT);    
    digitalWrite(ledPin3, ledVal3);
    pinMode(ledPin4, OUTPUT);    
    digitalWrite(ledPin4, ledVal4);
}

void loop() {
    // Get button event and act accordingly
    int b = checkButton();
    if (b == 1) clickEvent();
    if (b == 2) doubleClickEvent();
    if (b == 3) holdEvent();
    if (b == 4) longHoldEvent();
}

//=================================================
// Events to trigger

void clickEvent() {
    ledVal1 = !ledVal1;
    digitalWrite(ledPin1, ledVal1);
}
void doubleClickEvent() {
    ledVal2 = !ledVal2;
    digitalWrite(ledPin2, ledVal2);
}
void holdEvent() {
    ledVal3 = !ledVal3;
    digitalWrite(ledPin3, ledVal3);
}
void longHoldEvent() {
    ledVal4 = !ledVal4;
    digitalWrite(ledPin4, ledVal4);
}

Page 2

//=================================================
//  MULTI-CLICK:  One Button, Multiple Events

// Button timing variables
int debounce = 20;          // ms debounce period to prevent flickering when pressing or releasing the button
int DCgap = 250;            // max ms between clicks for a double click event
int holdTime = 1000;        // ms hold period: how long to wait for press+hold event
int longHoldTime = 3000;    // ms long hold period: how long to wait for press+hold event

// Button variables
boolean buttonVal = HIGH;   // value read from button
boolean buttonLast = HIGH;  // buffered value of the button's previous state
boolean DCwaiting = false;  // whether we're waiting for a double click (down)
boolean DConUp = false;     // whether to register a double click on next release, or whether to wait and click
boolean singleOK = true;    // whether it's OK to do a single click
long downTime = -1;         // time the button was pressed down
long upTime = -1;           // time the button was released
boolean ignoreUp = false;   // whether to ignore the button release because the click+hold was triggered
boolean waitForUp = false;        // when held, whether to wait for the up event
boolean holdEventPast = false;    // whether or not the hold event happened already
boolean longHoldEventPast = false;// whether or not the long hold event happened already

int checkButton() {    
    int event = 0;
    buttonVal = digitalRead(buttonPin);
    // Button pressed down
    if (buttonVal == LOW && buttonLast == HIGH && (millis() - upTime) > debounce)
    {
        downTime = millis();
        ignoreUp = false;
        waitForUp = false;
        singleOK = true;
        holdEventPast = false;
        longHoldEventPast = false;
        if ((millis()-upTime) < DCgap && DConUp == false && DCwaiting == true)  DConUp = true;
        else  DConUp = false;
        DCwaiting = false;
    }
    // Button released
    else if (buttonVal == HIGH && buttonLast == LOW && (millis() - downTime) > debounce)
    {        
        if (not ignoreUp)
        {
            upTime = millis();
            if (DConUp == false) DCwaiting = true;
            else
            {
                event = 2;
                DConUp = false;
                DCwaiting = false;
                singleOK = false;
            }
        }
    }
    // Test for normal click event: DCgap expired
    if ( buttonVal == HIGH && (millis()-upTime) >= DCgap && DCwaiting == true && DConUp == false && singleOK == true && event != 2)
    {
        event = 1;
        DCwaiting = false;
    }
    // Test for hold
    if (buttonVal == LOW && (millis() - downTime) >= holdTime) {
        // Trigger "normal" hold
        if (not holdEventPast)
        {
            event = 3;
            waitForUp = true;
            ignoreUp = true;
            DConUp = false;
            DCwaiting = false;
            //downTime = millis();
            holdEventPast = true;
        }
        // Trigger "long" hold
        if ((millis() - downTime) >= longHoldTime)
        {
            if (not longHoldEventPast)
            {
                event = 4;
                longHoldEventPast = true;
            }
        }
    }
    buttonLast = buttonVal;
    return event;
}

Well I don't want it to stay on after I release the button

Then why are you using latches then? The latch will hold the state until the function is called again. Like I said, have your code return zero when it is not pressed for a certain amount of time or when nothing is pressed at all. Then once you have that, make a case 0 to set that particular LED off, or all of them off.

HazardsMind:

Well I don't want it to stay on after I release the button

Then why are you using latches then? The latch will hold the state until the function is called again. Like I said, have your code return zero when it is not pressed for a certain amount of time or when nothing is pressed at all. Then once you have that, make a case 0 to set that particular LED off, or all of them off.

Lol I didn't write this code I copied it from the link in my op. it will be the perfect code for my needs if I can figure out how to get ledPin3 to go off when the button is released. I really appreciate your help. I know it must be frustrating.

Ok, then try to debug the code, mainly this "int b = checkButton();" to see what it returns when nothing is pressed.

If I did it right…nothing but a constant string of 0’s. even when I pushed the button.