Кратко: Мерцание LED с AC-диммером имеет три различные причины. Типы 1 и 2 вызваны архитектурной несовместимостью TRIAC AC-диммеров с LED-лампами — аппаратное решение: MOSFET AC-диммер (trailing edge, разработан для LED). Если используете TRIAC-диммер, перейдите на лампу Philips/Osram/Ikea и держите яркость выше 20%. Тип 3 — нарушение тайминга ESP32 из-за WiFi/BLE — устраняется библиотекой rbdimmerESP32 или DimmerLink (применимо к любому типу диммера).
Проблема
Вы настроили диммер, код работает, детектирование перехода через ноль корректно — но LED-лампа всё равно мерцает. Это особенно заметно при яркости ниже 40–50%. Вы подозреваете проблему с прерываниями или таймингом, но изменения в коде не помогают.
Главный вывод: мерцание имеет несколько причин, требующих разных решений. Изменение кода помогает только при Типе 3 (тайминг ESP32). Для Типов 1 и 2 нужно сменить тип диммера (на MOSFET) или лампу — а не код.
Симптомы по типу мерцания:
Тип 1 (драйвер LED / архитектура TRIAC):
- «Дешёвые диммируемые LED используют затемнённую сеть напрямую для PWM, что даёт заметное мерцание» (Arduino Forum, 2019)
- Мерцание заметно при яркости ниже 40–50%; лампа нормально работает при 100%
- Изменения кода не дают эффекта — результат одинаков при любых настройках
- Даже при 50% дешёвые лампы явно мерцают
Тип 2 (ток удержания TRIAC):
- Случайные вспышки при малой яркости или небольшой нагрузке
- Гудение/жужжание при яркости ниже 20%
- Одна LED-лампа 5–7 Вт без дополнительной нагрузки
Тип 3 (тайминг ESP32):
- Нерегулярное, непредсказуемое мерцание — не синхронизировано с сетью
- Исчезает при отключении WiFi (
WiFi.disconnect()) - Появляется при активной нагрузке MQTT/HTTP на ESP32
- Качественные лампы тоже мерцают — характер меняется при изменении кода
TRIAC против MOSFET: почему тип диммера важнее кода
Типы 1 и 2 — не дефект лампы или кода. Это следствие того, что TRIAC AC-диммеры разработаны для ламп накаливания — не для LED-ламп.
| Параметр | TRIAC AC-диммер | MOSFET AC-диммер |
|---|---|---|
| Метод коммутации | Leading edge (резкий скачок в начале полупериода) | Trailing edge (плавное срезание в конце) |
| Разработан для | Лампы накаливания, галоген, резистивные нагреватели | LED-лампы, низковольтные трансформаторы |
| Ток удержания | Да — минимальный ток для поддержания открытого состояния | Нет — работает с любой нагрузкой |
| Мерцание LED | Типы 1 и 2 с дешёвыми лампами | Отсутствует — trailing edge совместим с LED |
| Диапазон диммирования LED | 20–95% (нестабильно ниже) | 5–95% |
MOSFET AC-диммер устраняет Типы 1 и 2 на аппаратном уровне:
- Trailing edge открывает нагрузку в начале каждого полупериода: драйвер LED сразу получает полное напряжение и заряжает буферные конденсаторы — пульсации 100/120 Гц исчезают.
- Нет тока удержания: стабильная работа с нагрузкой от 5 Вт.
Тип 3 (тайминг ESP32) применим к обоим типам диммеров — он не связан с методом коммутации, только с точностью прерываний MCU.
Причины мерцания
Detailed theory of zero-cross detection and TRIAC operation: AC Dimmer: Zero-Cross and TRIAC — How It Works.
Тип 1: мерцание из-за драйвера LED (специфично для TRIAC)
TRIAC срезает синусоиду AC с ведущего фронта: в каждом полупериоде первая часть отсекается, ток течёт только во второй части. При малой яркости — лишь короткий импульс тока в конце каждого полупериода.
Качественный драйвер LED сглаживает эти импульсы через конденсаторы и запускает собственный высокочастотный PWM (1–4 кГц). Результат: ровный, стабильный свет.
Дешёвый драйвер LED выпрямляет ток без буферизации. LED получает пульсирующий постоянный ток с частотой 100 Гц (сеть 50 Гц) или 120 Гц (сеть 60 Гц). Эта частота видна человеческому глазу — мерцание очевидно.
MOSFET AC-диммер (trailing edge) открывает нагрузку в начале каждого полупериода: драйвер LED сразу получает полное напряжение и заряжает конденсаторы. Пульсации 100 Гц исчезают — даже с дешёвой лампой.
Тип 2: ток удержания TRIAC (специфично для TRIAC)
У каждого TRIAC есть параметр тока удержания — минимальный ток, необходимый для поддержания проводимости. Если ток нагрузки падает ниже этого значения, TRIAC случайно выключается — до перехода через ноль. Результат: пропущенные полупериоды, случайные вспышки и жужжание при малой яркости.
MOSFET не имеет тока удержания — это транзистор, а не тиристор. Стабильная работа с нагрузкой от 5 Вт.
Тип 3: нарушение тайминга ESP32 (не зависит от типа диммера)
Управление TRIAC требует точности ±50 мкс: MCU должен открыть TRIAC ровно через рассчитанную задержку после перехода через ноль. WiFi-стек ESP32 и задачи RTOS могут задержать выполнение ISR на 200–500 мкс — мерцание появляется при активном WiFi.
Источники задержек:
- WiFi / BLE стек временно блокирует прерывания при обработке пакетов
- Доступ к Flash (OTA, SPIFFS, Serial) — заморозка на 10–100 мс
- ISR не в IRAM: ESP32 обращается к Flash при каждом вызове — добавляет задержку
loop()и WiFi работают на одном ядре (Core 1) и конкурируют за CPU
Ключевое отличие от Типов 1 и 2: мерцание нерегулярно, исчезает
при WiFi.disconnect() и меняется при изменении кода — а не при смене лампы.
Detailed breakdown: How to Fix ESP32 AC Dimmer Flickering.
Решения
🔑 Лучшее решение: MOSFET AC-диммер
Устраняет Типы 1 и 2 на аппаратном уровне — без замены лампы, без настройки кода.
MOSFET AC-диммер (trailing edge) создан специально для LED-ламп. Коммутация trailing edge даёт драйверу LED чистое начало каждого полупериода — пульсации 100/120 Гц исчезают. Нет тока удержания — стабильная работа с одной лампой 5–7 Вт.
Когда выбрать MOSFET AC-диммер:
Тип 3 (тайминг ESP32) применим и к MOSFET-диммерам — точность ISR одинаково важна. Используйте rbdimmerESP32 или DimmerLink для его устранения.
🟢 Начальный уровень: TRIAC + качественная лампа или DimmerLink
Используете TRIAC-диммер? Два варианта: заменить лампу или использовать DimmerLink.
Вариант 1: Замените лампу на модель с качественным драйвером LED:
- Philips WarmGlow, SceneSwitch, Master LED
- Osram CLASSIC A, SUPERSTAR
- Ikea TRÅDFRI (диммируемый диапазон)
Ищите на упаковке: «TRIAC dimmable», «phase-cut compatible», «leading edge compatible».
Вариант 2: Минимальная нагрузка.
Не менее 15–20 Вт. При меньшей нагрузке подключите балластный резистор параллельно: 100–150 Ом / 20 Вт.
Вариант 3: Управление по I2C без ISR — DimmerLink.
If you use Raspberry Pi, ESP32-S2/C3/H2, or simply don't want to deal with interrupts — Любой ESP32 controls TRIAC via I2C without writing any ISR code.
Когда выбрать DimmerLink:
// DimmerLink по I2C — без ISR, без перехода через ноль в вашем коде
// Работает с: Arduino, ESP32, Raspberry Pi
// Документация: https://www.rbdimmer.com/docs/dimmerlink-I2CCommunication
#include <Wire.h>
#define DIMMER_ADDR 0x50
#define REG_LEVEL 0x10
// Устанавливает яркость (20–95% для LED-ламп с TRIAC)
void setLevel(uint8_t level) {
Wire.beginTransmission(DIMMER_ADDR);
Wire.write(REG_LEVEL);
Wire.write(level);
Wire.endTransmission();
}
void setup() {
Wire.begin();
setLevel(50); // яркость 50%
}
void loop() {}Результат: стабильная яркость без мерцания при использовании качественной лампы.
🔵 Продвинутый уровень: исправление тайминга ESP32 (Тип 3)
Тип 3 применим к любому AC-диммеру — TRIAC или MOSFET.
Сначала определите тип мерцания — иначе исправление не поможет:
| Симптом | Тип | Решение |
|---|---|---|
| Одинаковое мерцание при любом коде | Тип 1 — драйвер LED | MOSFET AC-диммер или замена лампы |
| Случайные вспышки, жужжание ниже 20% | Тип 2 — ток удержания TRIAC | MOSFET AC-диммер или мин. 20% |
| Меняется при вкл/выкл WiFi | Тип 3 — тайминг ESP32 | IRAM_ATTR / rbdimmerESP32 |
Исправление тайминга ESP32 (Тип 3)
Если мерцание исчезает при WiFi.disconnect() — проблема в тайминге ISR.
// Проблема: ISR не в IRAM — ESP32 читает его из Flash при каждом вызове
// Решение: IRAM_ATTR размещает ISR в RAM постоянно
// ❌ Неверно (без IRAM_ATTR — мерцание при нагрузке WiFi):
void zeroCrossISR() {
triggerTriac();
}
// ✅ Верно (IRAM_ATTR — ISR всегда в RAM, без задержек Flash):
void IRAM_ATTR zeroCrossISR() {
triggerTriac();
}For ESP32 двухъядерный, IRAM_ATTR is applied automatically inside the library.
Разделение ядер дополнительно повышает стабильность:
// rbdimmerESP32: ISR работает на Core 0 (системное ядро)
// loop() и WiFi работают на Core 1 — нет конкуренции за CPU
#include "rbdimmerESP32.h"
// ... остальной код без измененийКлючевое правило для LED-ламп: никогда не устанавливайте яркость ниже 20%. Большинство LED-ламп нестабильны в диапазоне 0–15%.
Вариант A: ESP32 с rbdimmerESP32 ✅ Рекомендуется
When: dual-core ESP32 only (not S2/C3/H2) Library: rbdimmerESP32 — docs · GitHub
// Платформа: двухъядерный ESP32
// Библиотека: rbdimmerESP32
// Диапазон: 20–95% для стабильного диммирования LED с TRIAC
#include "rbdimmerESP32.h"
#define ZC_PIN 18 // вход перехода через ноль
#define DIM_PIN 19 // управление затвором TRIAC
rbdimmer dimmer;
// Ограничивает диапазон яркости для LED-ламп
void setLedLevel(uint8_t percent) {
// Преобразует 0–100% → 20–95% для стабильности LED с TRIAC
uint8_t mapped = 20 + (percent * 75) / 100;
if (mapped > 95) mapped = 95;
dimmer.setPower(mapped);
}
void setup() {
dimmer.begin(ZC_PIN, DIM_PIN, 50); // сеть 50 Гц
setLedLevel(50);
}
void loop() {}Типичные ошибки:
- Использование
rbdimmerESP32на одноядерном ESP32 (S2/C3/H2) — не поддерживается - Установка яркости = 0 вместо вызова off: TRIAC нестабилен при очень малых
углах открытия. Используйте
setPower(0)только для полного отключения.
Вариант Б: Arduino AVR (Uno, Mega, Nano)
When: AVR boards only — do not use on ESP32! Library: Arduino Uno/Mega (legacy)
// Платформа: Arduino Uno / Mega / Nano (только AVR)
// ВНИМАНИЕ: для ESP32 используйте rbdimmerESP32!
// Переход через ноль: только пины 2 или 3 на Uno/Nano
#include <RBDdimmer.h>
#define ZC_PIN 2 // переход через ноль — только пины 2 или 3
#define DIM_PIN 11 // пин с PWM
dimmerLamp dimmer(DIM_PIN, ZC_PIN);
void setup() {
dimmer.begin(NORMAL_MODE, ON);
dimmer.setPower(20); // минимум 20% для LED-ламп
}
void loop() {}⚠️ Типичные ошибки с форумов
Реальные ошибки из 3 форумных тредов (2019–2025).
-
«Пробовал разный код — мерцание не уходит»: Код не является причиной для Типов 1 и 2. Нужно заменить диммер (MOSFET AC-диммер) или лампу (Philips/Osram).
-
«Ниже 30% яркости — случайные яркие вспышки»: Ток удержания TRIAC (Тип 2). Решение: MOSFET AC-диммер, или держать яркость выше 20%, или добавить нагрузку.
-
«При 100% работает, мерцает только при диммировании»: Классический признак дешёвого драйвера LED (Тип 1). При полной мощности синусоида не срезается. MOSFET AC-диммер или замена лампы решают проблему.
-
«Добавил delay() в loop() — стало чуть лучше»: Иллюзия. Случайная синхронизация с частотой сети. При другой яркости мерцание вернётся.
-
«ESP32 мерцает только при активном WiFi»: Тип 3 — нарушение тайминга ISR. Решение:
rbdimmerESP32(IRAM_ATTR применяется автоматически) или DimmerLink (аппаратная изоляция управления диммером).
Краткий чек-лист
Перед публикацией на форуме проверьте:
→ Тип 3 — используйте IRAM_ATTR или rbdimmerESP32
Таблица совместимости
| Лампа | TRIAC (leading edge) | MOSFET (trailing edge) | Примечания |
|---|---|---|---|
| Philips WarmGlow / Master LED | ✅ 10–95% | ✅ 5–95% | Рекомендуется |
| Osram SUPERSTAR | ✅ 15–95% | ✅ 5–95% | Рекомендуется |
| Ikea TRÅDFRI dimmable | ✅ 10–95% | ✅ 5–95% | Рекомендуется |
| Дешёвая «dimmable» без бренда | ⚠️ Мерцает < 40% | ✅ 5–95% | MOSFET устраняет |
| Лампа накаливания | ✅ 10–95% | ✅ 5–95% | Идеальная резистивная нагрузка |
| Любой «non-dimmable» LED | ❌ Постоянное мерцание | ❌ Возможно | Замените лампу |
Похожие темы
- LED Lamps with AC Dimmer: TRIAC vs MOSFET — Compatibility Guide
- Trailing Edge vs Leading Edge: Which Dimmer Method to Choose
Остались вопросы?
Post on rbdimmer.com forum or open a GitHub Issue.