ESP32 - Button Module

A doorbell for your workshop, a "fire" key for a small game, a start/stop key for a data logger: many ESP32 projects need just one thing from the user, a press. This tutorial shows how to get that press into your ESP32 with the 3-pin button module, step by step, from reading the raw pin level, to catching clean press and release events with a short delay, and finally to the ezButton library, which does the debouncing for you without pausing your code.

ESP32 button module

This tutorial shows how to program the ESP32 using the Arduino language (C/C++) via the Arduino IDE. If you’d like to learn how to program the ESP32 with MicroPython, visit this ESP32 MicroPython - Button Module tutorial.

Introduction to the Button Module

Button module pinout
image source: diyables.io

In short, the button module is a push button with its resistor already on board. A small tactile switch with a colored cap sits on a tiny PCB, next to a pull-down resistor. While nobody touches the cap, that resistor holds the output at LOW. Press the cap and the output jumps to the supply voltage, so the ESP32 reads HIGH. Let go and it falls back to LOW. One pack holds five modules, one in each color: red, yellow, green, blue and white, so you can give every key in your project its own color.

Button Module
The switch type momentary tactile push button
The operating voltage 3.3V to 5V DC
The output when released LOW
The output when pressed HIGH (equal to VCC)
The pull resistor pull-down, built into the module
The connector 3-pin male header, 2.54mm pitch

Button Module Pinout

The three pins are printed on the board in the order VCC, OUT, GND:

  • VCC pin: connect this pin to 3V3 of the ESP32. Do not use the 5V or VIN pin (see the warning below).
  • OUT pin: connect this pin to a GPIO of the ESP32. It gives LOW when the cap is up and HIGH when the cap is down.
  • GND pin: connect this pin to GND (0V).

※ NOTE THAT:

When the cap is pressed, the OUT pin gives out the same voltage as the VCC pin. The ESP32 GPIO pins work at 3.3V and are not 5V tolerant. If VCC is wired to 5V or VIN, every press pushes 5V into GPIO21 and can damage the ESP32. Always power the module from the 3V3 pin.

There is one more thing every mechanical button does: its metal contacts bounce for a few milliseconds when they close or open. During that short time the pin flips between LOW and HIGH, so a single press can look like several presses to a fast chip like the ESP32. The second and third examples below fix this.

Why pick the module over a bare 4-pin push button? The bare button needs a pull-up or pull-down resistor (or INPUT_PULLUP in code), and its four legs are easy to wire the wrong way. The module has labeled pins and its own pull-down, and its logic is not inverted: pressed simply means HIGH. We highly recommend you using the button module if you are new to buttons. If you want to learn the bare button too, see the ESP32 - Button tutorial.

Wiring Diagram

The module needs three wires, and the same wiring is used for all three codes in this tutorial:

Button Module ESP32
VCC → 3V3 (not 5V, not VIN)
OUT → GPIO21
GND → GND
ESP32 button module wiring diagram

This image is created using Fritzing. Click to enlarge image

If you're unfamiliar with how to supply power to the ESP32 and other components, you can find guidance in the following tutorial: The best way to Power ESP32 and sensors/displays.

How To Program For Button Module

The module already has a pull-down resistor, so the code only has to read a pin. No external resistor is needed.

  • Make GPIO21 a plain input. Do not write INPUT_PULLUP: the internal pull-up would work against the module's pull-down.
pinMode(21, INPUT);
  • Read the level of the OUT pin with digitalRead(). HIGH means the cap is pressed, LOW means it is up.
int level = digitalRead(21);
  • To catch the moment of a press or a release, keep the last level in a variable and compare it with the new one. When they differ, something happened.

ESP32 Code - Read the Raw State

This first code is the simplest one. Five times per second, the ESP32 reads GPIO21 and prints the level, plus a short word that says if the key is down or up.

/* * This ESP32 code is created by esp32io.com * * This ESP32 code is released in the public domain * * For more detail (instruction and wiring diagram), visit https://esp32io.com/tutorials/esp32-button-module */ #define BUTTON_MODULE_PIN 21 // ESP32's GPIO21 connected to the OUT pin of the button module void setup() { Serial.begin(9600); // plain INPUT: the module already has its own pull-down resistor, // so do NOT use INPUT_PULLUP here pinMode(BUTTON_MODULE_PIN, INPUT); } void loop() { int level = digitalRead(BUTTON_MODULE_PIN); // HIGH = pressed, LOW = released Serial.print("OUT pin = "); Serial.print(level); if (level == HIGH) Serial.println(" -> key is down"); else Serial.println(" -> key is up"); delay(200); // print 5 lines per second, easy to read }

Quick Instructions

  • If this is the first time you use ESP32, see how to setup environment for ESP32 on Arduino IDE.
  • Wire the button module to the ESP32 as in one of the diagrams above. Check twice that VCC goes to 3V3.
  • Connect the ESP32 to your PC with the USB Type-C cable.
  • Open Arduino IDE and choose your ESP32 board (e.g. ESP32 Dev Module) and its COM port.
  • Paste the code above into a new sketch.
  • Click to the Upload button to build the code and send it to the ESP32.
How to upload ESP32 code on Arduino IDE
  • Open the Serial Monitor and set the baud rate to 9600.
How to open serial monitor on Arduino IDE
  • Do nothing for two or three seconds, press the button and hold it for about a second, then release it.
∞
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
OUT pin = 0 -> key is up OUT pin = 0 -> key is up OUT pin = 0 -> key is up OUT pin = 1 -> key is down OUT pin = 1 -> key is down OUT pin = 1 -> key is down OUT pin = 1 -> key is down OUT pin = 1 -> key is down OUT pin = 0 -> key is up OUT pin = 0 -> key is up
Ln 11, Col 1
ESP32 Dev Module on COM15
2

The value stays 0 while the cap is up. There is no random 0/1 noise, because the module's pull-down holds the pin firmly at LOW. If you see 1 all the time, check the OUT and VCC wires. They may be swapped.

ESP32 Code - Detect Press and Release Events (Debounce with delay)

Printing the level many times per second is not what a doorbell or a game key needs. Those projects want one message per press. This code remembers the last confirmed state. When a new reading is different, it waits 50 milliseconds for the contacts to stop bouncing, reads the pin again, and only then reports the change.

/* * This ESP32 code is created by esp32io.com * * This ESP32 code is released in the public domain * * For more detail (instruction and wiring diagram), visit https://esp32io.com/tutorials/esp32-button-module */ #define BUTTON_MODULE_PIN 21 // ESP32's GPIO21 connected to the OUT pin of the button module #define DEBOUNCE_DELAY 50 // milliseconds to wait for the contacts to settle int lastState = LOW; // the module rests at LOW (pull-down), so start with LOW void setup() { Serial.begin(9600); pinMode(BUTTON_MODULE_PIN, INPUT); // the module has its own pull-down resistor } void loop() { int reading = digitalRead(BUTTON_MODULE_PIN); if (reading != lastState) { // the level looks different from before delay(DEBOUNCE_DELAY); // wait until the bouncing is over (this blocks the loop) reading = digitalRead(BUTTON_MODULE_PIN); // read again to confirm if (reading != lastState) { // still different -> it is a real change if (reading == HIGH) Serial.println("The button is pressed"); else Serial.println("The button is released"); lastState = reading; // remember the confirmed state } } }

Quick Instructions

  • Keep the same wiring.
  • Paste this code into Arduino IDE and upload it to the ESP32.
  • Press the button three times, at any speed you like.
  • The Serial Monitor shows exactly one pair of lines for each press:
∞
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 released The button is pressed The button is released The button is pressed The button is released
Ln 11, Col 1
ESP32 Dev Module on COM15
2

This works well, but delay() blocks the loop: during those 50 milliseconds the ESP32 can do nothing else. For a project that also blinks LEDs, reads sensors or serves a web page, the next example is a better choice.

ESP32 Code - Button Module with the ezButton Library (Non-blocking Debounce)

The ezButton library checks the time with millis() instead of waiting, so the loop never stops. It gives you the steady (debounced) state of the button and tells you when a press or a release just happened. Because the module has its own pull-down resistor, the button object is created with the EXTERNAL_PULLDOWN mode. In this mode, HIGH means pressed. This mode needs ezButton version 1.0.6 or newer.

  • Button.setDebounceTime(50) sets the debounce time in milliseconds.
  • Button.loop() must be called first in every loop.
  • Button.getState() returns the steady state: HIGH (pressed) or LOW (released).
  • Button.isPressed() and button.isReleased() return true once for each event.
/* * This ESP32 code is created by esp32io.com * * This ESP32 code is released in the public domain * * For more detail (instruction and wiring diagram), visit https://esp32io.com/tutorials/esp32-button-module */ #include <ezButton.h> #define BUTTON_MODULE_PIN 21 // ESP32's GPIO21 connected to the OUT pin of the button module // EXTERNAL_PULLDOWN: the module has its own pull-down resistor, so HIGH means pressed ezButton button(BUTTON_MODULE_PIN, EXTERNAL_PULLDOWN); int lastSteadyState = -1; // used to print the steady state only when it changes void setup() { Serial.begin(9600); button.setDebounceTime(50); // 50 milliseconds debounce time } void loop() { button.loop(); // MUST be called first. It never blocks the loop if (button.isPressed()) Serial.println("The button is pressed"); if (button.isReleased()) Serial.println("The button is released"); int state = button.getState(); // the debounced (steady) state: HIGH or LOW if (state != lastSteadyState) { Serial.print("Steady state: "); Serial.println(state == HIGH ? "HIGH (held down)" : "LOW (not touched)"); lastSteadyState = state; } // other tasks can run here without waiting for the button }

Quick Instructions

  • Keep the same wiring.
  • In Arduino IDE, click to the Libraries icon on the left bar.
  • Type ezButton in the search box, then find the ezButton library by ArduinoGetStarted.com.
  • Click to the Install button. If an older version is already installed, update it to 1.0.6 or newer.
  • Search for ezButton created by ArduinoGetStarted.com and click the Install button.
∞
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
ESP32 Dev Module
Library Manager
Type:
All
Topic:
All
ezButton by ArduinoGetStarted.com
Button library supports debounce, pressed/released events and the press counting. It is easy to use with multiple buttons. The library can be used for push-button, momentary switches, toggle switch, magnetic contact switch (door sensor)... It is designed for not only beginners but also experienced users. More info
1.0.6
INSTALL
Newbiely.ino
···
1 void setup() {
Output
Serial Monitor
Ln 1, Col 1
ESP32 Dev Module on COM15
1
  • Paste the code above into Arduino IDE and upload it to the ESP32.
  • Press the button twice, holding it a little longer the second time.
∞
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
Steady state: LOW (not touched) The button is pressed Steady state: HIGH (held down) The button is released Steady state: LOW (not touched) The button is pressed Steady state: HIGH (held down) The button is released Steady state: LOW (not touched)
Ln 11, Col 1
ESP32 Dev Module on COM15
2

The first line shows the state at start-up. After that, each press gives one "pressed" line and one "released" line, and the steady state follows them. You can learn more about the ezButton library here. To use the key to switch an LED, see ESP32 - Button - LED and ESP32 - Button Toggle LED. For more about bouncing, see ESP32 - Button - Debounce.

Line-by-line Code Explanation

Each of the three ESP32 codes above has comments on its important lines. Please read the comments in the code!

Video Tutorial

Making video is a time-consuming work. If the video tutorial is necessary for your learning, please let us know by subscribing to our YouTube channel , If the demand for video is high, we will make the video tutorial.

Language References

※ OUR MESSAGES