Использование ШИМ в ESP32 с помощью ESP-IDF


В этом уроке мы научимся генерировать ШИМ-сигналы (широтно-импульсной модуляции, в англ. PWM - Pulse Width Modulation) с помощью платы ESP32, используя ESP-IDF. Мы рассмотрим, как генерировать ШИМ-сигналы с помощью аппаратного обеспечения LEDC на ESP32 и подключать эти сигналы к любому из выводов GPIO платы ESP. Для демонстрации мы будем управлять яркостью светодиода, изменяя коэффициент заполнения выходного сигнала с помощью потенциометра. С помощью потенциометра мы преобразуем значение АЦП в коэффициент заполнения ШИМ сигнала.

Прежде чем продолжить, убедитесь, что у вас установлена ​​последняя версия VS Code и настроено расширение ESP-IDF:

Также на нашем сайте вы можете прочитать статью про начало работы с ESP32 с использованием ESP-IDF.

Введение в ШИМ

Широтно-импульсная модуляция (ШИМ) — это сигнал, который обычно получают от аналоговых или цифровых микросхем, таких как платы ESP32. Это прямоугольный сигнал, который обеспечивает выходной сигнал, который может быть либо высоким, либо низким одновременно. При использовании источника питания 3,3 В сигналы ШИМ будут либо высокими (3,3 В), либо низкими (0 В). «Включение» сигнала — это время, в течение которого он находится в высоком состоянии, а «выключение» — это время, в течение которого он находится в низком состоянии. Для лучшего понимания принципов работы ШИМ на плате ESP32 необходимо ознакомиться со следующими двумя терминами, тесно связанными с цифровыми сигналами:

  • коэффициент заполнения;
  • частота.

Коэффициент заполнения

Коэффициент заполнения — это процент времени, в течение которого ШИМ-сигнал остается в высоком состоянии или «включен». Например, сигнал, который всегда выключен, имеет коэффициент заполнения 0%, тогда как сигнал, который постоянно включен, имеет коэффициент заполнения 100%. Уникальность этого фактора заключается в том, что пользователь может регулировать коэффициент заполнения для управления временем «включения». Для определения коэффициента заполнения используется формула:

Коэффициент заполнения = Время включения сигнала / Период времени сигнала

Демонстрация различных коэффициентов заполнения ШИМ сигнала

Частота

Частота ШИМ-сигнала — это количество циклов в секунду. Она также определяет, как быстро ШИМ-сигнал завершает один цикл, что называется периодом. Таким образом, для определения периода сигнала суммируются времена включения и выключения. Например, если период сигнала составляет 20 мс, то его частота будет равна 50 Гц. Следующие формулы показывают взаимосвязь между частотой и периодом:

Частота = 1 / Период времени
Период времени = Время включения + Время выключения

Контакты ШИМ ESP32

В ESP32 ШИМ-управление поддерживается только через все выходные контакты. Поэтому контроллер ШИМ для светодиодов ESP32 имеет 16 отдельных каналов, которые можно настроить для генерации ШИМ-сигналов.

Контакты с поддержкой ШИМ Все выходные контакты: GPIO0-GPIO5, GPIO12-GPIO33 

Контакты ШИМ ESP32

Если вы используете Arduino IDE вместо ESP-IDF, вы можете обратиться к этой статье:

API ESP32 для использования ШИМ

Прежде чем двигаться дальше, давайте обсудим некоторые важные функции, необходимые для доступа к ШИМ-каналам ESP32.

ESP-IDF предоставляет библиотеку driver/ledc.h, необходимую для управления светодиодами с помощью ШИМ. Нам потребуется настроить таймер, конфигурацию каналов и изменить сигнал ШИМ. Давайте посмотрим, как это будет реализовано. 

Первым шагом является подключение заголовочного файла:

Эта библиотека используется для управления яркостью светодиодов, а также для генерации ШИМ-сигналов. 16 каналов LEDC разделены на две группы по 8 каналов, которые генерируют отдельные формы сигналов. Из двух групп каналов LEDC одна работает в высокоскоростном режиме, а другая — в низкоскоростном. Более того, обе группы каналов могут работать с противоположными источниками тактовой частоты.

Теперь давайте посмотрим, как настроить канал LEDC в одном из двух режимов (высокоскоростной или низкоскоростной). Начнем с настройки таймера.

Настройка таймера ESP32

На этом этапе мы настраиваем таймер, определяя разрешение коэффициента заполнения ШИМ-сигнала, частоту, режим скорости, номер таймера и источник тактового сигнала. Для настройки таймера мы будем использовать функцию ledc_timer_config(). Эта функция принимает структуру данных ledc_timer_config_t. Внутри этой структуры данных мы определим следующие параметры:

  • Режим скорости (ledc_mode_t);
  • Частота ШИМ-сигнала;
  • Разрешение рабочего цикла;
  • Номер таймера (ledc_timer_t);
  • Источник тактового сигнала (ledc_clk_cfg_t).

Примечание: разрешение по коэффициенту заполнения и частота тактового сигнала источника связаны с частотой ШИМ-сигнала. Разрешение по коэффициенту заполнения обратно пропорционально частоте ШИМ. Это означает, что чем выше частота ШИМ, тем ниже разрешение по коэффициенту заполнения, и наоборот. Аналогично, частота тактового сигнала источника прямо пропорциональна частоте ШИМ-сигнала. Это означает, что чем выше частота тактового сигнала источника, тем выше может быть установлена ​​максимальная частота ШИМ, и наоборот.

В следующей функции ledc_timer_config() мы настраиваем таймер LEDC с заданными параметрами таймера/частоты (Гц)/разрешения заполнения. Она принимает в качестве параметра timer_conf, который является указателем на структуру конфигурации таймера LEDC.

В таблице ниже представлены три различных источника тактовой частоты, которые можно настроить, с указанием соответствующей частоты и доступных режимов работы.

Тип часов Тактовая частота Режим скорости
APB_CLK 80 МГц Высокий или низкий
REF_TICK 1 МГц Высокий или низкий
RTC8M_CLK 8 МГц Низкий

Тактовый генератор REF_TICK способен к динамическому масштабированию частоты, тогда как тактовый генератор RTC8M_CLK способен как к динамическому масштабированию частоты, так и к режиму легкого сна.

Про использование таймеров в ESP32 с помощью Arduino IDE вы можете прочитать в этой статье.

Настройка ШИМ-канала ESP32

Далее, для установки канала мы воспользуемся функцией ledc_channel_config(). Эта функция принимает структуру ledc_channel_config_t, которая определяет параметры конфигурации канала. Это позволит генерировать ШИМ-сигнал на указанном выводе GPIO с частотой и разрешением коэффициента заполнения, уже заданными в конфигурации таймера. Если вы хотите остановить генерацию ШИМ-сигнала, вызовите функцию ledc_stop().

В следующей функции ledc_channel_config() мы настраиваем канал LEDC с заданными параметрами: номер канала/выхода gpio_num/прерывание/источник таймера/частота (Гц)/разрешение заполнения LEDC. Функция принимает в качестве параметра timer_conf - это указатель на структуру конфигурации таймера LEDC.

Настройка коэффициента заполнения ШИМ ESP32

Теперь давайте разберемся, как изменять ШИМ-сигнал. В случае светодиодов изменение ШИМ-сигнала означает изменение коэффициента заполнения, поэтому яркость светодиода изменяется соответствующим образом. Существует несколько различных способов изменения ШИМ-сигнала, включая программные и аппаратные. Мы сосредоточимся на API, которые будем использовать в нашем проекте.

Для установки коэффициента заполнения ШИМ-сигнала программным способом мы будем использовать функцию ledc_set_duty() . Она принимает три параметра. Первый параметр — это режим скорости. Второй параметр — это канал LEDC. Третий параметр — это коэффициент заполнения LEDC, который вы хотите установить. Диапазон этого коэффициента заполнения составляет [0, (2**duty_resolution) – 1]. Это означает, что если выбранное разрешение заполнения равно 10, то значения коэффициента заполнения могут варьироваться от 0 до 1023. Это обеспечивает разрешение приблизительно 0,1%.

Для запуска режима работы LEDC мы будем использовать функцию ledc_update_duty(). Она используется для обновления параметров канала LEDC. Функция принимает два параметра: первый — это режим скорости, а второй — канал LEDC.

Примечание: после вызова функции ledc_set_duty() необходимо вызвать функцию ledc_update_duty(), поскольку она отвечает за активацию установленных изменений режима работы LEDC.

Кроме того, функция ledc_get_duty() возвращает текущее значение коэффициента заполнения LEDC. Она также принимает два параметра: режим скорости и канал LEDC соответственно. Функция вернет значение коэффициента заполнения в текущем цикле ШИМ.

Существует еще несколько способов управления ШИМ в ESP32. Для получения более подробной информации обратитесь к официальному API Espressif ESP32 для управления светодиодами .

ШИМ-управление яркостью светодиода с помощью ESP32 ESP-IDF

Теперь давайте продемонстрируем проект в VS Code с расширением ESP-IDF, связанным с генерацией ШИМ-сигнала на ESP32. Мы настроим проект управления яркостью светодиода, где потенциометр, подключенный к ESP32, будет использоваться для изменения яркости светодиода. Мы подключим потенциометр к выводу АЦП ESP32. При вращении ручки потенциометра изменяющиеся значения АЦП будут использоваться для установки коэффициента заполнения светодиода, тем самым изменяя его яркость.

АЦП означает аналого-цифровое преобразование, при котором аналоговый сигнал преобразуется в цифровое значение с определенным разрешением. ESP32 имеет два 12-битных АЦП (АЦП 1 и АЦП 2) и поддерживает максимум 18 аналоговых каналов. Аналоговые значения в ESP32 считываются с помощью переменных напряжений в диапазоне от 0 до 3,3 В. Полученному напряжению затем присваивается значение от 0 до 4095 для 12-битного разрешения. Соответственно, значение 0 равно 0 В, а максимальное значение 4095 равно 3,3 В. Любые промежуточные значения также будут присваиваться соответствующим образом. При использовании АЦП с 10-битным разрешением значения АЦП будут находиться в диапазоне от 0 до 1023. Также на нашем сайте вы можете более подробно изучить вопросы использования АЦП в ESP32 с использованием ESP-IDF.

ШИМ (широтно-импульсная модуляция) — это модуляция ширины импульса, которую мы будем использовать для плавного изменения яркости светодиода. Хотя это и не настоящий цифро-аналоговый преобразователь (ЦАП), выходная мощность уменьшается на величину коэффициента заполнения (изменения коэффициента включения/выключения) при генерации высокочастотного цифрового сигнала. Это и приводит к плавному изменению яркости светодиода.

Управление яркостью светодиода с помощью ШИМ на ESP32

Для нашего проекта по ШИМ на основе платы ESP32 необходимы следующие компоненты:

  1. Плата ESP32.
  2. 5-мм светодиод.
  3. Токоограничивающий резистор 220 Ом.
  4. Макетная плата.
  5. Потенциометр.
  6. Соединительный провод.

На приведенной ниже схеме показана схема сборки для данного проекта.

Схема проекта управления яркостью светодиода с помощью ШИМ на ESP32

Потенциометр питается от 3,3 В от ESP32. Его центральный вывод подключен к GPIO32, который обозначается как ADC1_CH4. Последний вывод подключен к контакту GND ESP32.

Мы использовали вывод GPIO27 для подключения к аноду светодиода через токоограничивающий резистор сопротивлением 220 Ом. Катод светодиода подключен к выводу GND микроконтроллера ESP32.

Вы можете использовать любой другой подходящий ШИМ-выход ESP32 для подключения к светодиоду, а также аналоговый вывод ESP32 для подключения к потенциометру.

Вот как выглядит наша схема после подключения всех компонентов.

Собранная на макетной плате конструкция проекта

Код управления яркостью светодиода с помощью ШИМ на EPS32

Откройте VS Code и создайте новый проект ESP-IDF. Теперь перейдите к файлу main.c. Здесь мы определим функции и программный код.

Мы будем использовать этот скрипт для управления яркостью светодиода, подключенного к GPIO27, путем усреднения необработанных значений АЦП, полученных с канала 4 АЦП1.

Как работает код?

Для начала мы подключим необходимые библиотеки для этого проекта. Это включает в себя драйвер светодиода, драйвер АЦП, библиотеку калибровки АЦП и библиотеку FreeRTOS. Библиотеки driver/adc.h и esp_adc_cal.h необходимы для драйвера АЦП и калибровки АЦП соответственно. Библиотека driver/ledc.h необходима для ШИМ-управления светодиодом.

Здесь мы определяем переменную, которая представляет собой количество выборок. Она установлена ​​на 32. Это будет использоваться для более точного приближения значения АЦП. Мы будем считывать значение АЦП 32 раза, усреднять его и устанавливать в качестве коэффициента заполнения в каждой итерации цикла.

Для подключения потенциометра мы используем канал 4 АЦП1.

Мы подключили светодиод к выводу GPIO27. Поэтому мы определим переменную с именем 'LEDC_GPIO', которая будет хранить данные о выводе GPIO 27. Кроме того, мы определим канал управления светодиодом, ledc_channel, и используемый с ним вывод GPIO следующим образом:

Инициализация оборудования

Функция init_hw() отвечает за инициализацию АЦП и канала управления светодиодом.

Для инициализации АЦП сначала устанавливаем разрядность АЦП1 на 10 бит с помощью функции adc1_config_width(). Это означает, что значения АЦП будут изменяться в диапазоне от 0 до 1023. Затем настраиваем параметр ослабления канала 4 АЦП1 на 11 дБ. Это устанавливает диапазон входного напряжения АЦП примерно в 150-2450 мВ.

Для инициализации канала управления светодиодом сначала настроим таймер. Мы используем LEDC_TIMER_0 с частотой 1000 Гц. Для коэффициента заполнения ШИМ мы также установили разрешение 10 бит. Выбран высокоскоростной режим. После настройки таймера настроим канал управления светодиодом. Мы используем LEDC_CHANNEL_0 на нашем LEDC_GPIO, который мы ранее определили как GPIO27 (подключенный к светодиоду). Доступно до 8 каналов, так как они есть. Этот настроенный нами LEDC_GPIO использует LEDC_TIMER_0, как было установлено ранее.

Регулировка яркости светодиодов

Внутри функции loop() мы получаем исходное значение АЦП с помощью функции ad1_get_raw() и указываем номер канала АЦП в качестве параметра. Это значение сохраняется в целочисленной переменной с именем 'adc_value'. Значение считывается 32 раза, а затем его среднее значение сохраняется в переменной 'adc_value'. Это делается для получения хорошего приближенного значения.

Далее, для установки коэффициента заполнения светодиода мы используем функцию ledc_set_duty() и указываем в качестве параметров режим скорости, канал светодиода и значение adc_val. Здесь коэффициент заполнения устанавливается равным значению, хранящемуся в переменной 'adc_value'. Затем для активации значения коэффициента заполнения мы используем функцию ledc_update_duty() и указываем в ней режим скорости и канал светодиода. Кроме того, мы добавляем задержку в 500 мс, используя функцию vTaskDekay(), прежде чем цикл повторится.

Компиляция скетча

Для прошивки микросхемы введите следующую команду в последовательном терминале. Не забудьте заменить COM-порт на тот, через который подключена ваша плата.

Команда для прошивки платы ESP32 в VS Code

После успешной прошивки кода поверните ручку потенциометра, чтобы изменить коэффициент заполнения ШИМ-сигнала, подаваемого на GPIO27. По мере увеличения показаний АЦП от 0 до 1023 яркость светодиода увеличивается. Аналогично, вращение ручки в противоположном направлении приводит к уменьшению показаний АЦП от 1023 до 0, в результате чего светодиод тускнеет.

Тестирование работы проекта управления яркостью светодиода на ESP32

Видео, демонстрирующее работу проекта

(Проголосуй первым!)
Загрузка...
123 просмотров

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *