Detecting the release of a momentary switch?

Hi everyone,

I have a momentary switch connected to an input. It is normally open.

All I want to do is invert a Boolean value when the switch is pressed, so it essentially works as a toggle switch. At the moment, this is how I am doing it:

  // See if we need to turn the lights on or off
  if(digitalRead(pinTailLightSwitch) == HIGH){
    while(digitalRead(pinTailLightSwitch) == HIGH){
      // Do nothing
    };

    if(blnLightsOn==true){
      blnLightsOn=false;
    }
    else{
      blnLightsOn=true;
    }
  }

This is the part in question:

    while(digitalRead(pinTailLightSwitch) == HIGH){
      // Do nothing
    };

The obvious issue with this is that while the input is high, the program halts. I have done this on purpose so that the blnLightsOn variable only inverts once the button is released. If I do it when I see the input as HIGH, it constantly switches between True and False every loop.

Surely there's a smarter method to do this.

Any hints?

Cheers,
Scott

As usual I've invested some brain power and resolved my own issue before wasting anyone's time! Lucky [smiley=smiley.gif]

I'll post my solution here for future reference, feel free to correct me if you see any problems.

So, now with this code...when it sees a HIGH on the pin and it knows the last time it checked it was LOW, it'll invert the Boolean...if not, it leaves it alone. So the switch performs its duty as soon as you press it and allows the program to continue running even if you hold the button down. Nothing happens when you release the button, although I'm sure you could make that happen too if you needed it to.

You need at least these three variables defined for the sketch:

int pinLightSwitch = 12;
boolean blnLightsOn = false;
boolean blnLastLightSwitchState = false;
  // See if we need to turn the lights on or off
  if(digitalRead(pinLightSwitch) == HIGH){
    // Only if the state has changed since the last time we saw a HIGH
    if(blnLastLightSwitchState == false){
      // Invert the blnLightsOn variable for our other routines
      if(blnLightsOn==true){
        blnLightsOn=false;
      }
      else{
        blnLightsOn=true;
      }
      
      // Set LastLightSwitchState to true
      blnLastLightSwitchState = true;
    }
  }
  // If pinLightSwitch is LOW and blnLastLightSwitchState is currently True
  else if(blnLastLightSwitchState == true){
    // Set blnLastLightSwitchState back to false for the next button press
    blnLastLightSwitchState = false;
  }

Enjoy!

Hi scootabug, FWIW, here is a simplified version of your code. It should to the same as that posted above – either version may need additional code to handle de-bouncing.

int pinLightSwitch = 12;
boolean lightsOn = false;
boolean switchArmed = false; 


 // See if we need to turn the lights on or off 
  if(switchArmed && digitalRead(pinLightSwitch) == HIGH){   // toggle when switch is armed and HIGH
    lightsOn = ! lightsOn;  // this toggles the lightsOn state      
    switchArmed = false;
  }
  else if(digitalRead(pinLightSwitch) == LOW)   // Arm switch when it goes low
    switchArmed = true;
  }

Hi Mem.

I was trying to toggle my boolean by using a != operator (not the in the code I had posted though obviously) and it wasn't working. I can see in your code now where I was going wrong, using != as opposed to =!. So it was definitely worth it :wink:

Cheers,
Scott.