В этом вводном руководстве по ESP32 с использованием ESP-IDF мы познакомим вас с некоторыми основными понятиями программирования ESP32 с помощью ESP-IDF в VS Code. Будут рассмотрены примеры логирования, генерации задержек, ввода с клавиатуры и мигания встроенного светодиода ESP32.

Прежде чем продолжить, убедитесь, что у вас установлена последняя версия VS Code и настроено расширение ESP-IDF:
- Установка ESP32 ESP-IDF на Windows и его интеграция с Visual Studio Code
- Установка ESP32 ESP-IDF на Linux Ubuntu
В двух предыдущих уроках мы рассмотрели, как установить, скомпилировать, собрать и прошить код в ESP32 с помощью esp-idf. В этом уроке мы рассмотрим несколько примеров для начала работы, таких как логирование, включение отладочной информации и простая программа мигания светодиода.
Также про начало работы с ESP32 с использованием ESP-IDF вы можете прочитать в следующей статье на нашем сайте - эти две статьи как бы дополняют друга, какие то моменты лучше освещены в одной статье, другие моменты - в другой статье.
Вход в систему ESP-IDF
ESP-IDF обладает некоторыми возможностями логирования, которые мы рассмотрим в первую очередь, поскольку они чрезвычайно полезны и используются довольно часто. Сначала мы включим файл «esp_log.h» в наши скрипты.
|
1 |
#include "esp_log.h" |
Вместо простого вывода сообщения с помощью команды printf, мы можем использовать различные типы логов. Библиотека логирования ESP-IDF поддерживает следующие пять уровней логирования:
- ESP_LOGE: Ведение журнала ошибок (самый низкий уровень)
- ESP_LOGW: Ведение журнала предупреждений
- ESP_LOGI: Информационный журнал
- ESP_LOGD: Отладочная инструкция
- ESP_LOGV: Подробный (самый высокий уровень)
Для регистрации ошибки мы будем использовать следующую функцию:
|
1 |
ESP_LOGE(tag, format, __VA_ARGS__) |
Примечание: в функции ESP_LOGE() буква 'E' означает ошибку.
Функция логирования принимает два аргумента. Первый аргумент — это тег, а второй — отформатированная строка. Если вы зададите разные теги в разных участках кода, это упростит мониторинг этих частей кода.
В нашем скрипте мы укажем в качестве первого параметра 'LOG', который является тегом, а в качестве второго аргумента — отформатированную строку 'This is an error'. Таким образом, наша функция регистрации ошибок будет выглядеть примерно так:
|
1 |
ESP_LOGE(LOG, "This is an error"); |
Аналогичным образом мы определим разделы журналов для предупреждений, информационных сообщений, отладочной информации и подробного вывода соответственно.
|
1 2 3 4 |
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"); |
Тестирование скрипта для ведения логов.
Вот как выглядит наш скрипт на данный момент:
Теперь давайте скомпилируем этот код. Откройте последовательный терминал, введите следующую команду и нажмите Enter:
|
1 |
idf.py flash monitor |
Вот как выглядит результат после успешной прошивки микросхемы:
Давайте разберемся, что означает этот вывод. Слева направо: E означает ошибку, W — предупреждение, а I — информацию. Числа в скобках указывают время в миллисекундах после запуска приложения и вызова данной функции.
Обратите внимание, что журналы ошибок, предупреждений и информации отображаются, но отладочные сообщения и подробный вывод отсутствуют. По умолчанию они отключены. Нам придется изменить настройки самостоятельно.
Включите режимы отладки и подробного вывода с помощью Menuconfig
Мы будем использовать menuconfig для включения отладочных и подробных настроек. Откройте командную строку ESP-IDF 4.3 и дождитесь загрузки переменных окружения. Теперь укажите путь к текущему корневому каталогу, как показано ниже, а затем откройте menuconfig с помощью команды idf.py menuconfig.
Эта команда открывает конфигурацию среды разработки Espressif IoT. Перейдите в раздел ‘Component config’ («Конфигурация компонентов»).
Далее перейдите в раздел ‘Log output’ («Вывод в журнал»).
Затем перейдите к разделу ‘Default log verbosity (Info)’ («Уровень детализации журнала по умолчанию (Информация)»).
Теперь выберите ‘Verbose’. Здесь мы выбираем минимальный уровень детализации. Это означает, что мы будем получать сообщения в режиме подробного вывода и сообщения более высокого уровня (ошибки, предупреждения, информация, отладка). Однако, если бы мы выбрали ‘debug’ («Отладка»), то вывод отображал бы сообщения до уровня отладки, а подробный вывод отсутствовал бы. По сути, минимальный уровень устанавливается в следующем порядке:
Нажмите 'Q' для выхода и сохраните настройки, нажав 'Y'.
Включите режимы отладки и подробного вывода в коде
Мы также можем включить отладку и подробный вывод в скрипте программы. Добавьте следующую строку кода для установки конфигурации с помощью функции esp_log_level_set(). Она принимает два аргумента. Первый аргумент — это тег, а второй — фактический уровень, который мы хотим установить в качестве минимального уровня.
В нашем скрипте мы укажем в качестве первого параметра 'LOG', который является тегом, а в качестве второго аргумента — 'ESP_LOG_INFO', уровень логирования. Мы устанавливаем для тега 'LOG' уровень info. Таким образом, уровень логирования для тега LOG будет выглядеть примерно так:
|
1 |
esp_log_level_set("LOG", ESP_LOG_INFO); |
Кроме того, мы добавим дополнительный набор уровней логирования с другим тегом. В первом наборе мы использовали тег 'LOG'. Во втором наборе мы установим тег 'TAG'.
Вот как сейчас выглядит наш скрипт:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
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); } |
Теперь запустите программу.
Вот как теперь выглядит вывод. Те сообщения с тегом 'LOG' выводились до уровня info. Это потому, что мы установили для тега 'LOG' уровень info. Однако сообщения с тегом 'TAG' выводились до уровня verbose, потому что именно это мы задали в menuconfig.
Генерация задержек с помощью ESP-IDF на ESP32
Ещё одна важная концепция, которая часто используется, — это включение задержек в наши программные скрипты.
Для генерации задержек мы будем использовать FreeRTOS (на нашем сайте вы также можете более подробно прочитать про использование FreeRTOS в ESP32 с помощью ESP-IDF). Поэтому сначала мы включим необходимые для неё библиотеки в наш программный скетч.
|
1 2 |
#include "freertos/FreeRTOS.h" #include "freertos/task.h" |
Внутри функции цикла мы добавим задержку. Для генерации задержки мы будем использовать функцию «vTaskDelay». Она принимает в качестве первого параметра целое число (uint32), которое является константой TickType, определяющей количество тактов, которые нужно задержать. Это число соответствует такту, то есть частоте микросхемы.
|
1 |
vTaskDelay(1000); |
Чтобы перевести тактовые секунды в миллисекунды, мы разделим их на portTICK_PERIOD_MS. Параметр portTICK_PERIOD_MS является частью директивы #defines. Он настраивается при компиляции скетча и по умолчанию устанавливается равным скорости работы микросхемы. Таким образом, 1000, разделенное на количество тактов, в течение которых работает микросхема, даст нам миллисекунды.
|
1 |
vTaskDelay(1000 /portTICK_PERIOD_MS); |
Пример скетча
Давайте запустим следующий скетч, чтобы увидеть, как генерируется задержка. В этом скетче мы определили TAG как 'DELAY'. Это будет заменено внутри функции ESP_LOGI() на первый параметр. В качестве второго параметра мы будем увеличивать значение целочисленной переменной 'i', которая изначально имеет значение 0. Будет сгенерирована задержка, после которой будет выведена информация в лог.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#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++); } } |
Теперь прошейте микросхему, введя в терминале следующую команду:
Вот как выглядит вывод. Каждую секунду печатается новое число.
Пример мигания светодиода на ESP32 ESP-IDF
Теперь перейдём к одному из самых распространённых первых примеров, который выполняется с использованием ESP32. Мы покажем, как заставить мигать встроенный светодиод ESP32 с помощью ESP-IDF в VS Code.
Для начала создайте новый проект ESP-IDF и перейдите к файлу main.c.
Для начала мы подключим необходимые библиотеки для этого проекта. Это включает библиотеку driver/gpio.h, поскольку нам нужно работать с контактами GPIO, и библиотеки FreeRTOS, так как мы хотим добавить задержку для мигания светодиода.
|
1 2 3 |
#include "driver/gpio.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" |
На плате разработки ESP32 встроен светодиод, подключенный к выводу GPIO2. Поэтому мы определим переменную с именем 'LED_PIN', которая будет хранить значение вывода GPIO2. Она будет использоваться позже в коде для управления светодиодом.
|
1 |
#define LED_PIN 2 |
Настройка GPIO для мигания светодиода
Следующий шаг — настройка вывода LED_PIN в качестве вывода GPIO. Для этого мы воспользуемся следующей функцией:
Укажите контакт LED_PIN в качестве параметра внутри этой функции.
|
1 |
gpio_pad_select_gpio(LED_PIN); |
Затем мы зададим направление вывода в качестве выходного сигнала, используя следующую функцию:
Эта функция принимает два аргумента. Первый аргумент — это номер контакта GPIO, а второй — режим (вход или выход), в который мы хотим установить этот контакт. В нашем случае мы хотим установить контакт LED_PIN как выходной.
|
1 |
gpio_set_direction(LED_PIN, GPIO_MODE_OUTPUT); |
Для мигания светодиода мы будем использовать следующие строки кода внутри функции цикла.
|
1 2 3 4 5 6 7 |
int ON = 0; while(true) { ON = !ON; gpio_set_level(LED_PIN, ON); vTaskDelay(1000/ portTick_Period_MS); } |
Сначала мы создаём целочисленную переменную с именем 'ON', которая хранит значение 0. Это флаг, который будет отслеживать, включен светодиод или выключен. Внутри цикла while мы переключаем значение переменной ON. Используя gpio_set_level(LED_PIN, ON), мы устанавливаем значение LED_PIN равным значению, сохранённому в переменной ON. Затем мы добавляем задержку перед повторным запуском цикла.
Для добавления задержки в 1 секунду между изменениями состояния светодиода мы будем использовать функцию vTaskDelay(). Эта задержка вызовет эффект мигания светодиода.
Скрипт проекта "Мигание светодиода"
Это скрипт, который мы будем использовать для мигания встроенного светодиода ESP32.
Для прошивки микросхемы введите следующую команду в последовательном терминале. Не забудьте указать правильный COM-порт, через который подключена ваша плата.
Вот что мы получаем в терминале после успешной прошивки.
Здесь вы можете наблюдать, как встроенный светодиод ESP32 включается и выключается каждую секунду.
Считывание ввода с клавиатуры в ESP32 ESP-IDF
Наконец, мы покажем вам, как считывать ввод с клавиатуры от пользователя. Существует множество ситуаций, когда необходимо получить доступ к вводу с клавиатуры, например, при выборе из списка вариантов.
Сначала создадим две переменные. Одна из них будет типа char и будет хранить символ, введенный с клавиатуры.
|
1 |
char character = 0; |
Вторая переменная — это массив символов под названием 'str', который будет содержать символы с клавиатуры для формирования полной строки.
|
1 |
char str[100]; |
Следующая строка кода гарантирует, что все элементы нашего массива 'str' изначально будут установлены в 0.
|
1 |
memset(str,0,sizeofstr()); |
Наша цель — продолжать получать ввод с клавиатуры от пользователя до тех пор, пока не будет нажата клавиша Enter. Это означает, что вводимый символ должен быть не '\n'.
Функция getchar() возвращает целое число и сохраняет его в переменной 'character'. Поскольку getchar() является неблокирующей функцией, это означает, что если символ не введен, переменная character будет содержать значение 0xff. Поэтому мы добавим дополнительное условное выражение для проверки, нажал ли пользователь клавишу на клавиатуре, проверяя, равен ли символ 0xff. Если нет, мы добавим этот символ к нашей строке. Эта строка также будет выведена на последовательный терминал, чтобы пользователь мог видеть, что он вводит.
|
1 2 3 4 5 6 7 8 9 10 |
while(character!= '\n') { character =getchar(); if(character!= 0xff) { str[strlen(str)] = character; printf("%c",character); } vTaskDelay(1000 /portTICK_PERIOD_MS); } |
Кроме того, мы добавим задержку в 1 секунду, чтобы не возникало проблем с вводом и сохранением клавиш в непрерывном цикле. Для генерации задержки мы будем использовать функцию vTaskDelay(), доступную в задачах FreeRTOS.
|
1 |
vTaskDelay(1000 /portTICK_PERIOD_MS); |
В заключение мы выведем на экран символы, введенные пользователем в последовательный терминал:
|
1 |
printf("User Entered: %s\n", str); |
Скрипт для обработки ввода с клавиатуры
Это скрипт, который мы будем использовать для приема ввода с клавиатуры от пользователя и вывода его в последовательный терминал.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
#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); } |
Для прошивки микросхемы введите следующую команду в последовательном терминале. Не забудьте указать правильный COM-порт, через который подключена ваша плата.
После успешной прошивки микросхемы введите символы и нажмите клавишу Enter. В нашем случае мы ввели символы 'welcome to esp32tutorials.com' и затем нажали Enter.
После нажатия клавиши Enter в последовательном терминале отобразился следующий вывод:
52 просмотров

























