Switching Things On And Off With An Arduino: Toggle Switch

What if we do not want to hold the button switched closed to keep the LED on. What if we want to press once to turn on the LED and press again to turn it off.

To do this we need to know when the button switch is pressed but was not pressed before (we have already done this in the previous example) and we also need to know the status of the LED; is it on or is it off? We can keep track of the LED status by adding a new variable LEDstatus. LEDstatus will be LOW for off and HIGH for on.

Circuit

Pin D10 – 330 ohm resistor + LED to GND
Pin D2 – 10K ohm resistor to GND + push button switch to VCC

Sketch: Single push button switch toggle function

//  Sketch: Single button switch toggle function
//  www.martyncurrey.com
//
//  An  example of using a button switch as a toggle switch to turn an LED on or off
//
//  Pins
//  D10 to resister and LED
//  D2 to push button switch
//  
 
// Define the pins being used
int pin_LED = 10;
int pin_switch = 2;
 
// variables to hold the new and old switch states
boolean oldSwitchState = LOW;
boolean newSwitchState = LOW;
 
boolean LEDstatus = LOW;
 
void setup() 
{
    Serial.begin(9600);
    Serial.print("Sketch:   ");   Serial.println(__FILE__);
    Serial.print("Uploaded: ");   Serial.println(__DATE__);
    Serial.println(" ");
 
    pinMode(pin_LED, OUTPUT);  
    digitalWrite(pin_LED,LOW); 
 
    pinMode(pin_switch, INPUT); 
}
 
void loop()
{
    newSwitchState = digitalRead(pin_switch);
 
    if ( newSwitchState != oldSwitchState ) 
    {
       // has the button switch been closed?
       if ( newSwitchState == HIGH )
       {
           if ( LEDstatus == LOW ) { digitalWrite(pin_LED, HIGH);  LEDstatus = HIGH; }
           else                    { digitalWrite(pin_LED, LOW);   LEDstatus = LOW;  }
       }
       oldSwitchState = newSwitchState;
    }   
}

You may notice that the value of LEDstatus is the same as the value assigned to the LED pin. This means we could use it to set the pin and do away with one of the digitalWrite() statements.

if ( newSwitchState == HIGH )
{
      if ( LEDstatus == LOW ) {  LEDstatus = HIGH; } else {  LEDstatus = LOW; } // flip the value of LEDstatus
      digitalWrite(pin_LED, LEDstatus);  
}

Upload the sketch and give it a go. It works, sort of… You will probably notice that the LED turns on and off but not reliably. Sometimes, when you try to turn on the LED it will turn off straight away, and, when you try to turn it off, it will turn back on straight away. This is due to what they call bounce or switch bounce.

Switch Bounce

With many kinds of switches, you do not get a clean closed contact, you get a very short transition period where the switch very quickly closes, opens, closes, opens and closes before settling down and becoming fully closed. The contacts bounce a bit before becoming fully closed. Hence the name switch bounce.

There are many solutions, both hardware and software, called debouncing. Some fairly simple, some more complex. For simple push button switches where super fast speed is not critical I generally use a very simple technique of sampling the pin several times and if all results are the same I can be confident I have a clean reading. Adding a short delay also helps.

newSwitchState1 = digitalRead(pin_switch);
delay(1);
newSwitchState2 = digitalRead(pin_switch);
delay(1);
newSwitchState3 = digitalRead(pin_switch);

I changed newSwitchState to newSwitchState1 and added newSwitchState2 and newSwitchState3.

This is not an original solution. I saw it somewhere on the internet a while ago and found it worked very well. Unfortunately, I cannot remember where I first saw it.

Sketch: Single button switch toggle function with added debounce

Let’s try adding the new anti-bounce code. Upload the new sketch below and try again. This time you should get much cleaner and reliable on and offs.

//  Sketch: Single push button switch toggle function with added debounce
//  www.martyncurrey.com
//
//  An  example of using a button switch as a toggle switch to turn an LED on or off
//  now with a simple debounce
//
//  Pins
//  D10 to resister and LED
//  D2 to push button switch
//  
 
// Define the pins being used
int pin_LED = 10;
int pin_switch = 2;
 
// variables to hold the new and old switch states
boolean oldSwitchState = LOW;
boolean newSwitchState1 = LOW;
boolean newSwitchState2 = LOW;
boolean newSwitchState3 = LOW;
 
boolean LEDstatus = LOW;
 
 
void setup() 
{
    Serial.begin(9600);
    Serial.print("Sketch:   ");   Serial.println(__FILE__);
    Serial.print("Uploaded: ");   Serial.println(__DATE__);
    Serial.println(" ");
 
    pinMode(pin_LED, OUTPUT);  
    digitalWrite(pin_LED,LOW); 
 
    pinMode(pin_switch, INPUT); 
}
 
void loop()
{
    newSwitchState1 = digitalRead(pin_switch);
    delay(1);
    newSwitchState2 = digitalRead(pin_switch);
    delay(1);
    newSwitchState3 = digitalRead(pin_switch);
 
    // if all 3 values are the same we can continue
    if (  (newSwitchState1==newSwitchState2) && (newSwitchState1==newSwitchState3) )
    {
 
        if ( newSwitchState1 != oldSwitchState ) 
        {
 
           // has the button switch been closed?
           if ( newSwitchState1 == HIGH )
           {
               if ( LEDstatus == LOW ) { digitalWrite(pin_LED, HIGH);  LEDstatus = HIGH; }
               else                    { digitalWrite(pin_LED, LOW);   LEDstatus = LOW;  }
           }
           oldSwitchState = newSwitchState1;
        }  
    }
}