ESP32 S3 UNO - Button - Debounce

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:

  1. See how chattering makes one press look like many presses
  2. Write button debouncing code with the millis() function
  3. Debounce a single button with the ezButton library
  4. Debounce multiple buttons on the ESP32 S3 Uno at the same time
ESP32 S3 Uno button debounce

The picture below shows what chattering looks like on the button signal.

ESP32 S3 Uno chattering phenomenon

Hardware Preparation

1×ESP32 S3 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×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 .

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.

ESP32 S3 Uno Pinout

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.

ESP32 S3 Uno pinout diagram

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.

The wiring diagram between ESP32 S3 Uno Button

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 button int prev_button_state = LOW; // the previous state of button void setup() { // initialize serial communication at 9600 bits per second: Serial.begin(9600); // initialize the pushbutton pin as a pull-up input pinMode(BUTTON_PIN, INPUT_PULLUP); } void loop() { // 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"); else if (prev_button_state == LOW && button_state == HIGH) Serial.println("The button is released"); // save the last state prev_button_state = button_state; }

Detailed Instructions

  1. New to the ESP32 S3 Uno? Follow ESP32 S3 Uno - Getting Started first.
  2. Wire it up as shown in the diagram.
  3. Connect the board to your computer with a USB Type-C cable.
  4. Open Arduino IDE, choose the ESP32S3 Dev Module board and the correct COM port.
  5. Copy the code above and paste it into the Arduino IDE.
  6. Upload the code by clicking the Upload button.
  7. Open the Serial Monitor and set the baud rate to 9600.
  8. Press and hold the button for a few seconds, then let it go.
  9. Read the output in the Serial Monitor.
  10. 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
···
8 Serial.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 flickers int last_steady_state = LOW; // the previous steady state from the input pin int last_flickerable_state = LOW; // the previous flickerable state from the input pin int current_state; // the current reading from the input pin unsigned long last_debounce_time = 0; // the last time the output pin was toggled void setup() { // initialize serial communication at 9600 bits per second: Serial.begin(9600); // initialize the pushbutton pin as a pull-up input pinMode(BUTTON_PIN, INPUT_PULLUP); } void loop() { // 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"); else if (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

  1. Copy the code above and paste it into the Arduino IDE.
  2. Upload it to the ESP32 S3 Uno with the Upload button.
  3. Open the Serial Monitor at 9600 baud.
  4. Hold the button down for a few seconds, then release it.
  5. Check the output in the Serial Monitor.
  6. 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
···
8 Serial.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> ezButton button(14); // create ezButton object that attach to the ESP32 S3 Uno pin GPIO14 (D7); void setup() { Serial.begin(9600); button.setDebounceTime(50); // set debounce time to 50 milliseconds } void loop() { button.loop(); // MUST call the loop() function first if(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.

The wiring diagram between ESP32 S3 Uno Button Library

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) void setup() { 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 } void loop() { button_1.loop(); // update button_1 state button_2.loop(); // update button_2 state button_3.loop(); // update button_3 state if(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
···
8 Serial.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

※ 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!