Introduction
In this post, you will learn about controlling ESP32 GPIO using APIs in ESP-IDF. We will explore functions in gpio.h
to make a LED on or off and detect a button pressed by reading digital input from GPIO pins.
Components Used
In this article, we will implement a practical project which uses the following components
QTY | Component Name | Buy on amazon.com |
---|---|---|
1 | ESP32 DevKit C | Amazon |
1 | LED Kit | Amazon |
1 | Resistor Kit | Amazon |
1 | Push button | Amazon |
1 | Breadboard | Amazon |
1 | Jumper Wire Kit | Amazon |
Affiliate Disclosure: When you click on links in this section and make a purchase, this may result in this site earning a commission at no extra cost to you.
ESP-IDF GPIO APIs
In this section, we will examine the library gpio.h
in ESP-IDF and see basic functions to control digital input and output ports of ESP32. Basic tasks to configure I/O ports include setting a port as input or output port, setting and clearing an output port and reading digital input port. We will go through one by one.
Control Digital Output
To configure a GPIO pin as output, use the function gpio_set_direction()
and pass in the first argument as the pin to be configured, the second argument is GPIO_MODE_OUTPUT
. Note that for the pin number, you need to use a value defined in enumeration gpio_num_t
, that is, for pin 0, pass in GPIO_NUM_0
. The example below configure GPIO0 as output port.
gpio_set_direction(GPIO_NUM_0, GPIO_MODE_OUTPUT);
To set a GPIO output pin high or low, you use the function gpio_set_level()
. This function accepts two arguments: first argument is the pin number, second argument is the output level. If you want the pin to output high, use 1 in the second argument. Otherwise, pass 0 in the second argument. For instance, this example shows how to set GPIO_NUM_0
high.
gpio_set_level(GPIO_NUM_0, 1);
Read Input Pin
To configure a GPIO as Input pin, you use the function gpio_set_direction()
, too. However, this time you need to pass in GPIO_MODE_INPUT
as the second argument. This snippet shows how to configure GPIO1 as an input port.
gpio_set_direction(GPIO_NUM_1, GPIO_MODE_INPUT);
To read the digital input level of a GPIO pin, use the function gpio_get_level()
. This function returns 0 or 1 depending on the voltage level of GPIO pin is low or high.
int gpio_get_level(GPIO_NUM_1);
ESP32 GPIO Project Example
To demonstrate the usage of the above functions, we will implement a simple project in which there is one LED and one button. If the button is not pressed, the LED is turned off. If the button is pressed, the LED is turned on.
Hardware description
In this project, we will be using ESP32 DevKitC, a LED connected in series with a resistor, and a push button. If you are using other development kit, you will need to check which GPIO pins are used to connect to a LED and button.
- Connect GPIO 32 (pin 7 on the left hand side of the board with USB on the bottom) with a LED and a resistor. This pin is used to drive the LED and to turn it on or off.
- Connect GPIO 36 (pin 3 on the left hand side of the board) with the push button.
The circuit is shown in the below figure
Code
The below code performs the task described above.
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#define LED_PIN GPIO_NUM_32
#define BUTTON_PIN GPIO_NUM_36
void app_main(void)
{
gpio_set_direction(LED_PIN, GPIO_MODE_OUTPUT);
gpio_set_direction(BUTTON_PIN, GPIO_MODE_INPUT);
while(1) {
if (gpio_get_level(BUTTON_PIN) == 0) { // If button is pressed
gpio_set_level(LED_PIN, 1); // Turn the LED on
} else {
gpio_set_level(LED_PIN, 0); // Turn the LED off
}
vTaskDelay(1); // Add 1 tick delay (10 ms) so that current task does not starve idle task and trigger watchdog timer
}
}
Code explanation
- You first need to include the
gpio.h
driver in order to use GPIO APIs. - You then define the GPIO pins as
LED_PIN
andBUTTON_PIN
. This allows you quickly modify the pins when necessary and eliminate magic numbers in your code, hence make it easier to read. - The next step is to configure
LED_PIN
as output port,BUTTON_PIN
as input port. - In the main loop inside
app_main()
, you check if a button is pressed by reading input level ofBUTTON_PIN
usinggpio_get_level()
. If it is pressed, turn the LED on by callinggpio_set_level()
. - A delay of 1 tick (equal to 10 ms since the tick frequency is 100 Hz) is added in the main loop to avoid the main task consume all CPU resources, so that idle task can run and clear the watchdog timer. If there’s no delay, idle task has lower priority than the main task and can not run, hence watchdog timer will be triggered to reset the chip and your code will not work properly.
Building and flashing
To build and flash the code to target ESP32 board, make sure all the necessary tools are installed.
All you need to do now is to run
get_idf
idf.py build
Then wait until the build process completes. Next, determine the port that your board is connecting to and run the following command to flash the code on the ESP32.
idf.py -p [PORT] flash
After flashing, you should see that pressing the button will turn the LED light on. Otherwise, the LED light will be off.
Wrapping Up
In this tutorial, you have learnt about using APIs in ESP-IDF to control GPIO pins of ESP32. Your knowledge is solidified by doing a practical project. To learn more, the ESP32 official documentation is a good place to go. You can find more GPIO API functions in the API reference page. If you have any comments, leave it in the comment section. See you in the next tutorials.