This ESP32 S3 Uno button debounce tutorial shows you how to make the board count one press as exactly one press. A push button does not switch cleanly. Its metal contacts bounce, so the signal jumps between LOW and HIGH many times in a few milliseconds. This is called chattering, and the ESP32 S3 Uno form board is fast enough to see every bounce. Button debouncing with millis() or a library fixes it.
In this tutorial, you will:
See how chattering makes one press look like many presses
Write button debouncing code with the millis() function
Debounce a single button with the ezButton library
Debounce multiple buttons on the ESP32 S3 Uno at the same time
The picture below shows what chattering looks like on the button signal.
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 .
Overview of Button
Debouncing only makes sense once you know how a button is read. If the pinout, the pull-up input or the basic button code is new to you, read the button tutorial first. It covers everything this page builds on.
The image below shows the pinout of the ESP32 S3 Uno form board. Use it to find the Uno header pins (D6, D7, D8…) and their GPIO numbers when you wire the buttons.
Wiring Diagram
Connect one leg of the button to pin D7 and the other leg to GND. No external resistor is needed, because the code turns on the internal pull-up resistor of the ESP32 S3 Uno.
This image is created using Fritzing. Click to enlarge image
Component Pin
ESP32 S3 Uno Pin
Button pin 1
D7 (GPIO14)
Button pin 2
GND
The same wiring is used for the first three sketches below. You will run the code without debounce first, then with debounce, and compare what the Serial Monitor shows.
ESP32 S3 Uno - Button without Debounce
It helps to see the problem with your own eyes before you fix it. This sketch reads the button on every loop and prints a message each time the state changes from HIGH to LOW (pressed) or from LOW to HIGH (released). There is no filter, so every bounce gets printed.
/* * This ESP32 S3 Uno code was developed by newbiely.com * * This ESP32 S3 Uno code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/esp32-s3-uno/esp32-s3-uno-button-debounce */#define BUTTON_PIN 14 // The ESP32 S3 Uno pin connected to the button (D7)int button_state; // the current state of buttonint prev_button_state = LOW; // the previous state of buttonvoidsetup() {// initialize serial communication at 9600 bits per second:Serial.begin(9600);// initialize the pushbutton pin as a pull-up inputpinMode(BUTTON_PIN, INPUT_PULLUP);}voidloop() {// read the state of the switch/button: button_state = digitalRead(BUTTON_PIN);if (prev_button_state == HIGH && button_state == LOW)Serial.println("The button is pressed");elseif (prev_button_state == LOW && button_state == HIGH)Serial.println("The button is released");// save the last state prev_button_state = button_state;}
Connect the board to your computer with a USB Type-C cable.
Open Arduino IDE, choose the ESP32S3 Dev Module board and the correct COM port.
Copy the code above and paste it into the Arduino IDE.
Upload the code by clicking the Upload button.
Open the Serial Monitor and set the baud rate to 9600.
Press and hold the button for a few seconds, then let it go.
Read the output in the Serial Monitor.
Tip: Press the button quickly a few times. The more worn the button is, the more extra messages you will see.
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
ESP32S3 Dev Module
Newbiely.ino
···
8Serial.println("Hello World!");
Output
Serial Monitor
Message (Enter to send message to 'ESP32S3 Dev Module' on 'COM15')
New Line
9600 baud
The button is pressed
The button is pressed
The button is pressed
The button is released
The button is released
Ln 11, Col 1
ESP32S3 Dev Module on COM15
2
You pressed and released the button only once, but the ESP32 S3 Uno saw several presses and several releases. Those extra lines come from the contacts bouncing.
※ NOTE THAT:
The right DEBOUNCE_TIME depends on the project and on the button itself. One application may work well with 50 ms, while another needs a different value.
ESP32 S3 Uno - Button with Debounce
The fix is to wait until the signal stops changing. Every time the pin changes, the sketch restarts a timer with millis(). Only when the pin has stayed the same for longer than DEBOUNCE_TIME (50 ms) does the code accept the new state as real and print a message.
/* * This ESP32 S3 Uno code was developed by newbiely.com * * This ESP32 S3 Uno code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/esp32-s3-uno/esp32-s3-uno-button-debounce */#define BUTTON_PIN 14 // The ESP32 S3 Uno pin GPIO14 (D7) connected to the button#define DEBOUNCE_TIME 50 // The debounce time; increase if the output flickersint last_steady_state = LOW; // the previous steady state from the input pinint last_flickerable_state = LOW; // the previous flickerable state from the input pinint current_state; // the current reading from the input pinunsignedlong last_debounce_time = 0; // the last time the output pin was toggledvoidsetup() {// initialize serial communication at 9600 bits per second:Serial.begin(9600);// initialize the pushbutton pin as a pull-up inputpinMode(BUTTON_PIN, INPUT_PULLUP);}voidloop() {// read the state of the switch/button: current_state = digitalRead(BUTTON_PIN);// If the switch/button changed, due to noise or pressing:if (current_state != last_flickerable_state) {// reset the debouncing timer last_debounce_time = millis();// save the the last flickerable state last_flickerable_state = current_state; }if ((millis() - last_debounce_time) > DEBOUNCE_TIME) {// if the button state has changed:if (last_steady_state == HIGH && current_state == LOW)Serial.println("The button is pressed");elseif (last_steady_state == LOW && current_state == HIGH)Serial.println("The button is released");// save the the last steady state last_steady_state = current_state; }}
Detailed Instructions
Copy the code above and paste it into the Arduino IDE.
Upload it to the ESP32 S3 Uno with the Upload button.
Open the Serial Monitor at 9600 baud.
Hold the button down for a few seconds, then release it.
Check the output in the Serial Monitor.
Tip: If you still see double messages, raise DEBOUNCE_TIME to 80 or 100 ms.
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
ESP32S3 Dev Module
Newbiely.ino
···
8Serial.println("Hello World!");
Output
Serial Monitor
Message (Enter to send message to 'ESP32S3 Dev Module' on 'COM15')
New Line
9600 baud
The button is pressed
The button is released
Ln 11, Col 1
ESP32S3 Dev Module on COM15
2
Now one press gives one "pressed" line and one "released" line. The chattering is gone.
We Made It Simple: ESP32 S3 Uno Button Debounce Code Using a Library
Writing the timer logic for every button gets tiring, especially when you have many buttons. To make it easy for beginners, we created the ezButton library. It handles the debounce timer for you. You can learn more about the ezButton library here.
To install it, open the Library Manager in the Arduino IDE, search for "ezButton", and install the library by ArduinoGetStarted.com. The examples below show how to use it.
ESP32 S3 Uno Button Debounce Code for A Single Button
This sketch does the same job as the long debounce code above, but in a few lines. You create one ezButton object on GPIO14 (D7), set a 50 ms debounce time, and call button.loop() at the start of every loop.
/* * Created by ArduinoGetStarted.com * * This example code is in the public domain * * Tutorial page: https://arduinogetstarted.com/tutorials/arduino-button-library * * This example reads the state of a button with debounce and print it to Serial Monitor. */#include <ezButton.h>ezButtonbutton(14); // create ezButton object that attach to the ESP32 S3 Uno pin GPIO14 (D7);voidsetup() {Serial.begin(9600);button.setDebounceTime(50); // set debounce time to 50 milliseconds}voidloop() {button.loop(); // MUST call the loop() function firstif(button.isPressed())Serial.println("The button is pressed");if(button.isReleased())Serial.println("The button is released");}
ESP32 S3 Uno Button Debounce Code for Multiple Buttons
The library really helps when you have more than one button. Here you debounce three buttons at once. Each button goes between its own pin and GND, and each one gets its own ezButton object.
This image is created using Fritzing. Click to enlarge image
Component Pin
ESP32 S3 Uno Pin
Button 1 pin 1
D6 (GPIO3)
Button 2 pin 1
D7 (GPIO14)
Button 3 pin 1
D8 (GPIO21)
Pin 2 of every button
GND
WARNING
D6 (GPIO3) is a boot strapping pin on the ESP32 S3 Uno. The board reads it at startup. A button with the internal pull-up is normally safe, but do not hold button 1 down while you power on, reset or upload code. If the board will not boot or upload, release the button or unplug its wire and try again.
/* * This ESP32 S3 Uno code was developed by newbiely.com * * This ESP32 S3 Uno code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/esp32-s3-uno/esp32-s3-uno-button-debounce */#include <ezButton.h>ezButton button_1(3); // initialize ezButton object connected to ESP32 S3 Uno pin GPIO3 (D6)ezButton button_2(14); // initialize ezButton object connected to ESP32 S3 Uno pin GPIO14 (D7)ezButton button_3(21); // initialize ezButton object connected to ESP32 S3 Uno pin GPIO21 (D8)voidsetup() {Serial.begin(9600); button_1.setDebounceTime(50); // configure debounce time for button_1 to 50ms button_2.setDebounceTime(50); // configure debounce time for button_2 to 50ms button_3.setDebounceTime(50); // configure debounce time for button_3 to 50ms}voidloop() { button_1.loop(); // update button_1 state button_2.loop(); // update button_2 state button_3.loop(); // update button_3 stateif(button_1.isPressed())Serial.println("The button 1 is pressed");if(button_1.isReleased())Serial.println("The button 1 is released");if(button_2.isPressed())Serial.println("The button 2 is pressed");if(button_2.isReleased())Serial.println("The button 2 is released");if(button_3.isPressed())Serial.println("The button 3 is pressed");if(button_3.isReleased())Serial.println("The button 3 is released");}
Press each button once and you should see a clean pair of lines for it.
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
ESP32S3 Dev Module
Newbiely.ino
···
8Serial.println("Hello World!");
Output
Serial Monitor
Message (Enter to send message to 'ESP32S3 Dev Module' on 'COM15')
New Line
9600 baud
The button 1 is pressed
The button 1 is released
The button 2 is pressed
The button 2 is released
The button 3 is pressed
The button 3 is released
Ln 11, Col 1
ESP32S3 Dev Module on COM15
2
Video Tutorial
Watch the video below to see this ESP32 S3 Uno project step by step.
FAQ
Why does my button press count many times on the ESP32 S3 Uno?
The metal contacts inside the button bounce for a few milliseconds when you press or release it. The ESP32 S3 Uno reads the pin very fast, so it sees every bounce as a new press. Debouncing in code, with millis() or the ezButton library, ignores these short changes.
What debounce time should I use?
50 ms works for most push buttons. If you still see extra presses, try 80 or 100 ms. If the button feels slow when you press it quickly, lower the value a little.
Do I need an external pull-up resistor for the button?
No. The code uses INPUT_PULLUP, which turns on the internal pull-up resistor of the ESP32 S3 Uno. Just wire the button between the pin and GND. The pin reads HIGH when the button is free and LOW when it is pressed.
Can I use the same debounce code from the UNO R4 on the ESP32 S3 Uno?
Yes. The logic and the ezButton library work the same way. You only need to change the pin numbers to GPIO numbers, for example D7 on the UNO R4 becomes GPIO14 on the ESP32 S3 Uno. Also remember that ESP32 S3 Uno pins use 3.3V logic and are not 5V tolerant.
Is it safe to use D6 for a button on the ESP32 S3 Uno?
D6 is GPIO3, a boot strapping pin. A button to GND with the internal pull-up usually works fine. Just do not hold that button during power-on, reset or upload, or the board may not start correctly. If you have a free pin, you can move the button to a normal pin like D4 or D5 and change the number in the code.
What if my project needs more pins than the Uno headers give?
The ESP32 S3 Uno has two extra rows of holes with more GPIOs. GPIO15 and GPIO16 are I/O, PWM and analog. GPIO45 and GPIO35 to GPIO42 are I/O and PWM. GPIO47 and GPIO48 are output only, with PWM. Solder pin headers to use them and write the GPIO number in code. For extra buttons, GPIO35 to GPIO42, GPIO15 and GPIO16 are good choices. Do not use GPIO47 or GPIO48, because they cannot read inputs. Two warnings: GPIO47 and GPIO48 may run at 1.8V instead of 3.3V on some modules (especially ones with "V" in the name, like R8V or R16V), so 3.3V devices can be damaged or act strangely. Also, GPIO0, GPIO3 (D6), GPIO45 and GPIO46 (D9) are boot strapping pins, and a wrong connection can stop the board from booting or uploading code. Use the other extra pins first.
Troubleshooting
Problem
Possible Cause
Solution
No COM port appears in Arduino IDE
Missing USB driver or the board is not in upload mode
Install the CP210x or CH340 driver, try another USB cable, or hold BOOT while pressing RESET
Nothing prints when you press the button
Button wired to the wrong pin or not to GND
Check that the button goes from D7 (GPIO14) to GND and that the code uses pin 14
Serial Monitor shows strange characters
Wrong baud rate
Set the Serial Monitor to 9600 baud
One press still prints several messages
Debounce time too short for this button
Increase DEBOUNCE_TIME or setDebounceTime() to 80 or 100 ms
Messages appear without touching the button
Floating input or loose wire
Make sure the code uses INPUT_PULLUP and push the jumper wires firmly into the breadboard
Compile error ezButton.h not found
ezButton library is not installed
Install ezButton from the Library Manager
Board does not boot or upload with three buttons
Button 1 on D6 (GPIO3) is held at startup
Release the button during reset and upload, or move it to another pin
Press and release are swapped
Button wired to 3.3V instead of GND
Wire the button to GND, because INPUT_PULLUP reads LOW when pressed
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!