TL;DR: Нерегулярное мерцание при 5–25% яркости (стабильно от 50% и выше) вызвано джиттером сигнала перехода через ноль, задержками ISR от WiFi на ESP32/ESP8266 или срывами тока удержания TRIAC. Решение: установите минимальный стабильный уровень (10–15%), используйте
rbdimmerESP32на ESP32, фильтруйте линию перехода через ноль, или переходите на DimmerLink для аппаратного управления таймингом.
Эта статья vs. статья о мерцании LED
Важно: Эта статья о резистивных нагрузках — лампах накаливания, галогенных лампах, нагревательных элементах — мерцающих при малых уровнях диммера. Симптом: нерегулярное медленное колебание (0,5–8 Гц), которое исчезает при средней и высокой яркости.
Если вы используете светодиодные лампы и наблюдаете мерцание при любой яркости — проблема в совместимости TRIAC–LED, а не в тайминге при малой яркости. См.: Мерцание LED с AC диммером
Как выглядит проблема
- Лампа, установленная на 10–20%, заметно и нерегулярно мерцает.
- Та же лампа при 50% абсолютно стабильна.
- Замена контроллера на Arduino устраняет мерцание, но ESP32 или ESP8266 с WiFi — нет.
- Разные мощности ламп дают разные минимальные стабильные уровни (лампа 40 Вт может быть стабильна с 18%, а 100 Вт — с 8%).
Причины
Причина 1 — Джиттер перехода через ноль
Фазовое диммирование включает TRIAC с точной задержкой после каждого перехода через ноль переменного тока. При яркости 10% задержка составляет ~9 мс (при 50 Гц сети, полупериод = 10 мс):
задержка = (1 - уровень/100) × полупериод
задержка при 10% = (1 - 0,10) × 10 мс = 9,0 мсДжиттер ±0,5 мс сигнала перехода через ноль — это лишь 5% ошибка при яркости 50%, но 55% ошибка угла включения при 10%. Это создаёт большие видимые скачки яркости.
Источники джиттера перехода через ноль:
- помехи сетевого напряжения и EMI на линии перехода через ноль;
- длинный кабель перехода через ноль, проложенный параллельно AC кабелям;
- недостаточная развязка на плате детектора перехода через ноль.
Причина 2 — Задержки ISR на ESP32 (WiFi)
Библиотека rbdimmerESP32 привязывает процедуру обработки прерываний
к ядру 0 с атрибутом IRAM_ATTR. Если вы используете неверную библиотеку
(RBDdimmer вместо rbdimmerESP32) или скетч препятствует правильной
привязке ISR, стек WiFi может задержать прерывание DIM на 1–5 мс.
При яркости 10% (окно задержки 9 мс) задержка WiFi 2 мс — это 22% относительная ошибка тайминга — достаточно, чтобы полностью пропустить окно включения в некоторых полупериодах.
На Arduino (AVR) прерывание обрабатывается аппаратно в реальном времени — без задержки, следовательно, без мерцания от этой причины.
Причина 3 — Ток удержания TRIAC
При очень малых углах проводимости (< 8–10% уровня) ток через нагрузку может упасть ниже тока удержания TRIAC до того, как прибор полностью зафиксируется. В одних полупериодах TRIAC включается, в других нет. Это создаёт медленное нерегулярное мерцание 1–8 Гц — в отличие от плавного диммирования при более высоких уровнях.
Минимальный стабильный уровень, ограниченный током удержания, зависит от мощности нагрузки:
| Нагрузка | Прибл. минимальный стабильный уровень |
|---|---|
| Накаливание 25–40 Вт | 20–25% |
| Накаливание 60 Вт | 15% |
| Накаливание 100 Вт | 8–10% |
| Накаливание 150 Вт | 5–8% |
| Нагревательный элемент 500 Вт | 3–5% |
Причина 4 — Слишком низкий минимальный уровень мощности
В ESPHome компонент ac_dimmer имеет параметр min_power. Установка
его ниже стабильного порога для вашей нагрузки заставляет компонент
пытаться включаться при углах, при которых TRIAC не может надёжно
зафиксироваться.
Диагностика
- Определите нагрузку — сначала проверьте с лампой 100 Вт. Если стабильна при 10%, у исходной нагрузки проблема с током удержания при такой мощности.
- Проверьте платформу — замените ESP32/ESP8266 на Arduino Uno. Если мерцание исчезает, проблема в задержках ISR (Причина 2) или джиттере перехода через ноль (Причина 1).
- Осмотрите прокладку кабеля перехода через ноль — если кабель проходит рядом с AC кабелями, проложите его в другом месте и повторите тест.
- Измерьте импульс перехода через ноль осциллографом или логическим анализатором. Джиттер > 200 мкс при 50 Гц указывает на зашумлённый сигнал.
Решения
🟢 Для начинающих — Используйте DimmerLink
DimmerLink управляет детектированием перехода через ноль и включением TRIAC на собственном микроконтроллере Cortex-M0+. Джиттер включения менее 50 мкс независимо от того, что делает МК хоста (ESP32, Raspberry Pi, Arduino). Активность WiFi не влияет на тайминг.
// ESP32 + DimmerLink — установить 15% яркости по I2C
#include <Wire.h>
Wire.begin();
Wire.beginTransmission(0x50);
Wire.write(0x10); // DIM0_LEVEL
Wire.write(15); // 15% — стабильно на этом уровне
Wire.endTransmission();С DimmerLink нет мерцания при малой яркости, потому что прошивка обеспечивает чистые импульсы включения с помощью аппаратных таймеров.
🔵 Для продвинутых пользователей — Исправления для конкретной платформы
Вариант A — Установите минимальный стабильный уровень
Экспериментально найдите минимальный стабильный уровень для вашей конкретной нагрузки, затем ограничьте диапазон управления снизу.
rbdimmerESP32 / RBDdimmer:
const uint8_t MIN_STABLE_LEVEL = 12; // настройте под свою нагрузку
void setDimmerLevel(uint8_t requestedLevel) {
if (requestedLevel == 0) {
dimmer.setState(OFF);
} else {
uint8_t level = max(requestedLevel, MIN_STABLE_LEVEL);
dimmer.setState(ON);
dimmer.setPower(level);
}
}ESPHome:
output:
- platform: ac_dimmer
id: triac_out
gate_pin: GPIO4
zero_cross_pin: GPIO5
min_power: 0.12 # 12% — настройте под свою нагрузку
zero_means_zero: trueВариант B — Проверьте IRAM_ATTR на ESP32
Убедитесь, что используете rbdimmerESP32, а не RBDdimmer:
// Правильно для двухъядерного ESP32:
#include <rbdimmerESP32.h>
rbdimmer::Dimmer dimmer(DIM_PIN, ZC_PIN, CHANNEL_1, 50);
// Неправильно для ESP32 — нет IRAM_ATTR, ISR может быть вытеснен:
// #include <RBDdimmer.h>Также убедитесь, что задачи WiFi не привязывают себя к ядру 0:
// Выделенная задача WiFi должна выполняться на ядре 1
xTaskCreatePinnedToCore(wifiTask, "WiFi", 4096,
NULL, 1, NULL, 1 /*ядро 1*/);Вариант C — Фильтрация линии перехода через ноль
Добавьте простой RC фильтр для снижения высокочастотных помех на сигнале перехода через ноль:
Выход перехода через ноль ── 100 Ом ──┬── Вход МК ZC
│
100 пФ
│
GNDДополнительно:
- Прокладывайте кабель перехода через ноль не менее 2–3 см от AC кабелей.
- Если AC и ZC кабели должны пересекаться, располагайте их под прямым углом.
- Держите кабель перехода через ноль короче 30 см.
Вариант D — Переключитесь на кривую RMS диммирования
Кривая RMS концентрирует чувствительность управления в диапазоне 20–80%, что позволяет избежать нестабильной нижней зоны:
rbdimmerESP32:
// После begin():
dimmer.setCurve(RBDIMMER_CURVE_RMS);DimmerLink (регистр I2C 0x11):
Wire.beginTransmission(0x50);
Wire.write(0x11); // DIM0_CURVE
Wire.write(1); // 1 = RMS
Wire.endTransmission();| Кривая | Код | Лучше всего для |
|---|---|---|
| LINEAR | 0 | Универсальная (по умолчанию) |
| RMS | 1 | Накаливание, галоген |
| LOG | 2 | Диммируемые LED (восприятие глазом) |
Матрица платформ
| Платформа | Вероятная причина | Решение |
|---|---|---|
| Arduino Uno / Mega | Джиттер ZC или ток удержания | min_power + RC фильтр |
| ESP32 с WiFi | Задержка ISR + джиттер ZC | rbdimmerESP32 + IRAM_ATTR |
| ESP8266 с WiFi | Задержка ISR | Мин. уровень 15%+, или DimmerLink |
| Любая платформа, нагрузка < 40 Вт | Ток удержания | Ограничьте мин. уровень |
| Любая платформа, гарантированно | Аппаратное решение | DimmerLink |
Краткий чеклист
Связанные статьи
- Лампа не выключается при 0% → AC диммер не выключается
- Мерцание LED → Мерцание LED с AC диммером
- Исправление ESP32 IRAM_ATTR → Guru Meditation и IRAM_ATTR
- Неверная библиотека на ESP32 → Неверная библиотека: RBDdimmer vs rbdimmerESP32
- Ошибки детектирования перехода через ноль → Ошибки детектирования перехода через ноль
Остались вопросы?
Задайте на forum.rbdimmer.com или откройте GitHub Issue.