ESP32 UNO - Button - LED

Want a push button to switch a light with the ESP32 Uno? Put one button and one LED on the ESP32 Uno form board and you get a working button-controls-LED circuit in a few minutes. First the LED mirrors the button. Then each press flips the LED, like a real light switch, and you find out why a button toggle LED needs debounce to behave.

What you will do:

  1. Connect a push button and a 220 ohm LED circuit to the ESP32 Uno
  2. Light the LED only while the button is held down
  3. Toggle the LED on and off with single presses
  4. See contact bounce cause missed or double toggles
  5. Fix the bounce with the ezButton library
ESP32 Uno button LED

Components You Need

1×ESP32 Uno-form Board
1×USB Cable Type-A to Type-C (for USB-A PC)
1×USB Cable Type-C to Type-C (for USB-C PC)
1×Breadboard-mount Button with Cap
1×Breadboard-mount Button Kit
1×Panel-mount Push Button
1×Push Button Module
1×LED Kit
1×LED (red)
1×LED Module
1×Alternatively, Button and LED Kit
1×220Ω Resistor
1×Breadboard
1×Jumper Wires

Or you can buy the following kits:

1×DIYables Sensor Kit (18 sensors/displays)
Disclosure: Some of the links provided in this section are Amazon affiliate links. We may receive a commission for any purchases made through these links at no additional cost to you.
Additionally, some of these links are for products from our own brand, DIYables .

Buy Note: Use the LED Module for easier wiring. It includes an integrated resistor.

The Button, the LED and the Two Behaviors

After this part, you know what each piece does and which of the two programs you want.

Part Job Here Learn It Alone
Push button Input, pulls D7 to GND when pushed ESP32 Uno - Button
LED + 220 ohm resistor Output, lit when D3 is HIGH ESP32 Uno - LED
Debounce Filters the noisy contact signal ESP32 Uno - Button Debounce
Program Button Action LED Result
Application 1 (follow) Hold down On for as long as you hold
Application 1 (follow) Let go Off at once
Application 2 (toggle) Push (HIGH to LOW edge) Swaps between on and off
Application 2 (toggle) Let go Stays as it is

Application 2 reacts to the moment of the push, so a bouncing contact can fool it. You will run it twice: once raw, once with debounce, and compare.

Good to know: an ESP32 Uno GPIO gives 3.3V when HIGH. That is enough for a red, yellow or green LED with a 220 ohm resistor.

ESP32 Uno Pinout

The board prints Uno names like D3 and D7, but the sketch needs the chip's GPIO numbers. Look up both pins of this project in the picture first.

ESP32 Uno pinout diagram

How to Connect It

When this part is done, the button sits on D7, the LED sits on D3, and both share GND.

The wiring diagram between ESP32 Uno Button LED

This image is created using Fritzing. Click to enlarge image

Component Pin ESP32 Uno Pin
Button leg A D7 (GPIO14)
Button leg B GND
LED anode (long leg) via 220 ohm resistor D3 (GPIO25)
LED cathode (short leg) GND

Good to know: skip the external resistor for the button. INPUT_PULLUP turns on a pull-up inside the chip, so GPIO14 rests at HIGH and drops to LOW on a push. Keep every signal at 3.3V; ESP32 Uno pins are not 5V tolerant.

Application 1 - LED Mirrors the Button

Here you get the most direct link: button down, LED on. Use it to prove the wiring works.

ESP32 Uno Code - Follow Mode

The sketch polls GPIO14 nonstop and copies the result to the LED on GPIO25, printing the state each time.

/* * This ESP32 Uno code was developed by newbiely.com * * This ESP32 Uno code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/esp32-uno/esp32-uno-button-led */ #define BUTTON_PIN 14 // D7 (GPIO14) reads the push button #define LED_PIN 25 // D3 (GPIO25) drives the LED through the resistor void setup() { Serial.begin(9600); // open the USB serial link pinMode(BUTTON_PIN, INPUT_PULLUP); // idle HIGH thanks to the internal pull-up pinMode(LED_PIN, OUTPUT); // the LED pin sends a signal out } void loop() { int buttonState = digitalRead(BUTTON_PIN); // take a fresh button reading if (buttonState == LOW) { Serial.println("The button is being pressed"); digitalWrite(LED_PIN, HIGH); // light the LED } else if (buttonState == HIGH) { Serial.println("The button is unpressed"); digitalWrite(LED_PIN, LOW); // switch the LED off } }

Upload and Test

  1. First time with this board? Set it up with ESP32 Uno - Getting Started before you continue.
  2. Build the circuit by following the wiring table above.
  3. Plug in the USB Type-C cable between the ESP32 Uno and your computer.
  4. Select the board in Arduino IDE: pick ESP32 Dev Module and the COM port of the board (CH340).
  5. Paste the sketch into a new Arduino IDE window.
  6. Press Upload (Upload) and wait for "Done uploading".
  7. Start the Serial Monitor and set it to 9600 baud.
  8. Hold the button for about two seconds, then release it.
  9. Check the LED: it glows only during the hold.
∞
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
ESP32 Dev Module
Newbiely.ino
···
8 Serial.println("Hello World!");
Output
Serial Monitor
Message (Enter to send message to 'ESP32 Dev Module' on 'COM15')
New Line
9600 baud
The button is unpressed The button is being pressed The button is being pressed The button is being pressed The button is unpressed
Ln 11, Col 1
ESP32 Dev Module on COM15
2
  1. Pro tip: the text scrolls very fast because loop() prints on every pass. Untick "Autoscroll" in the Serial Monitor to freeze it and read single lines.

Code Explanation

Code Part What It Does
BUTTON_PIN 14 and LED_PIN 25 Tie the names to D7 (GPIO14) and D3 (GPIO25)
pinMode(BUTTON_PIN, INPUT_PULLUP) Enables the internal pull-up so a free button reads HIGH
digitalRead(BUTTON_PIN) Gets the current button level every loop pass
buttonState == LOW Means the button is down, so the LED pin goes HIGH
buttonState == HIGH Means the button is up, so the LED pin goes LOW

The result is an LED that tracks your finger with no visible delay.

Application 2 - Each Press Flips the LED

Now the LED keeps its new state after you let go. For that, the code must catch the single moment of the push.

ESP32 Uno Code - Toggle Without Debounce

The sketch stores the previous button reading. A HIGH followed by a LOW counts as one push and flips the LED.

/* * This ESP32 Uno code was developed by newbiely.com * * This ESP32 Uno code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/esp32-uno/esp32-uno-button-led */ #define BUTTON_PIN 14 // D7 (GPIO14) reads the push button #define LED_PIN 25 // D3 (GPIO25) drives the LED through the resistor int led_state = LOW; // LED level right now int button_state; // button level from this pass int prev_button_state; // button level from the pass before void setup() { Serial.begin(9600); // open the USB serial link pinMode(BUTTON_PIN, INPUT_PULLUP); // idle HIGH thanks to the internal pull-up pinMode(LED_PIN, OUTPUT); // the LED pin sends a signal out button_state = digitalRead(BUTTON_PIN); } void loop() { prev_button_state = button_state; // keep the old reading button_state = digitalRead(BUTTON_PIN); // take a fresh button reading if(prev_button_state == HIGH && button_state == LOW) { Serial.println("The button is pressed"); // flip the stored LED level led_state = !led_state; // send the new level to the LED pin digitalWrite(LED_PIN, led_state); } }

Code Explanation

Code Part What It Does
prev_button_state Holds the reading from the last loop pass
prev HIGH and now LOW Detects the falling edge, which is one push
led_state = !led_state Swaps LOW to HIGH or HIGH to LOW
digitalWrite(LED_PIN, led_state) Sends the new level to GPIO25

The ! operator is a short form. It gives the same result as this longer block:

if(led_state == LOW) led_state = HIGH; else led_state = LOW;

Upload and Test

  1. Paste this sketch into the Arduino IDE.
  2. Upload it to the ESP32 Uno.
  3. Push and release the button about ten times.
  4. Watch the LED after each push.
  5. Pro tip: count your pushes and the "The button is pressed" lines side by side. If the line count is higher, you have caught bounce in action.

Many pushes work fine. Some pushes, though, flip the LED two or three times in a row, or look like they did nothing (two flips, too fast to see). The metal parts in the button spring back and forth for a few milliseconds, and the fast ESP32 Uno loop reads every bounce as a new push.

⇒ The cure is to debounce the button.

ESP32 Uno Code - Toggle With Debounce

Hand-written debounce code is easy to get wrong. The ezButton library handles it in two lines. For the full story on bounce, see the ESP32 Uno - Button Debounce page.

This version waits until the button level stays stable for 50 ms, then reports exactly one push.

/* * This ESP32 Uno code was developed by newbiely.com * * This ESP32 Uno code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/esp32-uno/esp32-uno-button-led */ #include <ezButton.h> #define BUTTON_PIN 14 // D7 (GPIO14) reads the push button #define LED_PIN 25 // D3 (GPIO25) drives the LED through the resistor ezButton button(BUTTON_PIN); // debounced button object on GPIO14 int led_state = LOW; // LED level right now void setup() { Serial.begin(9600); // open the USB serial link pinMode(LED_PIN, OUTPUT); // the LED pin sends a signal out button.setDebounceTime(50); // ignore contact bounce shorter than 50 ms } void loop() { button.loop(); // let ezButton update first, on every pass if(button.isPressed()) { Serial.println("The button is pressed"); // flip the stored LED level led_state = !led_state; // send the new level to the LED pin digitalWrite(LED_PIN, led_state); } }

Upload and Test

  1. Install ezButton: open the Library Manager, search "ezButton" and click Install. Full steps are on the ezButton install guide.
  2. Paste the sketch into the Arduino IDE.
  3. Click Upload (Upload) to send it to the ESP32 Uno.
  4. Push and release the button four times.
  5. Check the LED: on, off, on, off, one change per push.
∞
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
ESP32 Dev Module
Newbiely.ino
···
8 Serial.println("Hello World!");
Output
Serial Monitor
Message (Enter to send message to 'ESP32 Dev Module' on 'COM15')
New Line
9600 baud
The button is pressed The button is pressed The button is pressed The button is pressed
Ln 11, Col 1
ESP32 Dev Module on COM15
2
  1. Pro tip: a big panel-mount button can bounce longer than a small breadboard one. If it still double-toggles, try button.setDebounceTime(30) down to button.setDebounceTime(120) until one push equals one line.

Video Tutorial

See the ESP32 Uno build in action in the video below.

ESP32 Uno vs UNO R4 for This Project

Moving this button and LED build from the UNO R4 to the ESP32 Uno only touches the pin numbers and the voltage.

Item Arduino UNO R4 ESP32 Uno
Logic voltage 5V 3.3V
Button pin in code 7 (D7) 14 (D7)
LED pin in code 3 (D3) 25 (D3)
Internal pull-up Yes Yes
ezButton library Works Works, no change
Arduino IDE board Arduino UNO R4 WiFi or Minima ESP32 Dev Module

The wires stay in the same header holes, so you can move the breadboard over without changes. The LED looks a bit dimmer at 3.3V, which is normal.

Go Wireless: A Phone Button for the Same LED

This idea lets you switch the LED from two places at once.

The ESP32 Uno has WiFi and Bluetooth (Classic and BLE) on board. Keep the real button on D7, and add an on-screen switch on your phone that flips the same led_state. The LED then answers to both the physical push and the phone tap, and the phone can show the current state too.

Good to know: use the ezButton version as your base. It never blocks loop(), so the WiFi or Bluetooth library gets enough time to run.

Troubleshooting

Problem Possible Cause Solution
No COM port shows up in Arduino IDE CH340 driver not installed or the cable is charge-only Install the CH340 driver and use a USB cable that carries data
Upload stops at "Failed to connect" or "Waiting for download" The board did not go into download mode Hold the BOOT button as the upload begins, then release it
LED stays dark in every sketch LED turned around or resistor missing from the path Long leg goes to the resistor and D3 (GPIO25), short leg to GND
LED is lit all the time and the button does nothing Button leg B wired to 3.3V or 5V instead of GND Move that leg to a GND pin
Monitor jumps between pressed and unpressed with no touch Wire to D7 is loose, so GPIO14 floats Reseat the jumper and check it lands in the button row
Sketch copied from another board does nothing Pins 7 and 3 left in the code Change them to 14 and 25
ezButton.h no such file Library not installed Install ezButton from the Library Manager and compile again
Gibberish in the Serial Monitor Baud mismatch Choose 9600 baud in the Serial Monitor

FAQ

How does a push button turn an LED on and off with the ESP32 Uno?

The button changes the level on an input pin, and the sketch reads it with digitalRead(). Based on that level, the sketch writes HIGH or LOW to the LED pin with digitalWrite(). The button never carries the LED current itself.

What is the difference between follow mode and toggle mode?

Follow mode copies the button: the LED is on only while you hold it. Toggle mode remembers the LED state and flips it once per push, so the LED stays on or off after you let go.

Why is the button signal LOW when I press it?

With INPUT_PULLUP, GPIO14 is pulled up to 3.3V inside the chip. Pressing the button connects the pin to GND, so it reads LOW. Released, it goes back to HIGH.

Which resistor value is right for the LED at 3.3V?

220 ohm works well. With a red LED it gives roughly 6 mA, which is safe for the ESP32 Uno pin and still clearly visible. 330 ohm is fine too, just a little dimmer.

Why do I type 14 and 25 in the code and not 7 and 3?

The ESP32 Uno code uses GPIO numbers. The D7 header hole is GPIO14 and the D3 hole is GPIO25. Writing 7 or 3 would point to other chip pins.

Could I use A2 for the button instead of D7?

Only with an extra part. A2 to A5 (GPIO35, 34, 36, 39) are input only on the ESP32 Uno and have no internal pull-up, so INPUT_PULLUP does nothing there. Add a 10k ohm resistor from the pin to 3.3V, or just keep D7.

Can the LED go on A3 or A4?

No. A2 to A5 cannot output a signal on the ESP32 Uno, so an LED there never lights. Keep the LED on a digital header pin like D3.

Do I need a driver to upload code to the ESP32 Uno?

This board uses a CH340 USB-to-serial chip. Windows and macOS often need the CH340 driver once. After that, the board shows up as a COM port in the Arduino IDE.

How can I control two LEDs with two buttons?

Copy the ezButton object and the led_state variable for the second pair, and give them new pins, for example D4 (GPIO17) for the button and D6 (GPIO27) for the LED. Call loop() on both button objects at the top of loop().

What if I run out of Uno header pins for more buttons and LEDs?

The ESP32 Uno has a few extra holes near the power header: GPIO32 and GPIO33 (I/O, PWM, analog on ADC1, so they also work while WiFi is on) and GPIO15 (I/O, PWM, analog on ADC2). Solder pin headers there and write the GPIO number in code. GPIO32 and GPIO33 are the best picks for extra buttons or LEDs in this project, since both support the internal pull-up. Two warnings: GPIO15 and GPIO0 (the IO0 pin at the unused Uno NC position) are boot strapping pins, and a wrong connection can stop the board from booting or uploading code, so use GPIO32/33 first. Never use the six holes under the digital header (SD0 to SD3, CMD, CLK = GPIO6 to GPIO11); they are wired to the flash chip and using them crashes the board.

※ OUR MESSAGES

  • As freelancers, We are AVAILABLE for HIRE. See how to outsource your project to us
  • Please feel free to share the link of this tutorial. However, Please do not use our content on any other websites. We invested a lot of effort and time to create the content, please respect our work!