Switches Tutorial for Arduino, ESP8266 and ESP32

There are two different types of switches:

  • Buttons which are losing connection when released. Buttons power a device as long as the button is pressed.
  • Switches which maintain the state when the switch is pressed to hold the connection as long as the switch is pressed again.

Buttons and switches can have a debouncing problem, that can lead to functional errors in your program. In this article I show you how to fix this problem with a software and a hardware solution.

Switches Thumbnail

Table of Contents

How do Switches Work?

You might wonder why the four-pin switch has 4 legs. How do we have to connect the switch to other components?

If the four-pin switch is not pressed, the pins A and C are connected as well as the pins B and D. If the switch is pressed, the connection of the pins changes and all pins are wired together. Therefore there is no difference if you connect your component you want to switch on pin B or pin D of the other side of the button.

Switch

The following table gives you an overview of all components and parts that I used for this tutorial. I get commissions for purchases made through links in this table.

ComponentAmazon LinkAliExpress Link
Arduino Nano AmazonAliExpress
Arduino Pro Mini AmazonAliExpress
Arduino Uno AmazonAliExpress
Arduino Mega AmazonAliExpress
ESP32 ESP-WROOM-32 AmazonAliExpress
ESP8266 NodeMCU AmazonAliExpress
ESP8266 WeMos D1 Mini AmazonAliExpress
Resistor and LED in Package AmazonAliExpress
Button Kit AmazonAliExpress
Capacitor Kit AmazonAliExpress

Difference between Pull-Down and Pull-Up Resistor Circuits

If you want to connect one or multiple switches to your Arduino, ESP8266 or ESP32 microcontroller you have to use a digital I/O pin to read the current state of the switch or button. Now the question is how to connect the second pin of the switch? Do you have to connect the second pin to the power supply or to ground?

The answer to this question depends on your objective and also you have to add a resistor in the circuit. Otherwise when the switch is open, the digital pin is not connected to GND or to 5V and the pin state would be undefined.

There are two different setups how the resistor is added to the circuit and how the second pin of the switch is connected.

  • Add a pull-down resistor when the signal should be LOW if the switch is open
  • Add a pull-up resistor if the signal should be HIGH if the switch is open. 

The following section describes the difference between the pull-down resistor and the pull-up resistor and shows how to wire all components with different Arduino, ESP8266 and ESP32 microcontroller boards.

If you create a program, this program is independent of the difference in the circuit if you use a pull-down or a pull-up resistor.

Setup of a Pull-Down Circuit with a Resistor

The following circuit shows the pull-down wiring between an Arduino Uno, the resistor and a button. The button is connected to the power supply and the digital pin. The resistor is connected to the same digital pin and ground.

Pull Down Resistor Circuit
Wiring Pull Down Resistor Arduino Nano
Wiring Pull Down Resistor Arduino Nano

For more information about the Arduino Nano, visit the Arduino Nano Tutorial.

Wiring Pull Down Resistor Arduino Pro Mini
Wiring Pull Down Resistor Arduino Pro Mini
Wiring Pull Down Resistor Arduino Uno
Wiring Pull Down Resistor Arduino Uno

For more information about the Arduino Uno, visit the Arduino Uno Tutorial.

Wiring Pull Down Resistor Arduino Mega
Wiring Pull Down Resistor Arduino Mega

For more information about the Arduino Mega, visit the Arduino Mega Tutorial.

Wiring Pull Down Resistor ESP32 ESP-WROOM-32
Wiring Pull Down Resistor ESP32 ESP-WROOM-32
Wiring Pull Down Resistor ESP8266 NodeMCU
Wiring Pull Down Resistor ESP8266 NodeMCU
Wiring Pull Down Resistor ESP8266 WeMos D1 Mini
Wiring Pull Down Resistor ESP8266 WeMos D1 Mini

When the button is not pressed, the pull down-resistor permits a small current to flow between the digital pin and GND. Therefore the digital input is pulled down to LOW. If the button is pressed, the digital pin is connected to the 5V power supply of the Arduino Uno and therefore the digital input is HIGH.

Setup of a Pull-Up Circuit with a Resistor

In the case of a pull-up resistor circuit, the pull up-resistor connect the digital pin and 5V. Therefore the digital input is pulled up to 5V. Only if the switch is closed, the digital pin is connected to GND.

The following pictures shows the circuit diagram for the Arduino Uno with the pull-up resistor and the wiring for different Arduino, ESP8266 and ESP32 microcontroller boards.

Pull Up Resistor
Wiring Pull Up Resistor Arduino Nano
Wiring Pull Up Resistor Arduino Nano

For more information about the Arduino Nano, visit the Arduino Nano Tutorial.

Wiring Pull Up Resistor Arduino Pro Mini
Wiring Pull Up Resistor Arduino Pro Mini
Wiring Pull Up Resistor Arduino Uno
Wiring Pull Up Resistor Arduino Uno

For more information about the Arduino Uno, visit the Arduino Uno Tutorial.

Wiring Pull Up Resistor Arduino Mega
Wiring Pull Up Resistor Arduino Mega

For more information about the Arduino Mega, visit the Arduino Mega Tutorial.

Wiring Pull Up Resistor ESP32 ESP-WROOM-32
Wiring Pull Up Resistor ESP32 ESP-WROOM-32
Wiring Pull Up Resistor ESP8266 NodeMCU
Wiring Pull Up Resistor ESP8266 NodeMCU
Wiring Pull Up Resistor ESP8266 WeMos D1 Mini
Wiring Pull Up Resistor ESP8266 WeMos D1 Mini

Control a LED with a Pull-Down Resistor and a Button

In he following example, we want to control a LED, that is connected with a button and a pull-down resistor. The objective of the sketch is that the LED is off, when the button is not pressed and the LED is on as long as the button is pressed. Of cause, you can insert the LED into the circuit of the button to achieve this functionality, but in this article we want to read the state of the button to control the LED.

The following pictures show the wiring between all components on different Arduino, ESP8266 and ESP32 microcontroller boards for the pull-down resistor circuit.

Wiring Pull Down Resistor LED Arduino Nano
Wiring Pull Down Resistor LED Arduino Nano

For more information about the Arduino Nano, visit the Arduino Nano Tutorial.

Wiring Pull Down Resistor LED Arduino Pro Mini
Wiring Pull Down Resistor LED Arduino Pro Mini
Wiring Pull Down Resistor LED Arduino Uno
Wiring Pull Down Resistor LED Arduino Uno

For more information about the Arduino Uno, visit the Arduino Uno Tutorial.

Wiring Pull Down Resistor LED Arduino Mega
Wiring Pull Down Resistor LED Arduino Mega

For more information about the Arduino Mega, visit the Arduino Mega Tutorial.

Wiring Pull Down Resistor LED ESP32 ESP-WROOM-32
Wiring Pull Down Resistor LED ESP32 ESP-WROOM-32
Wiring Pull Down Resistor LED ESP8266 NodeMCU
Wiring Pull Down Resistor LED ESP8266 NodeMCU
Wiring Pull Down Resistor LED ESP8266 WeMos D1 Mini
Wiring Pull Down Resistor LED ESP8266 WeMos D1 Mini

After the wiring, we can dive into the Arduino program code that is very easy to understand and shown in the following box.

// for Arduino microcontroller
int button_pin = 7;
int LED_pin = 4;

// for Arduino microcontroller
//int button_pin = D6;
//int LED_pin = D7;

// for Arduino microcontroller
//int button_pin = 4;
//int LED_pin = 0;

void setup() {
  Serial.begin(9600);
  pinMode(LED_pin, OUTPUT);
  pinMode(button_pin, INPUT);
}

void loop() {
  int switchStatus = digitalRead(button_pin); 
  digitalWrite(LED_pin, switchStatus); 
}

In the first part of the program code we have to define the connected pins of the microcontroller. In this example we have the switch and the LED that are connected to the Arduino, ESP8266 or ESP32 microcontroller. Because the script can be used for Arduino, ESP8266 and ESP32 microcontroller boards, you have to select one out of three sections of the program code and comment the other two sections, like I did for the ESP8266 and ESP32, or delete the sections.

In the setup function, we set the baud rate of the serial USB connection to your PC to 9600 that has to be the same in the serial monitor of your Arduino IDE. Also we have to declare the button pin as input and the LED pin as output pins.

In the loop function, we read the current status of the button in the pull-down circuit, that is HIGH if the button is pressed and LOW is the button is not pressed and write the exact same state to the LED. Therefore if the button is pressed, the status of the LED changes from LOW to HIGH and the LED turns on.

The following video shows that the LED turns on, when I press the button.

YouTube

By loading the video, you agree to YouTube's privacy policy.
Learn more

Load video

Change the Functionality of the Button to a Switch

It is possible to change the sketch that the used button has the functionality of a switch. The LED is turned on and off only if the button is pressed and holds its state. Therefore the states of the LED and switch have to be stored in variables to compare the last state with the current inputs. If the button in continuously pressed the states should not be changed.

The wiring is not changed but the following sections shows the program code that is modified.

// for Arduino microcontroller
int switch_pin = 7;
int LED_pin = 4;

// for Arduino microcontroller
//int switch_pin = D6;
//int LED_pin = D7;

// for Arduino microcontroller
//int switch_pin = 4;
//int LED_pin = 0;

int switchStatusLast = LOW;  // last status switch
int LEDStatus = LOW;         // current status LED

void setup() {
  Serial.begin(9600);
  pinMode(LED_pin, OUTPUT);
  pinMode(switch_pin, INPUT);
}

void loop() {
  int switchStatus = digitalRead(switch_pin);   // read status of switch
  if (switchStatus != switchStatusLast)  // if status of button has changed
      {
        // if switch is pressed than change the LED status
        if (switchStatus == HIGH && switchStatusLast == LOW) LEDStatus = ! LEDStatus;
        digitalWrite(LED_pin, LEDStatus);  // turn the LED on or off
        switchStatus = switchStatusLast;
      }
}

The first part stays the same, but we have to define two new variables with the initial state LOW that stores the last status of the switch and the LED.

In the loop function, we read the current status of the button. If this state is different from the previous one, e.g. the button is either pressed (digital signal from LOW to HIGH) or released (digital signal from HIGH to LOW) we enter a second if query that is only true if the button is pressed (last status is LOW and current status is HIGH). In this case we switch the status of the LED. If the LED was off (LOW) the status of the LED changes to HIGH and if the LED was on (HIGH), we change the status to LOW. This changed status is written to the digitalWrite function to control the LED. The last step is to save the current status of the switch as last state before we start the loop function from the beginning.

The following video shows the function of the switch in action. From the video, you also see the common debouncing problem that we solve in later chapters of this article.

YouTube

By loading the video, you agree to YouTube's privacy policy.
Learn more

Load video

Microcontroller Datasheet eBook

The 35 pages Microcontroller Datasheet Playbook contains the most useful information of 14 Arduino, ESP8266 and ESP32 microcontroller boards.

Control a LED with a Pull-Up Resistor and a Button

With the pull-up resistor, we want that the LED is on when the button is not pressed and if we press the button, the LED should goes off. Basically the functionality is the opposite of the pull-down circuit and has the advantage that you directly know that maybe there is a broken cable in the circuit if the LED is off and you do not push the button. In a pull-down circuit you know that there is a problem inside the circuit only until you press the button. If you have any critical circuits, you should preferer the pull-up resistor.

The following picture show the wiring for the pull-up resistor and button, as well as the LED in combination with different Arduino, ESP8266 and ESP32 microcontroller boards.

Wiring Pull Up Resistor LED Arduino Nano
Wiring Pull Up Resistor LED Arduino Nano

For more information about the Arduino Nano, visit the Arduino Nano Tutorial.

Wiring Pull Up Resistor LED Arduino Pro Mini
Wiring Pull Up Resistor LED Arduino Pro Mini
Wiring Pull Up Resistor LED Arduino Uno
Wiring Pull Up Resistor LED Arduino Uno

For more information about the Arduino Uno, visit the Arduino Uno Tutorial.

Wiring Pull Up Resistor LED Arduino Mega
Wiring Pull Up Resistor LED Arduino Mega

For more information about the Arduino Mega, visit the Arduino Mega Tutorial.

Wiring Pull Up Resistor LED ESP32 ESP-WROOM-32
Wiring Pull Up Resistor LED ESP32 ESP-WROOM-32
Wiring Pull Up Resistor LED ESP8266 NodeMCU
Wiring Pull Up Resistor LED ESP8266 NodeMCU
Wiring Pull Up Resistor LED ESP8266 WeMos D1 Mini
Wiring Pull Up Resistor LED ESP8266 WeMos D1 Mini

The program code depends not on you circuit and if you use a pull-down or pull-up configuration with your resistor. Therefore we use the same program code, we used for the pull-down configuration.

// for Arduino microcontroller
int button_pin = 7;
int LED_pin = 4;

// for Arduino microcontroller
//int button_pin = D6;
//int LED_pin = D7;

// for Arduino microcontroller
//int button_pin = 4;
//int LED_pin = 0;

void setup() {
  Serial.begin(9600);
  pinMode(LED_pin, OUTPUT);
  pinMode(button_pin, INPUT);
}

void loop() {
  int switchStatus = digitalRead(button_pin); 
  digitalWrite(LED_pin, switchStatus); 
}

The following video shows the pull-up configuration with the resistor. You see that if I do not press the button, the LED is on and if I press the button, the LED goes off.

YouTube

By loading the video, you agree to YouTube's privacy policy.
Learn more

Load video

Explanation of the Debouncing Problem with Buttons

When a switch or button is pressed, the metal contacts in the contact points can cause the contact points to touch several times. Therefore the contact is bouncing before making a permanent contact. You might ask yourself what problem could occur due the bouncing contacts. The problem is that the Arduino clock speed is 16 MHz which results in 16 million operations per second. So the Arduino will recognize the bouncing contacts as having closed and opened the contacts several times in a row. The following picture shows this behavior on the oscilloscope when pressing a button.

Button Debounce Problem
Button Debounce Problem

In the first picture you see clear, that when the button is pressed, the voltage only reach the around 1.8V instead of 5V. This behavior results in an LED that is not reacting when the switch or button is pressed. Only when the button is pressed a second time the internal contacts are connected and the operating voltage of 5V is reached and the LED stays on.

The same behavior can be shown when I try to switch the LED off in the second picture. The operating voltage is 5V and I push the button. Two times the voltage drops to around 4V and jumps back to 5V. The third time the voltage drops to around 1V but also jumpy back to 5V. Only when I push the button a forth time the switch is released and the LED goes off.

This behavior is a big problem in real live because to you want to push a button multiple times to switch on or off a light in your kitchen? I do not think so.

Good to know that there are two software and one hardware solution to fix this behavior called the debouncing problem.

Two Software Solutions Against the Debouncing Problem

As far as I know, there are two software solutions against the debouncing effect. In the following sections I explain both solutions before I also show you a hardware solution.

Add a Delay when reading the Button State

The first software solution is quite simple and initiates a delay and then rereads the state. The time between the two input reads is defined by a delay. If the delay is too short, the switch may be still bounding.

// for Arduino microcontroller
int switch_pin = 7;
int LED_pin = 4;

// for Arduino microcontroller
//int switch_pin = D6;
//int LED_pin = D7;

// for Arduino microcontroller
//int switch_pin = 4;
//int LED_pin = 0;

int switchStatusLast = LOW;  // last status switch
int LEDStatus = LOW;         // current status LED

void setup() {
  Serial.begin(9600);
  pinMode(LED_pin, OUTPUT);
  pinMode(switch_pin, INPUT);
}

void loop() {
  int switchStatus = digitalRead(switch_pin);   // read status of switch
  if (switchStatus != switchStatusLast)  // if status of button has changed
      {
        delay(50);     // debounce time of 50 ms
        switchStatus = digitalRead(switch_pin);   // read the status of the switchPIN again
        if (switchStatus != switchStatusLast) // if the status of the button has changed again
        {
          // if switch is pressed than change the LED status
          if (switchStatus == HIGH && switchStatusLast == LOW) LEDStatus = ! LEDStatus;
          digitalWrite(LED_pin, LEDStatus);  // turn the LED on or off
          switchStatus = switchStatusLast;
        }
      }
}

You see in the following pictures of the oscilloscope that the press and release voltage is more smoothly than without a software solution. This results in the behavior that when the button is pressed once, the LED turns on or off. The following video also shows the result of the software solution against debouncing.

Press

Debounce Problem Software Solution

Release

Debounce Problem Software Solution
YouTube

By loading the video, you agree to YouTube's privacy policy.
Learn more

Load video

Save the States of the Button - Not Recommended

A second possible software solution against debouncing is to continue delaying until there is no longer change in the switch state at the end of the debounce time. Therefore the state of the switch has to be stored at three different times:

  • State before the switch was pressed (switchStatusLast)
  • State during the debounce time (switchStatusDebounce)
  • State when the switch was last pressed (switchStatus)

If the state has changed and is present longer than a predefined debounce time, the state of the LED can be changed. To compare the debounce time with the time, the switch was last pressed we have to define the time the switch was last pressed as unsigned long variable because the integer number has an upper limit of (2^15-1) ms or 33 seconds. The unsigned long maximum value is (2^32-1) ms or 50 days.

But there is also a much better solution than saving the state of the switch 3 times because it is also possible to solve the problem with the debouncing switch with a capacitor hardware solution.

Hardware Solutions Against the Debouncing Problem

The possible hardware solution to fix the debounce problem is to use a capacitor across the switch. While the switch is not pressed, the capacitor charges. When the switch is pressed, the capacitor discharges while the switch signal to the Arduino is HIGH. During the bouncing the energy of the capacitor maintains the switch signal at HIGH. A recommended resistor-capacitor combination is 10 kΩ pull-down resistor and 10µF capacitor.
The rate which the capacitor charges and discharges depends on the resistance R and the capacitance C. The equation for the voltage of the capacitor after t seconds

  • of charging is V(1-^e(-t/RC)) and
  • discharging is V(e(-t/RC))

Therefore the higher the RC value, the longer is the debounce delay. The debounce delay can be expressed as 0.693 * RC seconds. With a combination of a 10 kΩ pull-down resistor and 10µF capacitor the debounce delay is 69 ms. Although the combination of resistor and capacitor is free of choice, a large resistor should be used to minimize the current through the resistor.

The following pictures show the wiring for different Arduino, ESP8266 and ESP32 microcontroller boards.

Wiring Pull Down Resistor LED Capacitor Arduino Nano
Wiring Pull Down Resistor LED Capacitor Arduino Nano

For more information about the Arduino Nano, visit the Arduino Nano Tutorial.

Wiring Pull Down Resistor LED Capacitor Arduino Pro Mini
Wiring Pull Down Resistor LED Capacitor Arduino Pro Mini
Wiring Pull Down Resistor LED Capacitor Arduino Uno
Wiring Pull Down Resistor LED Capacitor Arduino Uno

For more information about the Arduino Uno, visit the Arduino Uno Tutorial.

Wiring Pull Down Resistor LED Capacitor Arduino Mega
Wiring Pull Down Resistor LED Capacitor Arduino Mega

For more information about the Arduino Mega, visit the Arduino Mega Tutorial.

Wiring Pull Down Resistor LED Capacitor ESP32 ESP-WROOM-32
Wiring Pull Down Resistor LED Capacitor ESP32 ESP-WROOM-32
Wiring Pull Down Resistor LED Capacitor ESP8266 NodeMCU
Wiring Pull Down Resistor LED Capacitor ESP8266 NodeMCU
Wiring Pull Down Resistor LED Capacitor ESP8266 WeMos D1 Mini
Wiring Pull Down Resistor LED Capacitor ESP8266 WeMos D1 Mini

Because we do not add any software solution for the debouncing problem, we can use the standard switch Arduino script that we build in the previous chapter.

// for Arduino microcontroller
int switch_pin = 7;
int LED_pin = 4;

// for Arduino microcontroller
//int switch_pin = D6;
//int LED_pin = D7;

// for Arduino microcontroller
//int switch_pin = 4;
//int LED_pin = 0;

int switchStatusLast = LOW;  // last status switch
int LEDStatus = LOW;         // current status LED

void setup() {
  Serial.begin(9600);
  pinMode(LED_pin, OUTPUT);
  pinMode(switch_pin, INPUT);
}

void loop() {
  int switchStatus = digitalRead(switch_pin);   // read status of switch
  if (switchStatus != switchStatusLast)  // if status of button has changed
      {
        // if switch is pressed than change the LED status
        if (switchStatus == HIGH && switchStatusLast == LOW) LEDStatus = ! LEDStatus;
        digitalWrite(LED_pin, LEDStatus);  // turn the LED on or off
        switchStatus = switchStatusLast;
      }
}

The following two videos show the impact of the hardware solution against the debouncing with a 10µF and a 100µF capacitor. From the video, you see that the 100µF capacitor is powering the LED much longer than the 10µF capacitor if I push the LED off with the button.

Capacitor = 10µF

YouTube

By loading the video, you agree to YouTube's privacy policy.
Learn more

Load video

Capacitor = 100µF

YouTube

By loading the video, you agree to YouTube's privacy policy.
Learn more

Load video

In the following picture you see the voltage rise during the button press. It is very similar to the software solution.

Debounce Problem Hardware Solution

The following picture shows the voltage during the press and release phases. You see very good the impact of the capacitor reducing the voltage over time. The picture shows 4 cycles.

Debounce Problem Hardware Solution

Conclusion

In this article you learn about different kinds of switches and the pull-up and pull down resistors, how to use them and the differences. Also you learned what the debouncing problem is. Moreover we discussed hardware and software solutions against the debouncing problem.
I hope you enjoined this article. Do you have any further questions about switches? Use the comment section below to ask your questions.

1 thought on “Switches Tutorial for Arduino, ESP8266 and ESP32”

  1. Contrary to narrative, the comments for all code fragments say “Arduino”… none are tagged for ESP8266/ESP32. Presumably the uncommented one really is Arduino Uno, the 2nd is ESP8266 and the 3rd is ESP32.

    Reply

Leave a Comment