ESP32 Push Button with ESP-IDF (Digital Input)

In this tutorial, we will learn to interface a push button with ESP32 using ESP-IDF. We will see how to configure GPIO pins as digital input pins. In other words, we will see how to read digital input from ESP32 and control a digital output. For demonstration purposes, we will build an ESP32 project in VS Code with an ESP-IDF extension. The project will enable the readers to understand how to configure GPIO pins of ESP32 as both input and output with a very basic example that will switch an LED on and off with a push button. We will connect a push button with the ESP32 GPIO pin that will be configured as an output pin. An LED will be connected with a digital input pin of the board. The Push Button’s value will be read, and the LED will be lit as a result.

Before we move forward, make sure you have the latest version of VS Code installed in your system with the ESP-IDF extension configured.

ESP32 GPIO Pins as Digital Input/output

ESP32 development board comes in a variety of models with varied numbers of GPIOs. There are 36 GPIO pins on the one we’ll be looking at. We can utilize the pins as they are configured by default or even modify them in the program code. The GPIO pins for the ESP32 DEVKIT V1 are depicted in the diagram below in their default configuration.

ESP32 DevKit V1 Pinout
ESP32 DEVKIT V1 Pinout


The 48 GPIO pins on the ESP32 chip utilized in this board are not all accessible via development boards. This indicates that not all GPIO pins are exposed in the pinout. There are 36 GPIO pins supported by the ESP32 Devkit, although not all of them may be utilized as digital output pins. Only 24 of the total 30 pins can be utilized for both digital input and output out of which GPIO34-GPIO39 can only be used as input pins.

The ESP32 DEVKIT does not expose GPIO6 to GPIO11. This is because these pins are internally connected to the integrated SPI flash on the ESP-WROOM-32 chip.

This time, while connecting the push button and the LED, we will use the GPIO pins on our ESP32 board as digital input and digital output pins, respectively. The GPIO connected with the push button gives us the digital input and the GPIO connected with the LED gives us the digital output.

The diagram below shows the GPIO pins for ESP32 which we will use to connect the push button and the LED. We will use GPIO13  to connect the LED and GPIO14 to connect the push button.

ESP32 Control LED with Push Button Pinout

For more in-depth information regarding ESP32 GPIO pins, refer to the article below:

ESP-IDF GPIO APIs for Digital Input & Digital Output

Before we move ahead, let us discuss some important functions that are required for GPIO programming with regard to this project.

ESP-IDF provides a gpio.h library that provides helpful functions to control the digital input and output pins of ESP32. For this project, we will be required to set a port as input or output port, set the output level of the output port and read the digital input port. Lets see how it will be accomplished.

The first step is to include the header file:

#include "driver/gpio.h"

Set Direction of GPIO Pins

Next, to configure a GPIO port as an input or output we will use the gpio_set_direction() function. It takes in two arguments. The first argument is the GPIO pin that we want to set. The second argument is the mode (input or output) we want to set the pin in. It will be either ‘GPIO_MODE_OUTPUT’ if you want to configure the port as an output or ‘GPIO_MODE_INPUT‘ if you want to configure the port as an input. In our case, we want to set the GPIO pin connected with the LED as an output pin and we want to set the GPIO pin connected with the push button as an input pin.

In the following line of code we are configuring GPIO27 as an output pin.

gpio_set_direction(GPIO_NUM_27, GPIO_MODE_OUTPUT);

In the following line of code we are configuring GPIO33 as an input pin.

gpio_set_direction(GPIO_NUM_33, GPIO_MODE_INPUT);

Set Output Level of Digital Pin

The next step is to set the output level of the GPIO port. For that we use the gpio_set_level() function. It also takes in two arguments. The first argument is the GPIO pin that we want to set the state of. The second argument is the state (0 or 1) we want to set. For setting the output of the pin HIGH, use ‘1’ as the second argument. Likewise, for setting the output of the pin LOW, use ‘0’ as the second argument.

In the following line of code we are setting GPIO27 to a HIGH state.

gpio_set_level(GPIO_NUM_27, 1);

Read Digital Input (Get Output Level of Input Pin)

To read the digital input we will use the gpio_get_level() function. This function takes in a single argument which is the digital input pin that has to be read. The function returns an integer value of 1 or 0 which denotes the state of the input pin as either HIGH or LOW respectively.

In the following line of code, we are reading the state of GPIO33.

int gpio_get_level(GPIO_NUM_33);

Push Button ESP32 Project Overview

The aim of our project is to control an LED by reading the input state of a GPIO pin connected with a push button. When the push button is pressed, the LED turns ON. When the push button is released, the LED turns OFF.

ESP32 Control LED with Push Button Project Overview 2

The diagram below shows the sequence of events. We will read the push buttons state, which will be either HIGH or LOW. If the logic state of the push button is HIGH, the LED will turn ON. Likewise, if the logic state of the push button is LOW, the LED will turn OFF.

ESP32 Pinout Control LED with Push Button Project Overview 1

Using a resistor, we will connect the push button to the ESP32 board. There are two different types of resistors that may be utilized in this project: pull-up and pull-down resistors. We will be employing pull-down resistors, which operate on the idea that when the push button is pressed, the input to the GPIO pin will be logic high state (1) and otherwise logic low state (0). An LED would turn on if the logic state was high, which is equivalent to 1, and off if the logic state was low, which is equivalent to 0. If we use pull-up resistors, it works the other way around.

ESP32 Control LED with Push button Schematic diagram & Hardware Setup

We will require the following components for this project.

Required Components:

  1. ESP32 development board
  2. 5mm LED
  3. 220 ohm resistor
  4. 10k ohm resistor
  5. Breadboard
  6. Connecting wires

The diagram below shows how to setup the circuit for this project.

ESP32 ESP-IDF Control LED with Push Button schematic diagram

We have used GPIO27 to connect with the anode pin of the LED through a 220 ohm current limiting resistor. The cathode pin of the LED is connected with the GND pin of ESP32.

There are four terminals on the push button. The ESP32 supplies power to one terminal at 3.3 volts, while the second terminal is linked through GPIO33 and a 10k ohm pull-down resistor via GPIO33. The common ground is connected to the resistor’s opposite end.

Feel free to use any other appropriate ESP32 digital output pin to connect with the LED and ESP32 digital input pin to connect with the push button.

This is how our circuit looks like after connecting all the components.

Push Button ESP32 ESP-IDF GPIO input

ESP32 Control LED with Push button

Open your VS Code and create a new ESP-IDF project. Now head over to the main.c file. We will define the functions and the program code here.

ESP32 Push Button Code

This is the code that we will use to control LED with the push button.

#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#define LED_PIN  27
#define PUSH_BUTTON_PIN  33

void app_main(void)
{
    gpio_set_direction(LED_PIN, GPIO_MODE_OUTPUT);   
    gpio_set_direction(PUSH_BUTTON_PIN, GPIO_MODE_INPUT);

    while(1) {       
        if (gpio_get_level(PUSH_BUTTON_PIN) == 1)
        {  
            gpio_set_level(LED_PIN, 1);        
        } 
        else
        {
            gpio_set_level(LED_PIN, 0);        
        }

        vTaskDelay(1);
    }
} 
ESP32 Control LED with Push Button Project Script

How the Code Works?

Firstly, we will start by including the necessary libraries for this project. This includes the driver/gpio.h library as we have to work with GPIO pins and FreeRTOS libraries as we want to add a delay.

#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

We have connected the LED at GPIO27. Therefore, we will define a variable called ‘LED_PIN’ that will hold the GPIO pin 27. This will be used later on in the code to control the digital output.

We have connected the push button at GPIO33. Therefore, we will define a variable called ‘PUSH_BUTTON_PIN’ that will hold the GPIO pin 33. This will be used later on in the code to read the digital input.

#define LED_PIN  27
#define PUSH_BUTTON_PIN  33
Configuring GPIO for digital input/output

Inside the loop function, the next step is to configure the LED_PIN as an output and PUSH_BUTTON_PIN as an input. We will set the direction of the pin as an input or output using the gpio_set_direction() function. This function takes in two arguments. The first argument is the GPIO pin and the second argument is the mode (input or output) we want to set the pin in. In our case, we want to set the LED_PIN as an output pin and the PUSH_BUTTON_PIN as an output pin.

gpio_set_direction(LED_PIN, GPIO_MODE_OUTPUT);
gpio_set_direction(PUSH_BUTTON_PIN, GPIO_MODE_INPUT);

Next, we will read the state of the PUSH_BUTTON_PIN by using gpio_get_level() and pass the GPIO pin connected with the push button as an argument inside it. Through an if-else statement, we will check if this digital input state is ‘1’ or not. If it is ‘1’, which means the push button was pressed, then turn the LED ON. Otherwise, turn the LED OFF. Using gpio_set_level(), we will pass the first argument as LED_PIN whose state we want to set, and the second argument as the state we want to set. It will be either ‘1’ or ‘0.’ When the second argument is ‘1’, then the LED turns ON. Likewise, when the second argument is ‘0’, the LED turns OFF.

if (gpio_get_level(PUSH_BUTTON_PIN) == 1)
        {  
            gpio_set_level(LED_PIN, 1);        
        } 
        else
        {
            gpio_set_level(LED_PIN, 0);        
        }

Moreover, we will add a delay of 1 tick (10ms) so that the watchdog timer does not get triggered.

vTaskDelay(1);

Compiling the Sketch

To flash your chip, type the following command in the serial terminal. Remember to replace the COM port with the one through which your board is connected.

idf.py -p COMX flash monitor
ESP32 Control LED with Push Button Project flash chip

After the code flashes successfully, press the push button to turn the LED on. When the push button is released, the LED turns off.

ESP32 ESP-IDF Control LED with Push Button Project demo

Video demo:

You may also like to read:

2 thoughts on “ESP32 Push Button with ESP-IDF (Digital Input)”

  1. Hello,
    First thanks for the example guide.
    I have problem, when I flashed this code into my ESP32 dev board my IDF serial monitor showed below phrase repeatedly, I have no idea bout it, can you help me to clear this.
    E (430298) task_wdt: Task watchdog got triggered. The following tasks did not reset the watchdog in time:
    E (430298) task_wdt: – IDLE (CPU 0)
    E (430298) task_wdt: Tasks currently running:
    E (430298) task_wdt: CPU 0: main
    E (430298) task_wdt: CPU 1: IDLE
    E (430298) task_wdt: Print CPU 0 (current core) backtrace

    Backtrace:0x400D5BD8:0x3FFB07F0 0x4008241D:0x3FFB0810 0x400D3D61:0x3FFB5EA0 0x400D49AC:0x3FFB5ED0 0x400E39E7:0x3FFB5EF0 0x40087E29:0x3FFB5F10
    0x400d5bd8: task_wdt_isr at C:/Users/pc/esp/esp-idf/components/esp_common/src/task_wdt.c:189

    0x4008241d: _xt_lowint1 at C:/Users/pc/esp/esp-idf/components/freertos/port/xtensa/xtensa_vectors.S:1105

    0x400d3d61: gpio_get_level at C:/Users/pc/esp/esp-idf/components/driver/gpio.c:244

    0x400d49ac: app_main at C:\Users\pc\gpio-test\build/../main/main.c:21

    0x400e39e7: main_task at C:/Users/pc/esp/esp-idf/components/freertos/port/port_common.c:145 (discriminator 2)

    0x40087e29: vPortTaskWrapper at C:/Users/pc/esp/esp-idf/components/freertos/port/xtensa/port.c:168

    E (430298) task_wdt: Print CPU 1 backtrace

    Reply
  2. Hello. I have a code that currently has a web interface. When I click my virtual button it runs my 30 second sequence

    How do I add a physical momentary button to trigger the same sequence? By button I mean I simply want to push and release the button and it will run the same code as if I pressed my virtual button

    I need help with the code to so this
    Thanks

    Reply

Leave a Comment