Кратко:
rbdimmerESP32рассчитан на двухъядерный ESP32 (оригинальный и S3). ESP32-S2, C3, C6 и H2 — одноядерные. Библиотека пытается выделить задачу диммера на отдельное ядро — на одноядерных чипах это невозможно. ISR конкурирует со стеком WiFi, тайминги нарушаются, результат — мерцание, случайные сбои и нестабильная яркость. Решение — DimmerLink (аппаратный ZC + I2C) или переход на двухъядерный чип.
Описание проблемы
Вы купили ESP32-C3 или ESP32-S2 — компактный, с WiFi/BLE, недорогой.
Подключаете AC-диммер напрямую, используете rbdimmerESP32 — и видите:
- Нагрузка мерцает на любом уровне яркости
- Тайминг нестабилен —
setPower(50)даёт то 30%, то 70% - Сбои при активном WiFi — без WiFi лучше, с WiFi — хаос
- Код компилируется без ошибок, нестабильность только в рантайме
Или компилятор предупреждает о xTaskCreatePinnedToCore с несуществующим ядром.
Типичные сообщения на форумах:
- «ESP32-C3 + диммер — мерцает на любом уровне мощности»
- «rbdimmerESP32 работает на ESP32, но не на ESP32-S2»
- «setPower(50) даёт случайную яркость на C3»
- «Без WiFi работает нормально, при подключении WiFi всё ломается»
Причина проблемы
Какие чипы ESP32 двухъядерные, а какие нет
| Чип | Ядра | Архитектура | Прямое ISR-диммирование |
|---|---|---|---|
| ESP32 (оригинал) | 2 | Xtensa LX6 | ✅ rbdimmerESP32 |
| ESP32-S3 | 2 | Xtensa LX7 | ✅ rbdimmerESP32 |
| ESP32-S2 | 1 | Xtensa LX7 | ⚠️ Только DimmerLink |
| ESP32-C3 | 1 | RISC-V | ⚠️ Только DimmerLink |
| ESP32-C6 | 1 | RISC-V | ⚠️ Только DimmerLink |
| ESP32-H2 | 1 | RISC-V | ⚠️ Только DimmerLink |
⚠️ Примечание об ESP32-C6: у C6 есть дополнительное LP-ядро (Low Power), но оно не подходит для ISR-диммирования — работает на пониженной частоте без полной поддержки FreeRTOS. Основное ядро — одно.
⚠️ Частая путаница: ESP32-S3 — двухъядерный (работает). ESP32-S2 — одноядерный (не работает с прямым ISR). Это разные чипы.
Почему диммирование с фазовой отсечкой требует изоляции ядер
Тайминг затвора TRIAC: от перехода через ноль до импульса на затворе — задержка 100–9000 мкс, точность ±10–20 мкс. Любое отклонение — неправильная яркость.
rbdimmerESP32 достигает такой точности на двухъядерном чипе так:
- Ядро 0 — задача диммера (цикл тайминга, обработка ZC, включение TRIAC)
- Ядро 1 — стек WiFi, TCP/IP, пользовательский код
Они работают параллельно и не блокируют друг друга.
На одноядерном (C3, S2, H2) — оба потока делят одно ядро. Стек WiFi регулярно блокирует процессор на 1–5 мс для обработки пакетов. В это время ISR диммера пропускает своё окно → лампа мерцает.
Прерывания WiFi DMA имеют фиксированный высокий аппаратный приоритет в ESP-IDF —
они не вытесняются пользовательскими IRAM_ATTR ISR на одноядерном чипе.
portDISABLE_INTERRUPTS() тоже не помогает: WiFi DMA работает на уровне NMI.
Программно это не решается.
Решения
🟢 Для всех: DimmerLink — аппаратное решение
Единственное надёжное решение для одноядерного ESP32 с WiFi. DimmerLink сам определяет переход через ноль и управляет TRIAC — ваш MCU только отправляет уровень яркости по I2C.
Любой ESP32 has its own controller. Your ESP32-C3 only sets the brightness — no ISR, no timing-critical code on the MCU side.
Схема подключения для ESP32-C3:
- VCC → 3.3V
- GND → GND
- SDA → GPIO 8 (стандартный SDA на ESP32-C3)
- SCL → GPIO 9 (стандартный SCL на ESP32-C3)
⚠️ На некоторых модулях ESP32-C3 GPIO 8/9 используются внешней flash-памятью. Если
Wire.begin()не работает — укажите пины явно:Wire.begin(SDA_PIN, SCL_PIN)со свободными GPIO (например, 1, 10).
Схема подключения для ESP32-S2:
- SDA → GPIO 3 (проверьте распиновку вашей платы)
- SCL → GPIO 4
Код (одинаковый для всех платформ):
// DimmerLink на ESP32-C3 / S2 / H2 — без ISR на MCU
// Стабильная работа при активном WiFi
#include <Wire.h>
#define DIMMER_ADDR 0x50
#define REG_LEVEL 0x10
void setLevel(uint8_t level) { // level: 0–100%
Wire.beginTransmission(DIMMER_ADDR);
Wire.write(REG_LEVEL);
Wire.write(level);
Wire.endTransmission();
}
void setup() {
Wire.begin(); // стандартные SDA/SCL для вашей платы
setLevel(50); // яркость 50%
}
void loop() {
// WiFi можно использовать свободно — диммер не затрагивается
}Результат: Стабильная работа с WiFi/BLE на любом одноядерном ESP32.
🔵 Нужен прямой ISR — переходите на двухъядерный ESP32
Нужна архитектура с прямым ISR? Используйте оригинальный ESP32 или S3.
Оригинальный ESP32 и ESP32-S3 — двухъядерные, rbdimmerESP32 работает штатно:
// ESP32 оригинальный / ESP32-S3 — двухъядерный
// rbdimmerESP32 работает как задумано
#include "rbdimmerESP32.h"
#define ZC_PIN 18
#define DIM_PIN 19
rbdimmer dimmer;
void setup() {
Serial.begin(115200);
dimmer.begin(ZC_PIN, DIM_PIN, 50); // ZC_PIN, DIM_PIN, 50 Гц
dimmer.setPower(50);
}
void loop() {}Когда стоит менять чип:
the project
⚠️ Частые ошибки
-
«Без WiFi на C3 работает, с WiFi — мерцает»: Классический симптом конфликта ISR на одноядерном чипе. Хорошо задокументированное поведение. Решение: DimmerLink.
-
«
rbdimmerESP32скомпилировался на C3 — значит работает»: Компилируется, потому что ядро 0 существует даже на одноядерных чипах.xTaskCreatePinnedToCore(..., 0)создаст задачу, но без изоляции от WiFi. Тайминг нестабилен — это не «работает». -
«Использую ESPHome / Tasmota на ESP32-C3 — диммер не работает»: ESPHome и Tasmota на одноядерном ESP32 имеют те же ограничения, что и пользовательский код. Стек WiFi конкурирует с ISR диммера. Используйте DimmerLink с ESPHome через I2C (
i2c:+sensor:илиcustom_component). -
«У ESP32-S3 тоже есть S — он тоже одноядерный?»: Нет. ESP32-S3 — двухъядерный (как оригинальный ESP32, только LX7). Его путают с ESP32-S2. Проверьте маркировку чипа на плате.
-
«Я использую FreeRTOS вручную и могу привязать задачи сам»: На одноядерном
xTaskCreatePinnedToCore(..., 0)создаст задачу, но стек WiFi тоже на ядре 0. ЛюбойvTaskDelay(1)в задаче диммера отдаёт процессор WiFi — тайминг ломается. А прерывания WiFi DMA имеют аппаратный приоритет выше пользовательских ISR. Программно это не решается. DimmerLink — единственное надёжное решение. -
"I'm using FreeRTOS manually and can pin tasks myself": On single-core
xTaskCreatePinnedToCore(..., 0)creates the task, but the WiFi stack is also on Core 0. AnyvTaskDelay(1)in the dimmer task yields the CPU to WiFi — timing breaks. And WiFi DMA interrupts have a hardware priority above user ISR. This can't be solved in software. DimmerLink is the only reliable solution.
Экспресс-проверка
Связанные проблемы
- ESP32 + TRIAC: Guru Meditation Error →
troubleshooting/esp32-iram-attr.md - Переход через ноль не обнаружен →
troubleshooting/zero-cross-detection-errors.md - Zero-cross not detected →
troubleshooting/zero-cross-detection-errors.md
Остались вопросы?
Ask on forum.rbdimmer.com or open a GitHub Issue.