In breve:
rbdimmerESP32è progettato per ESP32 dual-core (originale e S3). ESP32-S2, C3, C6 e H2 sono single-core. La libreria tenta di isolare il task del dimmer su un core dedicato — il che è impossibile sui chip single-core. La ISR compete con lo stack WiFi, il timing viene compromesso e il risultato è sfarfallio, anomalie casuali e luminosità instabile. La soluzione è DimmerLink (ZC hardware + I2C) o il passaggio a un chip dual-core.
Descrizione del problema
Hai acquistato un ESP32-C3 o ESP32-S2 — compatto, con WiFi/BLE, economico.
Colleghi un dimmer AC direttamente, usi rbdimmerESP32 — e osservi:
- Il carico sfarfalla a qualsiasi livello di luminosità
- Il timing è instabile —
setPower(50)dà il 30 % un istante, il 70 % l'istante dopo - Anomalie con WiFi attivo — funziona meglio senza WiFi, caos con il WiFi
- Il codice compila senza errori, instabilità solo a runtime
Oppure il compilatore avvisa riguardo a xTaskCreatePinnedToCore con un core inesistente.
Messaggi tipici nei forum:
- «ESP32-C3 + dimmer — sfarfallio a qualsiasi livello di potenza»
- «rbdimmerESP32 funziona su ESP32 ma non su ESP32-S2»
- «setPower(50) dà luminosità casuale su C3»
- «Funziona senza WiFi, si blocca appena il WiFi si connette»
Causa profonda
Quali chip ESP32 sono dual-core e quali no
| Chip | Core | Architettura | Dimming ISR diretto |
|---|---|---|---|
| ESP32 (originale) | 2 | Xtensa LX6 | ✅ rbdimmerESP32 |
| ESP32-S3 | 2 | Xtensa LX7 | ✅ rbdimmerESP32 |
| ESP32-S2 | 1 | Xtensa LX7 | ⚠️ Solo DimmerLink |
| ESP32-C3 | 1 | RISC-V | ⚠️ Solo DimmerLink |
| ESP32-C6 | 1 | RISC-V | ⚠️ Solo DimmerLink |
| ESP32-H2 | 1 | RISC-V | ⚠️ Solo DimmerLink |
⚠️ Nota sull'ESP32-C6: il C6 ha un core LP aggiuntivo (Low Power), ma non è adatto al dimming ISR — opera a frequenza ridotta senza supporto completo di FreeRTOS. Il core principale è singolo.
⚠️ Confusione frequente: l'ESP32-S3 è dual-core (funziona). L'ESP32-S2 è single-core (non funziona con ISR diretta). Sono chip diversi.
Perché la dimmerizzazione con taglio di fase richiede l'isolamento dei core
Timing del gate TRIAC: dal passaggio per lo zero all'impulso del gate — un ritardo di 100–9000 µs, precisione ±10–20 µs. Qualsiasi ritardo significa luminosità errata.
rbdimmerESP32 raggiunge questa precisione su dual-core in questo modo:
- Core 0 — task del dimmer (loop di timing, gestione ZC, attivazione TRIAC)
- Core 1 — stack WiFi, TCP/IP, codice utente
Funzionano in parallelo e non si bloccano a vicenda.
Su single-core (C3, S2, H2) — entrambi i thread condividono un unico core. Lo stack WiFi blocca regolarmente la CPU per 1–5 ms per elaborare i pacchetti. Durante quel tempo la ISR del dimmer perde la sua finestra di timing → la lampada sfarfalla.
Gli interrupt DMA WiFi hanno una priorità hardware alta fissa in ESP-IDF —
non vengono interrotti dalle ISR IRAM_ATTR a livello utente su single-core.
portDISABLE_INTERRUPTS() non aiuta: il DMA WiFi opera a livello NMI.
Questo non può essere risolto via software.
Soluzioni
🟢 Per tutti: DimmerLink — soluzione hardware
L'unica soluzione affidabile per ESP32 single-core con WiFi. DimmerLink rileva il passaggio per lo zero e controlla il TRIAC autonomamente — il tuo MCU invia solo il livello di luminosità via I2C.
DimmerLink has its own controller. Your ESP32-C3 only sets the brightness — no ISR, no timing-critical code on the MCU side.
Cablaggio per ESP32-C3:
- VCC → 3.3V
- GND → GND
- SDA → GPIO 8 (SDA predefinito su ESP32-C3)
- SCL → GPIO 9 (SCL predefinito su ESP32-C3)
⚠️ Su alcuni moduli ESP32-C3 i GPIO 8/9 sono utilizzati dalla flash esterna. Se
Wire.begin()non funziona — specifica i pin esplicitamente:Wire.begin(SDA_PIN, SCL_PIN)con GPIO liberi (es. 1, 10).
Cablaggio per ESP32-S2:
- SDA → GPIO 3 (verifica la piedinatura della tua scheda)
- SCL → GPIO 4
Codice (identico per tutte le piattaforme):
// DimmerLink su ESP32-C3 / S2 / H2 — nessuna ISR sul MCU
// Funzionamento stabile con WiFi attivo
#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 predefiniti per la tua scheda
setLevel(50); // luminosità 50%
}
void loop() {
// Il WiFi può essere usato liberamente — il dimmer non è influenzato
}Risultato: Funzionamento stabile con WiFi/BLE su qualsiasi ESP32 single-core.
🔵 Vuoi la ISR diretta — passa a un ESP32 dual-core
Serve l'architettura ISR diretta? Usa l'ESP32 originale o l'S3.
L'ESP32 originale e l'ESP32-S3 sono dual-core, rbdimmerESP32 funziona normalmente:
// ESP32 originale / ESP32-S3 — dual-core
// rbdimmerESP32 funziona come previsto
#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 Hz
dimmer.setPower(50);
}
void loop() {}Quando conviene cambiare chip:
the project
⚠️ Errori comuni
-
«Funziona senza WiFi su C3, sfarfalla con WiFi»: Sintomo classico del conflitto ISR su single-core. Comportamento ben documentato. Soluzione: DimmerLink.
-
«
rbdimmerESP32compila su C3 — dovrebbe funzionare»: Compila perché il core 0 esiste anche sui chip single-core.xTaskCreatePinnedToCore(..., 0)creerà il task, ma senza isolamento dal WiFi. Il timing è instabile — questo non è «funzionare». -
«Uso ESPHome / Tasmota su ESP32-C3 — il dimmer non funziona»: ESPHome e Tasmota su ESP32 single-core hanno le stesse limitazioni del codice personalizzato. Lo stack WiFi compete con la ISR del dimmer. Usa DimmerLink con ESPHome via I2C (
i2c:+sensor:o uncustom_component). -
«Anche l'ESP32-S3 ha la S — è single-core anche quello?»: No. L'ESP32-S3 è dual-core (come l'ESP32 originale, solo LX7). Viene confuso con l'ESP32-S2. Controlla la marcatura del chip sulla tua scheda.
-
«Uso FreeRTOS manualmente e posso assegnare i task da solo»: Su single-core
xTaskCreatePinnedToCore(..., 0)crea il task, ma lo stack WiFi è anch'esso sul core 0. QualsiasivTaskDelay(1)nel task del dimmer cede la CPU al WiFi — il timing si rompe. E gli interrupt DMA WiFi hanno una priorità hardware superiore alle ISR utente. Questo non si risolve via software. DimmerLink è l'unica soluzione affidabile. -
"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.
Controllo rapido
Problemi correlati
- ESP32 + TRIAC: Guru Meditation Error →
troubleshooting/esp32-iram-attr.md - Passaggio per lo zero non rilevato →
troubleshooting/zero-cross-detection-errors.md - Zero-cross not detected →
troubleshooting/zero-cross-detection-errors.md
Hai ancora domande?
Ask on forum.rbdimmer.com or open a GitHub Issue.