Широтно-импульсная модуляция (ШИМ, в англ. PWM – Pulse Width Modulation) – это вид модуляции, при котором изменяется ширина импульса при постоянной частоте следования импульсов. В цифровой электронике данный вид модуляции широко применяется для управления яркостью свечения светодиода, скоростью вращения электродвигателя постоянного тока, управления серводвигателем и во многих других случаях когда необходимо сформировать аналоговый сигнал цифровыми методами.
В данной статье мы рассмотрим использование широтно-импульсной модуляции (ШИМ) в модуле ESP32 для управления яркостью свечения светодиода. Все контакты общего назначения (GPIO pins) модуля ESP32 (за исключением контактов Power, GND, Tx, Rx и EN) могут быть использованы для формирования ШИМ сигнала.
Необходимые компоненты
- Модуль ESP32 (купить на AliExpress).
- Резистор 330 Ом (купить на AliExpress).
- Светодиод (купить на AliExpress).
- Потенциометр 10 кОм (купить на AliExpress).
- Макетная плата.
Основные принципы ШИМ
Прежде чем переходить к рассмотрению ШИМ в модуле ESP32 познакомимся с некоторыми терминами, используемыми в ШИМ.
TON (On Time): время, в течение которого у сигнала высокий уровень (high).
TOFF (Off Time): время, в течение которого у сигнала низкий уровень (low).
Period: сумма времен TON и TOFF ШИМ сигнала.
TotalPeriod = TON + TOFF
Коэффициент заполнения/скважность (Duty Cycle): процент времени в течение периода ШИМ сигнала, в котором сигнал находится в состоянии high.
Duty Cycle = TON /TTotal * 100
К примеру, если импульс с общим периодом 10ms будет в состоянии ON (high) в течение 5ms, то коэффициент заполнения (duty cycle) в этом случае будет равен:
Duty Cycle = 5/10 * 100 = 50% Duty Cycle
Частота ШИМ сигнала: определяет как быстро ШИМ сигнал завершает один свой полный период (сумма времен ON и OFF) как показано на рисунке выше. Частота является обратной величиной по отношению к периоду.
Ранее на нашем сайте мы рассматривали использование ШИМ в следующих проектах:
- использование ШИМ в микроконтроллерах AVR;
- регулятор силы свечения светодиода на микроконтроллере AVR;
- использование широтно-импульсной модуляции (ШИМ) в Arduino;
- чистый синусоидальный инвертор на Arduino;
- использование ШИМ в Raspberry Pi.
Формирование ШИМ в модуле ESP32
В платах Arduino и NodeMCU ESP8266 использовали функцию analogWrite() с аргументом между 0 и 254 для формирования ШИМ сигнала с требуемым нам коэффициентом заполнения. Но плата/модуль ESP32 не поддерживает использование функции analogWrite(), вместо нее мы будем использовать функцию ledcWrite(), которая очень похожа на функцию analogWrite(). Для своей работы она также требует два параметра: канал (контакт), на котором мы хотим формировать ШИМ сигнал, и значение ШИМ сигнала, которое мы хотим передавать на заданный контакт. Модуль ESP32 имеет 16 каналов для формирования ШИМ, можно использовать любой контакт ввода/вывода для формирования ШИМ.
Для модуля ESP32 доступны три функции для работы с ШИМ: назначение канала для формирования ШИМ и настройки частоты, разрешения и коэффициента заполнения формируемого ШИМ сигнала. Эти функции имеют следующий синтаксис:
1 2 3 |
ledcAttachPin(gpio, channel) ledcSetup(channel, frequency, resolution) ledcWrite(channel, dutycycle) |
Схема проекта
Схема для формирования ШИМ сигнала в модуле ESP32 представлена на следующем рисунке.
Как видите, схема очень проста и содержит светодиод, резистор и потенциометр 10 кОм. Отрицательный контакт светодиода подключен к земле (GND) модуля ESP32 через токоограничивающий резистор 330 Ом (для этих целей можно выбрать резистор с сопротивлением от 230 до 500 Ом). Положительный контакт светодиода подключен к контакту 16 модуля ESP32, а средний контакт потенциометра – к контакту АЦП 1 (VP pin) модуля ESP32.
Объяснение программы для модуля ESP32
Полный код программы приведен в конце статьи, здесь же мы кратко рассмотрим его основные фрагменты.
Код нашей программы не содержит никаких подключаемых библиотек, поэтому начнем мы код программы с указания контакта модуля ESP32, к которому подключен светодиод. В нашем случае это контакт 16.
1 |
const int ledPin = 16; // 16 corresponds to GPIO16 |
После этого зададим параметры формируемого ШИМ сигнала. Мы будем использовать частоту ШИМ сигнала 9000 Гц и его разрешение равное 10. Модуль ESP32 поддерживает различные разрешения ШИМ сигнала – от 1 до 16 бит. Также мы зададим канал для формирования ШИМ сигнала, модуль ESP32 имеет 16 (от 0 до 15) подобных каналов.
1 2 3 |
const int freq = 9000; const int ledChannel = 0; const int resolution = 10; |
Внутри функции void setup() мы с помощью функции ledcSetup() зададим настройки для формирования ШИМ сигнала, которые мы указали ранее. Далее с помощью функции ledcAttachPin() мы назначим контакт (к которому подключен светодиод) и канал, на которых будет осуществляться формирование ШИМ сигнала.
1 2 3 4 5 |
void setup(){ Serial.begin(9600); ledcSetup(ledChannel, freq, resolution); ledcAttachPin(ledPin, ledChannel); } |
В функции void loop() мы будем считывать значение с выхода АЦП (аналого-цифрового преобразователя), к которому подключен средний контакт потенциометра, в переменную ‘dutyCycle’. Формировать необходимый нам ШИМ сигнал с заданными параметрами мы будем с помощью функции ledcWrite(). Таким образом, яркость свечения светодиода в нашем проекте будет зависеть от положения ручки потенциометра.
1 2 3 4 5 |
void loop(){ dutyCycle = analogRead(A0); ledcWrite(ledChannel, dutyCycle); delay(15); } |
Тестирование работы проекта
Для тестирования формирования ШИМ сигнала в модуле ESP32 соберите схему проекта, представленную на рисунке выше, и загрузите программу в модуль ESP32. Убедитесь в том, что в Arduino IDE вы выбрали правильный тип платы и COM порт, к которому подключен модуль. После этого вы можете вращать ручку потенциометра вправо или влево чтобы увеличить или уменьшить яркость свечения светодиода.
Более подробно работу проекта вы можете посмотреть на видео, приведенном в конце статьи.
Исходный код программы (скетча)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
const int ledPin = 16; // 16 corresponds to GPIO16 uint16_t dutyCycle; // устанавливаем настройки формирования ШИМ const int freq = 15000; const int ledChannel = 0; const int resolution = 13; void setup(){ Serial.begin(9600); // настраиваем ШИМ в соответствии с ранее указанными настройками ledcSetup(ledChannel, freq, resolution); // назначаем контакт и канал для формирования ШИМ ledcAttachPin(ledPin, ledChannel); } void loop(){ dutyCycle = analogRead(A0); Serial.print(dutyCycle); // изменяем яркость свечения светодиода с помощью ШИМ сигнала ledcWrite(ledChannel, dutyCycle); delay(15); } |
Здравствуйте, как сделать регулятор ШИМ но только чтобы импульс был с внешнего источника, например с датчика холла?
Добрый вечер, посмотрите вот этот проект спидометра на основе платы Ардуино, в нем как раз информация с колеса передается с помощью датчика Холла и прикрепленное к нему прерывание. Аналогичным образом можете сделать и вы, то есть чем чаще, к примеру, у вас будет поступать прерывание от датчика Холла, тем больше вы будете делать коэффициент заполнения ШИМ.
Спасибо что ответили это мне тоже пригодится но я ищу немного другое, может я чего-то не понял в той статье но я постараюсь описать как можно подробнее то что меня интересует, в общем мне нужно собрать схему для управления ДВС то есть есть датчик холла, есть датчик положения дроссельной заслонки(потенциометр) и электроная топливная форсунка, нужно сделать так чтобы можно было управлять потенциометром временем впрыска то есть длительностью импульса подаваемого на форсунку получаемого с датчика холла, так сказать простой приметивный ЭБУ для двигателя. Я сам авто электрик но в данном случае мне нужно максимально упростить управление двигателем, я просто раньше не сталкивался с ардуино и её программированием, а в инете ничего подобного я не смог найти. Скажите хотя бы это вообще возможно реализовать с мкроконтроллером ардуино нано, в моем распоряжение пока только он. Спасибо что откликнулись.
А с датчика Холла у вас есть возможность подать сигнал на ардуино? Если есть, то не вижу проблем в реализации вашего проекта. Что конкретно вас смущает?
Если честно я незнаю как правилно написать скетч. как подружить это всё програмно?
Я когда приеду из отпуска мог бы попробовать вам помочь взамен на то,что потом вы напишите для моего сайта статью с описанием вашего устройства