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 разметка не поддерживается! Используйте обычный текст.
    Плохо           Хорошо
Двухполярное питание из однополярного

Двухполярное питание из однополярного

Двухполярное питание необходимо для питания операционных усилителей, усилителей мощности и другой те..

Создание простого таймера на ESP32: пример периодического вызова функции

Создание простого таймера на ESP32: пример периодического вызова функции

Создание простого таймера на ESP32: пример периодического вызова функции При разработке проектов ..

Датчик температуры аналоговый 10К

Датчик температуры аналоговый 10К

Датчик температуры аналоговый NTC 10K Аналоговый датчик температуры NTC 10K ±1% — это высокоточный ..

44.68грн.

Модуль реле 8-канальный 5В 10А

Модуль реле 8-канальный 5В 10А

8-канальный модуль реле для подключения напрямую к дискретному выходу контроллера. Светодиодная инди..

262.46грн.

Припой с канифолью 0,5мм 30г

Припой с канифолью 0,5мм 30г

Нить припоя для тонкой пайки мелких радиодеталей, содержащая флюсСвинца 40 %Олова 60 %Флюса 1,2 %Нап..

211.57грн.