Что такое PWM? analogWrite, коэффициент заполнения и частота на Arduino
Что такое PWM (широтно-импульсная модуляция) и как она работает? Коэффициент заполнения и частота, PWM-пины Arduino, яркость светодиода и скорость мотора через analogWrite, сервоприводы, LEDC на ESP32 и PWM на Pico.
Цифровые пины Arduino знают только два состояния: 0 V или 5 V. Как же тогда приглушить светодиод до половины яркости или заставить мотор крутиться медленно? Ответ — PWM (Pulse Width Modulation, широтно-импульсная модуляция, ШИМ). Пин очень быстро включается и выключается, и, меняя долю времени, когда он включён, ты задаёшь среднюю мощность, которая доходит до нагрузки. Эту технику используют для регулировки яркости светодиодов, скорости моторов, управления сервоприводами, получения звука и даже в зарядках для телефонов.

Как работает PWM?
Сигнал PWM — это меандр (прямоугольные импульсы): какое-то время он в HIGH, потом в LOW, и цикл повторяется снова и снова. Длительность одного цикла «вкл-выкл» — это период, а доля периода, в течение которой сигнал остаётся в HIGH, — коэффициент заполнения (duty cycle). При заполнении 25% сигнал включён четверть времени, так что пин на 5 V в среднем ведёт себя как 1,25 V. Светодиод мигает примерно 490 раз в секунду; глаз за этим не успевает и видит только среднюю яркость. Мотор благодаря инерции сглаживает импульсы и вращается со средней скоростью.
| Заполнение | Значение analogWrite | Среднее напряжение (5 V) | Светодиод |
|---|---|---|---|
| 0% | 0 | 0 V | Выключен |
| 25% | 64 | 1,25 V | Тускло |
| 50% | 127 | 2,5 V | Половина яркости |
| 75% | 191 | 3,75 V | Ярко |
| 100% | 255 | 5 V | Полная яркость |
Глаза реагируют на свет нелинейно: изменения при слабом свете замечают очень хорошо, а при ярком — гораздо хуже. Поэтому светодиод при заполнении 50% кажется намного ярче, чем «наполовину». Чтобы яркость менялась естественно, используют гамма-коррекцию, показанную ниже.
Частота: насколько быстр PWM?
Частота — это сколько раз в секунду сигнал включается и выключается. На Arduino Uno пины 5 и 6 работают примерно на 980 Hz, а пины 3, 9, 10 и 11 — примерно на 490 Hz. Для светодиодов этих частот более чем достаточно. А вот с моторами 490 Hz попадают в слышимый диапазон, и мотор может слегка пищать; на ESP32 и Pico частоту можно поднять до 20 kHz, и писк пропадёт. Но если поднять частоту намного выше необходимого, транзисторы и MOSFET начинают греться.
| Плата | PWM-пины | Частота по умолчанию | Разрешение |
|---|---|---|---|
| Arduino Uno / Nano | 3, 5, 6, 9, 10, 11 | 490 Hz (5 и 6: 980 Hz) | 8 бит (0–255) |
| Arduino Mega | 2–13, 44–46 | 490 Hz (4 и 13: 980 Hz) | 8 бит (0–255) |
| ESP32 | Почти любой выходной пин | Настраивается (analogWrite: 1 kHz) | 1–16 бит |
| Raspberry Pi Pico | Любой пин GPIO | Настраивается | 16 бит (0–65535) |
Яркость светодиода через analogWrite
На Arduino PWM получают командой analogWrite(pin, value), где значение лежит между 0 и 255. Несмотря на обманчивое название, эта команда выдаёт не настоящее аналоговое напряжение, а PWM. Работает она только на пинах, отмеченных знаком ~. Код ниже медленно разжигает и гасит светодиод — получается эффект «дыхания»:
1const int LED_PIN = 9; // ~ işaretli PWM pini / PWM pin marked with ~
2
3void setup() {
4 pinMode(LED_PIN, OUTPUT);
5}
6
7void loop() {
8 for (int v = 0; v <= 255; v++) { // yavaşça yan / fade in
9 analogWrite(LED_PIN, v);
10 delay(8);
11 }
12 for (int v = 255; v >= 0; v--) { // yavaşça sön / fade out
13 analogWrite(LED_PIN, v);
14 delay(8);
15 }
16}Управление яркостью потенциометром
Если подключить потенциометр к A0, яркость светодиода можно задавать вручную. analogRead() возвращает значение от 0 до 1023; деление на 4 даёт диапазон 0–255, которого ждёт analogWrite. Подключение потенциометра разобрано в статье Что такое потенциометр?
1void loop() {
2 int pot = analogRead(A0); // 0–1023
3 analogWrite(9, pot / 4); // 0–255
4}Скорость мотора постоянного тока через PWM
Даже маленький мотор постоянного тока потребляет сотни миллиампер, а пин Arduino может безопасно отдать всего около 20 mA. Поэтому мотор подключают через транзистор, MOSFET или драйвер мотора вроде L298N, а сигнал PWM подают на вход скорости драйвера. На L298N этот вход — пин ENA (и ENB для второго мотора); чтобы использовать PWM, с него нужно снять перемычку. Пины IN1 и IN2 задают направление вращения.

1const int ENA = 9; // hız (PWM) / speed (PWM)
2const int IN1 = 8; // yön / direction
3const int IN2 = 7;
4
5void setup() {
6 pinMode(ENA, OUTPUT);
7 pinMode(IN1, OUTPUT);
8 pinMode(IN2, OUTPUT);
9 digitalWrite(IN1, HIGH); // ileri / forward
10 digitalWrite(IN2, LOW);
11}
12
13void loop() {
14 analogWrite(ENA, 255); delay(2000); // tam hız / full speed
15 analogWrite(ENA, 150); delay(2000); // orta hız / medium speed
16 analogWrite(ENA, 0); delay(2000); // dur / stop
17}Сервоприводы и PWM — это одно и то же?
Сервоприводы тоже управляются импульсами, но логика другая: положение задаётся шириной импульса, а не коэффициентом заполнения. Сервопривод ждёт 50 импульсов в секунду (50 Hz); импульс длиной 1 миллисекунда означает примерно 0°, 1,5 мс — 90°, а 2 мс — 180°. analogWrite не умеет выдавать такие тайминги, поэтому для сервоприводов используют библиотеку Servo. Подробности — в статье Что такое сервопривод?
Настоящее аналоговое напряжение из PWM: RC-фильтр
Иногда действительно нужно ровное напряжение, например чтобы дать операционному усилителю опорный уровень или получить звуковой выход. Тогда PWM пропускают через фильтр нижних частот из резистора и конденсатора. С 10 kΩ и 10 µF постоянная времени равна 0,1 секунды; выход получается довольно гладким, но на изменения реагирует медленно. Разные значения можно попробовать в калькуляторе Постоянная времени RC. У классического ESP32 есть ещё и два ЦАП на GPIO 25 и 26, которые дают настоящий аналоговый выход.
PWM на ESP32: LEDC
На ESP32 PWM формирует аппаратный блок LEDC, и частоту с разрешением выбираешь ты. В ядре Arduino 3.x используются ledcAttach(pin, frequency, resolution) и ledcWrite(pin, value); в старых версиях 2.x были команды ledcSetup и ledcAttachPin с привязкой к каналам. Пример ниже плавно меняет яркость светодиода на частоте 5 kHz с разрешением 8 бит:
1const int LED_PIN = 2;
2
3void setup() {
4 ledcAttach(LED_PIN, 5000, 8); // 5 kHz, 8 bit (0–255) — ESP32 Arduino core 3.x
5}
6
7void loop() {
8 for (int d = 0; d <= 255; d++) { ledcWrite(LED_PIN, d); delay(5); }
9 for (int d = 255; d >= 0; d--) { ledcWrite(LED_PIN, d); delay(5); }
10}PWM на Raspberry Pi Pico (MicroPython)
Любой пин GPIO на Pico умеет выдавать PWM. В MicroPython используется класс PWM: частота задаётся через freq(), а заполнение — через duty_u16(), который принимает значения от 0 до 65535:
1from machine import Pin, PWM
2import time
3
4led = PWM(Pin(15))
5led.freq(1000) # 1 kHz
6
7while True:
8 for d in range(0, 65536, 512): # yavaşça yan / fade in
9 led.duty_u16(d)
10 time.sleep_ms(5)
11 for d in range(65535, -1, -512): # yavaşça sön / fade out
12 led.duty_u16(d)
13 time.sleep_ms(5)Идеи проектов с PWM
- Дышащий светодиод: индикатор состояния, который медленно разгорается и гаснет, как у устройств в режиме ожидания.
- Настольная лампа с регулировкой: светодиодная лампа, яркость которой задаётся потенциометром.
- Вентилятор по температуре: разгоняй вентилятор по мере роста температуры, которую измеряет DHT11.
- Смешивание цветов: получай миллионы цветов на RGB-светодиоде тремя каналами PWM.
- Машинка-робот: делай повороты плавными, задавая скорость двух моторов по отдельности.
- Лампа-рассвет: медленно разжигай свет в течение 15 минут перед утренним будильником.
Частые ошибки и как их исправить
- analogWrite на пине без PWM: на Uno пины без ~ могут быть только включены или выключены; 128 и выше считается включением, всё, что ниже, — выключением.
- Пины 9 и 10 вместе с библиотекой Servo: на Uno библиотека Servo использует Timer1 и отключает PWM на этих двух пинах; переставь светодиод или мотор на другой PWM-пин.
- Пины 3 и 11 вместе с tone(): tone() использует Timer2 и ломает PWM на этих пинах.
- Мотор прямо на пине: всегда используй транзистор, MOSFET или драйвер мотора.
- Переполнение в расчёте гаммы: v * v выходит за предел int; добавь приведение (long).
- PWM как настоящий аналог: мультиметр показывает среднее, но сигнал всё равно скачет между 0 и 5 V; для чувствительных схем используй RC-фильтр или ЦАП.
PWM — одна из самых полезных идей, которые можно освоить на Arduino: светодиоды, моторы, вентиляторы и динамики управляются этим простым приёмом. Основы — в статье Что такое светодиод?; в приложении BlueGrays есть пошаговые проекты с кодом: плавное затухание светодиода через PWM, яркость от потенциометра и смена цветов RGB.
Частые вопросы
Что такое PWM в двух словах?
PWM — способ задать среднюю мощность, которая доходит до нагрузки, очень быстро включая и выключая пин и меняя долю времени, когда он включён (коэффициент заполнения). Благодаря ему цифровой пин, который выдаёт только 0 или 5 V, может приглушить светодиод или замедлить мотор.
Какие пины Arduino Uno поддерживают PWM?
На Uno и Nano PWM поддерживают пины 3, 5, 6, 9, 10 и 11; на плате они отмечены знаком ~. На Mega PWM умеют выдавать пины 2–13 и 44–46.
Даёт ли analogWrite настоящий аналоговый выход?
Нет. analogWrite формирует PWM: пин быстро переключается между 0 и 5 V. Он задаёт среднее напряжение, но для по-настоящему ровного напряжения PWM нужно пропустить через RC-фильтр или использовать ЦАП, как у ESP32.
Как рассчитать коэффициент заполнения?
Коэффициент заполнения — это время, когда сигнал в HIGH, делённое на весь период: (время HIGH / период) × 100. На Arduino его находят, деля значение analogWrite на 255 и умножая на 100; например, 64 — это примерно 25%.
Как изменить частоту PWM на Arduino?
analogWrite частоту не меняет. На Uno её можно настроить, изменив регистры таймера (например, TCCR1B для пинов 9 и 10), но это может повлиять на millis и библиотеки. На ESP32 частота задаётся прямо в ledcAttach, а на Pico — через freq().
Может ли PWM повредить светодиод?
Нет. Во время каждого импульса светодиод горит при полном токе, но этот ток уже ограничен последовательным резистором, а средний ток падает пропорционально заполнению. Если резистор подобран правильно, PWM не сокращает срок службы светодиода.
Что собрать после прочтения
Все проекты
Плавное затухание светодиода с PWM на ESP32
Плавное изменение яркости светодиода от 0 до максимума и от максимума до 0. PWM управляется через analogWrite(), как в Arduino, — тот же синтаксис без проблем работает в ESP32 Arduino Core 3.0+. Достаточно определения пина, pinMode и analogWrite.

Плавное затухание светодиода с PWM на Pico (эффект дыхания)
Светодиод больше не просто мигает — он дышит! С помощью PWM (широтно-импульсной модуляции) Raspberry Pi Pico яркость светодиода медленно растёт и медленно падает, как огонёк спящего MacBook. Изучи класс machine.PWM, duty_u16() (16-битная яркость 0–65535), частоту PWM (freq(1000) — 1000 циклов вкл/выкл в секунду, мерцания не видно), циклы range() с шагом (вверх и вниз) и почти аналоговый выход с цифрового пина.

Регулировка яркости светодиода потенциометром на ESP32 (аналог → PWM)
В этом проекте яркость светодиода плавно регулируется потенциометром. Пин АЦП ESP32 читает напряжение 0–3,3V с потенциометра, затем это значение превращается в сигнал PWM (широтно-импульсная модуляция) и подаётся на светодиод. В результате при повороте потенциометра светодиод постепенно становится ярче или тусклее. В Arduino Core 3.0+ можно сразу использовать analogWrite(); на ESP32-S2/S3 разрешение АЦП фиксировано — 12 бит.

Плавная смена цвета RGB-светодиода
Один RGB-светодиод медленно переходит от красного к зелёному, от зелёного к синему и обратно к красному, без остановки прокручивая радугу. Каждый переход длится около двух с половиной секунд, а жёлтый

Управление RGB-светодиодом на ESP32
Бесконечное число цветов одним RGB-светодиодом вместо 3 отдельных. Как в Arduino, радужный переход получается заданием значений R/G/B через analogWrite(). Теория цвета (например, красный + зелёный = жёлтый) видна на практике.

Смена цветов RGB-светодиода на Pico (3 канала PWM)
Один светодиод — миллионы цветов! RGB-светодиод содержит 3 светодиода: красный, зелёный и синий. Если управлять каждым своим каналом PWM Pico, цвета смешиваются: красный + зелёный = жёлтый, зелёный + синий = голубой, все три = белый. Светодиод перебирает 8 цветов. Изучи несколько каналов PWM, объявление функций (def set_color(...)), смешивание RGB, перевод 8 бит → 16 бит (x257) и общий катод и общий анод.

Сервопривод на ESP32 (управление потенциометром)
В этом проекте сервопривод SG90 управляется потенциометром. Угол сервопривода задаётся сопоставлением аналогового значения потенциометра с диапазоном 0–180 градусов. Библиотека ESP32Servo формирует сигналы сервопривода на подходящих выходных пинах GPIO у ESP32; этот проект использует GPIO 18. Это базовый способ управления для роборук, подвесов камер и механизмов автоматических дверей.

Смеситель цветов на ESP32 (3 потенциометра + RGB-светодиод + OLED)
Умная лампа для смешивания цветов на ESP32: вращая три потенциометра, можно получить любой цвет! Когда крутишь потенциометры красного, зелёного и синего, RGB-светодиод с общим катодом меняет цвет в реальном времени. OLED-дисплей SSD1306 показывает значения каждого цвета в диапазоне 0–255, полосы заполнения и веб-код цвета HEX (например, #FF8040). Мини-студия цвета, которая учит теории цвета RGB, чтению АЦП, регулировке яркости через PWM и дизайну экрана I2C.
Другие статьи
Приложение BlueGrays
Собери эту схему шаг за шагом в телефоне
Схема подключения, код и список деталей на одном экране. 200+ проектов на Arduino, ESP32 и Pico готовы к сборке.
Наведи камеру телефона
Наведи камеру на код — откроется магазин приложений на телефоне.
или открыть магазин

