In this getting started tutorial on ESP32 using ESP-IDF, we will introduce you to some basic concepts while programming ESP32 using ESP-IDF in VS Code. This will include examples of logging, generating delays, keyboard input and blinking the onboard LED of ESP32.
If you have not installed esp-idf on your Windows or Linux machine, you can follow these two guides:
In the above two tutorials, we have seen how to install, compile, build and flash code to ESP32 using esp-idf. In this tutorial, we will see some getting started examples such as logging, enable debug information and a simple LED blinking program.
Logging in ESP-IDF
The ESP-IDF comes with some logging abilities that we will look into first as they are extremely useful and used quite often. We will first include the “esp_log.h” file in our scripts.
#include "esp_log.h"
We can use different types of logs instead of just printing a statement using the printf command. This ESP-IDF logging library supports the following five log levels:
- ESP_LOGE: Error Logging (lowest level)
- ESP_LOGW : Warning Logging
- ESP_LOGI : Informational Log
- ESP_LOGD : Debug Statement
- ESP_LOGV : Verbose(highest level)
To log an error we will use the following function:
ESP_LOGE(tag, format, __VA_ARGS__)
Note: In ESP_LOGE(), the ‘E’ stands for error.
The log function takes in two arguments. The first argument is the tag and the second argument is a formatted string. If you set different tags at different sections of the code, it becomes easier to monitor that part of the code.
In our script, we will specify ‘LOG’ as the first parameter which is the tag and ‘This is an error’ as the formatted string in place of the second argument. Hence our error logging function looks something like this:
ESP_LOGE(LOG, "This is an error");
Likewise we will define the logs for warning, informational, debug and verbose respectively.
ESP_LOGW(LOG, "This is a warning");
ESP_LOGI(LOG, "This is an info");
ESP_LOGD(LOG, "This is a debug");
ESP_LOGV(LOG, "This is a verbose");
Testing the Script for Logging
This is how our script looks like at the moment:
Now let us compile this code. Open the serial terminal and type the following command and press enter:
idf.py flash monitor
This is how the output looks like once the chip is successfully flashed:
Lets understand what this output means. From left to right: the E stands for error, W for warning and I for information. The numbers in between the brackets give the time in milliseconds after the application started and that particular function was called.
Note that the error, warning and info logs can be seen but the debug statement and verbose is not present. By default, these are not turned on. We will have to change the settings ourselves.
Enable Debug and Verbose using Menuconfig
We will use the menuconfig to turn the debug and verbose settings on. Open ESP-IDF 4.3 CMD shell and wait till the environment variables are loaded. Now set the path of your current root directory as shown below and then open menuconfig using idf.py menuconfig.
This command opens the Espressif IoT Development Framework Configuration. Head over to ‘Component config.’
Next go to ‘Log output.’
Then go to ‘Default log verbosity (Info).’
Now select ‘Verbose.’ Here we are selecting the minimal level to verbose. This means we will get the loggings for verbose and the ones higher than that (error, warning, info, debug). However, if we had selected ‘debug’ then the output will show loggings till debug and verbose will not be present. Basically, it sets the minimum level in this particular order:
Press ‘Q’ to quit and save configuration by pressing Y.
This closes the configuration window. Now close the ESP-IDF command window as well.
Head back to your VS Code project and rebuild the script again. It will take a longer time to compile as the menuconfig was changed. Now you can view the output showing the loggings for error, warning, info, debug and verbose. Moreover, a greater amount of data is shown in the output as compared to before, when debug and verbose were set off.
Enable Debug and Verbose in Code
We can also enable debug and verbose in our program script. Include the following line of code to set the configuration using esp_log_level_set(). It takes in two arguments. The first argument is the tag and the second argument is the actual level that we want to set as the minimum level.
In our script, we will specify ‘LOG’ as the first parameter which is the tag and ‘ESP_LOG_INFO’ as the log level in place of the second argument. We are setting the tag ‘LOG’ to level info. Hence our set log level for the LOG tag looks something like this:
esp_log_level_set("LOG", ESP_LOG_INFO);
Moreover, we will include an additional set of log levels with a different tag. In the first set, we used the tag as ‘LOG.’ In the second set we will set the tag as ‘TAG.’
This is how our script looks like now:
include <stdio.h>
#include "esp_log.h"
void app_main(void)
{
esp_log_level_set("LOG", ESP_LOG_INFO);
ESP_LOGE("LOG", "This is an error);
ESP_LOGW("LOG", "This is a warning);
ESP_LOGI("LOG", "This is an info);
ESP_LOGD("LOG", "This is a debug);
ESP_LOGV("LOG", "This is a verbose);
ESP_LOGE("TAG", "This is an error);
ESP_LOGW("TAG", "This is a warning);
ESP_LOGI("TAG", "This is an info);
ESP_LOGD("TAG", "This is a debug);
ESP_LOGV("TAG", "This is a verbose);
}
Now run the program.
This is how the output looks like now. The ones with the tag ‘LOG’ were printed till info. This is because we set the tag ‘LOG’ to level info. However, the ones with the tag ‘TAG’ were printed all the way till verbose. because that is what we set in menuconfig.
ESP32 Generating Delays with ESP-IDF
Another important concept that is used a lot is the incorporations of delays in our program scripts.
We will use FreeRTOS to generate delays. Therefore we will first include its necessary libraries in our program sketch.
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
Inside the loop function, we will add the delay. To generate a delay, we will use “vTaskDelay.” It takes in the first parameters an integer (uint32) which is the constant TickType depicting the ticks to delay. This number corresponds to the tick which is the frequency of the chip.
vTaskDelay(1000);
To convert tick into milliseconds, we will divide it by portTICK_PERIOD_MS. The portTICK_PERIOD_MS is part of the #defines. It gets configured when we compile our sketch and by default is set to how fast the chip is running. So basically 1000 divided by amount of ticks that the chip is running will give us the milliseconds.
vTaskDelay(1000 /portTICK_PERIOD_MS);
Sample Sketch
Lets run the following sketch to see how a delay is generated. In the following sketch we have defined TAG as ‘DELAY.’ This will be replaced inside the ESP_LOGI() function in place of the first parameter. For the second parameter we will increment the value of an int variable ‘i’ that initially holds the value 0. A delay will be generated after which the info log will get printed.
#include <stdio.h>
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#define TAG "DELAY"
void app_main(void)
{
int i = 0;
while(1)
{
vTaskDelay(1000 / portTICK_PERIOD_MS);
ESP_LOGI(TAG, "in loop %d", i++);
}
}
Now flash the chip by entering the following command in the terminal:
This is how the output looks like. Every second, a new number is getting printed.
ESP32 ESP-IDF LED Blinking Example
Now let us proceed to one of the most common first example that is performed using ESP32. We will show you how to blink the on-board LED of ESP32 using ESP-IDF in VS Code.
To start off, create a new ESP-IDF project and head over to the main.c file.
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 in order to blink the LED.
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
The ESP32 development board has a built-in LED connected at GPIO2. Therefore, we will define a variable called ‘LED_PIN’ that will hold the GPIO pin 2. This will be used later on in the code to control the LED.
#define LED_PIN 2
Configuring GPIO for LED Blink
The next step is to configure the LED_PIN as a GPIO. To do that, we will use the following function:
Specify the LED_PIN as a parameter inside this function.
gpio_pad_select_gpio(LED_PIN);
Then, we will set the direction of the pin as an output using the following 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.
gpio_set_direction(LED_PIN, GPIO_MODE_OUTPUT);
To blink the LED, we will use the following lines of code inside the loop function.
int ON = 0;
while(true)
{
ON = !ON;
gpio_set_level(LED_PIN, ON);
vTaskDelay(1000/ portTick_Period_MS);
}
Here we are first creating an integer variable called ‘ON’ which holds the value 0. This is a flag that will monitor whether the LED is ON or OFF. Inside the while loop, we toggle the ON variable. Using gpio_set_level(LED_PIN, ON), we will set the LED_PIN to the value saved in ON. Then we will add a delay before it loops again.
To add a delay of 1 second between changing the state of the LED, we will use vTaskDelay() function. This delay will cause a blinking effect of the LED.
LED Blink Project Script
This is the script that we will use to blink the on-board LED of ESP32.
To flash your chip, type the following command in the serial terminal. Remember to enter the correct COM port through which your board is connected.
This is the output we get in the terminal after it flashes successfully.
Here you can view, the onboard LED of ESP32 turning ON and OFF after every second.
ESP32 ESP-IDF Take Keyboard Input
Lastly, we will show you how to acquire keyboard input from the user. There are numerous instances where it is required to access the input from a keyboard for example selecting from a list of options.
First we will create two variables. One is of type char, which holds the character captured from the keyboard.
char character = 0;
The second variable is an array of characters called ‘str’ that will hold the characters from the keyboard to form a complete string.
char str[100];
The following line of code will make sure all elements of our array ‘str’ are initially set to 0
memset(str,0,sizeofstr());
Our aim to to keep on obtaining keyboard input from the user until the enter key is pressed. This means until the variable character is not ‘\n.’
The function getchar() returns an integer and saves it in the variable ‘character.’ As getchar() is a nonblocking function which means that if no character is entered then the character variable will hold 0xff. Hence we will add an additional if statement to check if the user pressed a keyboard key or not by checking if character is equal to 0xff or not. In the case it is not equal, then we will concatenate that character to our string. This string will also be printed on the serial terminal so that the user can see what they are entering.
while(character!= '\n')
{
character =getchar();
if(character!= 0xff)
{
str[strlen(str)] = character;
printf("%c",character);
}
vTaskDelay(1000 /portTICK_PERIOD_MS);
}
Moreover we will add a delay of 1 second so there are no issues in entering and saving the keys in the continuous loop. We will use the vTaskDelay() function available in the FreeRTOS tasks to generate the delay.
vTaskDelay(1000 /portTICK_PERIOD_MS);
Finally, we will print the characters entered by the user in the serial terminal:
printf("User Entered: %s\n", str);
Take Keyboard Input Script
This is the script that we will use to take keyboard input from the user and print it in the serial terminal.
#include <stdio.h>
#include <string.h>
#include "freertos/freeRTOS.h"
#include "freertos/task.h"
void app_main(void)
{
char character = 0;
char str[100];
memset(str,0,sizeof(str));
while(character!= '\n')
{
character =getchar();
if(character!= 0xff)
{
str[strlen(str)] = character;
printf("%c",character);
}
vTaskDelay(1000 /portTICK_PERIOD_MS);
}
printf("User Entered: %s\n", str);
}
To flash your chip, type the following command in the serial terminal. Remember to enter the correct COM port through which your board is connected.
After the chip flashes successfully, enter the characters and press the enter key. In our case we have typed the characters ‘welcome to esp32tutorials.com’ and then pressed enter.
After the enter key is pressed, we got the following output printed in the serial terminal:
Where to go next?
- ESP32 GPIO with ESP-IDF with LED Blinking example
- ESP32 Push Button with ESP-IDF (Digital Input)
- ESP32 ADC with ESP-IDF Measure Analog Inputs
- ESP32 PWM ESP-IDF LED Brightness Control Example
We are a team of experienced Embedded Software Developers with skills in developing Embedded Linux, RTOS, and IoT products from scratch to deployment with a demonstrated history of working in the embedded software industry. Contact us for your projects: admin@esp32tutorials.com