ESP32 PWM (analogWrite): управление яркостью и скоростью без углублений в драйверы

ESP32 поддерживает широтно‑импульсную модуляцию (ШИМ), что позволяет плавно управлять яркостью светодиодов, скоростью вентиляторов и моторов, уровнем подсветки и т. п. В Arduino‑среде для ESP32 доступен простой, знакомый интерфейс analogWrite() — его достаточно, чтобы быстро запустить PWM без изучения низкоуровневых деталей.

Ключевые функции

  • void analogWrite(uint8_t pin, uint32_t duty); — записывает скважность (duty) на вывод pin.
  • void analogWriteResolution(uint8_t pin, uint8_t resolution); — задаёт разрешение ШИМ для пина (в битах). Диапазон значений duty будет 0 … 2resolution-1.
  • void analogWriteFrequency(uint8_t pin, uint32_t freq); — задаёт частоту ШИМ (в Гц) для пина.

Замечание: максимально возможное разрешение зависит от выбранной частоты: чем выше частота, тем меньше доступных бит. Для светодиодов часто используют 5–10 кГц с 8–12 битами; для моторов — 15–25 кГц, чтобы уйти выше слышимого диапазона.

Диапазоны значений duty

Разрешение (бит)Диапазон duty
80…255
100…1023
120…4095
130…8191

Рекомендации по пинам и подключению

  • Для ШИМ‑выходов используйте GPIO из диапазонов 4–19, 21–23, 25–27, 32–33.
  • Никогда не используйте GPIO34–39 — это входы‑только.
  • ESP32 работает на 3.3 В, выводы не 5V‑tolerant. Для светодиода — обязательно токоограничивающий резистор 220–330 Ω.

Пример 1. Плавное «мигание» светодиода

Частота 5 кГц, разрешение 8 бит (0–255). Плавный подъём/спад яркости.


#include <Arduino.h>

const uint8_t LED_PIN = 5;

void setup() {
  // Настраиваем частоту и разрешение для пина
  analogWriteFrequency(LED_PIN, 5000);    // 5 кГц
  analogWriteResolution(LED_PIN, 8);      // 8 бит → duty 0..255
}

void loop() {
  for (int d = 0; d <= 255; d++) {
    analogWrite(LED_PIN, d);
    delay(6);
  }
  for (int d = 255; d >= 0; d--) {
    analogWrite(LED_PIN, d);
    delay(6);
  }
}
  

Как это работает: при увеличении duty коэффициент заполнения ШИМ растёт — среднее напряжение на светодиоде увеличивается, яркость возрастает. При уменьшении — наоборот.

Пример 2. RGB‑светодиод: смешивание цветов

Три независимых канала PWM на 5 кГц, 8 бит. Выводим базовые и смешанные цвета.


#include <Arduino.h>

const uint8_t R_PIN = 21;
const uint8_t G_PIN = 22;
const uint8_t B_PIN = 23;

void setup() {
  // Одинаковая частота/разрешение для всех трёх каналов
  analogWriteFrequency(R_PIN, 5000);
  analogWriteResolution(R_PIN, 8);
  analogWriteFrequency(G_PIN, 5000);
  analogWriteResolution(G_PIN, 8);
  analogWriteFrequency(B_PIN, 5000);
  analogWriteResolution(B_PIN, 8);
}

void solid(uint8_t r, uint8_t g, uint8_t b, uint32_t ms) {
  analogWrite(R_PIN, r);
  analogWrite(G_PIN, g);
  analogWrite(B_PIN, b);
  delay(ms);
}

void loop() {
  solid(255,   0,   0, 800); // Красный
  solid(  0, 255,   0, 800); // Зелёный
  solid(  0,   0, 255, 800); // Синий
  solid(255, 255,   0, 800); // Жёлтый
  solid(  0, 255, 255, 800); // Голубой
  solid(255,   0, 255, 800); // Пурпурный
  solid(128,  32, 255, 800); // Произвольный оттенок
}
  

Как это работает: каждый из трёх каналов управляет яркостью соответствующего кристалла RGB‑светодиода. Комбинируя скважность, получаем любой цвет.

Пример 3. Регулятор скорости/яркости от потенциометра

Частота 20 кГц (выше слышимого диапазона), разрешение 12 бит для более тонкой градации. Значение с потенциометра (ADC) масштабируем в duty.


#include <Arduino.h>

const uint8_t PWM_PIN   = 19;  // Выход PWM (к драйверу/LED)
const uint8_t POT_PIN   = 34;  // Вход ADC (только-вход) - потенциометр
const uint8_t RES_BITS  = 12;  // 12 бит → duty 0..4095
const uint32_t F_PWM    = 20000; // 20 кГц

void setup() {
  Serial.begin(115200);
  analogWriteFrequency(PWM_PIN, F_PWM);
  analogWriteResolution(PWM_PIN, RES_BITS);
  analogReadResolution(12); // чтобы сопоставить с 12-битным duty
}

void loop() {
  int raw = analogRead(POT_PIN);        // 0..4095 (ESP32 ADC 12 бит)
  // Масштабируем ADC к duty (0..4095)
  uint32_t duty = (uint32_t)raw;        // при совпадающих разрядностях просто берём сырой ADC
  analogWrite(PWM_PIN, duty);

  // Телеметрия
  static uint32_t t0 = 0;
  if (millis() - t0 > 300) {
    t0 = millis();
    Serial.printf("ADC=%4d  duty=%4lu\r\n", raw, duty);
  }
}
  

Как это работает: с потенциометра читается 12‑битное значение, которое напрямую подаётся как duty того же разряда. Частота 20 кГц исключает акустический писк при управлении вентиляторами/моторами.


Типовые сочетания частоты и разрешения

ЗадачаЧастота (Гц)Разрешение (бит)Комментарий
Яркость LED5 000–10 0008–12Без мерцания, плавные градации
Мотор/вентилятор18 000–25 0008–11Выше слышимого диапазона
Подсветка/дисплей1 000–20 0008–12Подбирайте на глаз/по шуму

Подсказка: если выставили слишком высокую частоту и «не берётся» выбранное разрешение, уменьшите число бит. Для отладки начните с 5 кГц и 8 бит, затем повышайте частоту и/или разрядность.

Частые ошибки

  • Использование пинов 34–39 как выхода — они вход‑только, ШИМ не получится.
  • Слишком маленькая частота → заметное мерцание LED.
  • Слишком большая частота при высоком разрешении → канал не стартует/яркость «ступенчатая». Снижайте разрядность.
  • Подключение LED без резистора, нагрузок напрямую к GPIO — используйте резистор и соответствующие драйверы.

Итоги

analogWrite() на ESP32 позволяет быстро поднять PWM: задайте analogWriteFrequency(pin, freq), analogWriteResolution(pin, bits), затем меняйте duty через analogWrite(pin, value). Этого достаточно для подавляющего большинства задач — от плавной подсветки до управления вентиляторами и простыми моторами.

<< Проекты << Все товары >> Статьи, уроки >>

Написать отзыв

Примечание: HTML разметка не поддерживается! Используйте обычный текст.
    Плохо           Хорошо
Светодиодная матрица 8х8 с управляющим контроллером MAX7219

Светодиодная матрица 8х8 с управляющим контроллером MAX7219

Готовый блок светодиодной матрицы 8х8 с поддержкой каскадного включения нескольких идентичных модуле..

87.37грн.

Шилд SHT30 для Wemos D1 mini

Шилд SHT30 для Wemos D1 mini

Шилд датчика температуры и влажности на основе SHT30Коммуникационный интерфейс I2CДиапазон измерения..

102.48грн.

Аудио штекер 3,5мм папа с винтовым клеммником

Аудио штекер 3,5мм папа с винтовым клеммником

Стерео штекер 3,5 мм для монтажа цепей передачи звукового сигнала при помощи винтового клеммника.Выв..

94.08грн.

Корпус пластиковый 100x60x25мм

Корпус пластиковый 100x60x25мм

Универсальный бокс из чорного пластика под самодельное электронное устройствоArduino UNO и Leonardo ..

74.20грн.

Модуль часов реального времени DS1302

Модуль часов реального времени DS1302

Модуль часов реального времени на основе микросхемы DS1302 предназначен для работы с любительскими..

50.25грн.