En bref : Un variateur AC ne peut pas réguler la charge si le microcontrôleur ne reçoit pas le signal de passage par zéro (le moment où la sinusoïde traverse zéro). Sans ce signal, il est impossible de calculer le moment d'amorçage du TRIAC. Causes : mauvaise broche (ne supporte pas les interruptions), câblage ZC incorrect, bruit sur la ligne de signal ou erreur logicielle (mauvais mode d'interruption). Suivez la checklist ci-dessous étape par étape.
Description du problème
Vous avez connecté un variateur AC, téléversé le code d'exemple — mais la charge ne répond pas ou est toujours à pleine luminosité. Le câblage semble correct, pas d'erreurs de compilation.
La cause la plus fréquente est que le passage par zéro n'est pas détecté par le microcontrôleur. La variation par découpe de phase fonctionne selon ce principe : détecter le passage par zéro de la sinusoïde → attendre le délai calculé → amorcer le TRIAC. Sans passage par zéro il n'y a pas de timing, et le variateur soit n'allume pas la charge du tout, soit la maintient à 100% sans régulation.
Symptômes typiques :
- Charge toujours à pleine luminosité (TRIAC toujours ouvert)
- Charge ne s'allume pas du tout
setPower(50)n'a aucun effet — charge soit complètement allumée, soit éteinte- Le compteur de passages par zéro ne s'incrémente pas dans le moniteur série (avec debug)
- Le code compile sans erreurs mais le variateur « ne fonctionne pas »
Messages typiques sur les forums :
- « Le variateur ne varie pas — lampe toujours à pleine luminosité »
- « setPower n'a aucun effet »
- « L'interruption de passage par zéro ne se déclenche pas »
- « Le variateur fonctionne parfois, aléatoirement »
Cause profonde
Le signal de passage par zéro est généré par un circuit détecteur de passage par zéro intégré au variateur AC ou connecté en externe. C'est typiquement un optocoupleur + diviseur résistif qui produit une courte impulsion à chaque passage par zéro de la sinusoïde.
Fréquence des impulsions : 100 Hz (secteur 50 Hz) / 120 Hz (secteur 60 Hz). Une impulsion par demi-cycle.
Pour recevoir ces impulsions, le microcontrôleur utilise une interruption
externe (attachInterrupt()). Si l'interruption n'est pas configurée
correctement ou si le signal n'atteint pas la bonne broche — le gestionnaire
ISR n'est jamais appelé, le timing ne peut pas être calculé, et le variateur
ne fonctionne pas.
Causes principales de défaillance :
- Mauvaise broche (ne supporte pas les interruptions) — erreur la plus fréquente sur Arduino
- Câblage ZC incorrect — le signal n'atteint pas la broche
- Mauvais mode d'interruption (
FALLINGau lieu deRISINGou l'inverse — dépend du circuit) - Bruit — déclenchements parasites multiples sur un demi-cycle
- Problème d'alimentation du circuit ZC — pas de VCC sur le détecteur de passage par zéro
Solutions
🟢 Pour les débutants : DimmerLink — passage par zéro intégré
Vous ne voulez pas vous occuper des broches d'interruption, RISING/FALLING et du bruit électrique ? DimmerLink possède son propre détecteur de passage par zéro et contrôle le TRIAC de manière autonome.
❌ non supporté detects zero-cross in hardware and handles TRIAC firing timing internally. Your microcontroller only sets the brightness level — no ISR, no interrupts, no pin headaches.
Quand choisir cette solution :
DimmerLink → Arduino/ESP32 câblage :
- VCC → 3.3V (ESP32) ou 5V (Arduino)
- GND → GND
- SDA → SDA (GPIO 21 sur ESP32, A4 sur Arduino Uno)
- SCL → SCL (GPIO 22 sur ESP32, A5 sur Arduino Uno)
Code :
// DimmerLink — détecteur de passage par zéro et contrôle TRIAC dans le module
// Le microcontrôleur ne fait que définir le niveau de luminosité
// Documentation : https://www.rbdimmer.com/docs/dimmerlink-I2CCommunication
#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 par défaut pour votre carte
setLevel(50); // luminosité 50%
}
void loop() {
// Pas d'ISR, pas d'interruptions, pas de passage par zéro sur le MCU
}Résultat : Le variateur fonctionne sans dépendre des broches d'interruption ou du signal de passage par zéro sur le microcontrôleur.
🔵 Pour les utilisateurs avancés : diagnostiquer et corriger le ZC
Vous voulez garder la connexion ISR directe ? Suivez les étapes de diagnostic.
Diagnostic : étapes 1–5
Étape 1 : Vérifier que la broche supporte les interruptions
C'est la cause n°1 sur Arduino.
// Arduino Uno / Nano / Mini :
// ✅ Supportent les interruptions : UNIQUEMENT les broches 2 et 3
// ❌ Toutes les autres broches (4, 5, 6...) — interruptions non supportées
// Correct :
attachInterrupt(digitalPinToInterrupt(2), zeroCrossISR, RISING); // broche 2 ✅
attachInterrupt(digitalPinToInterrupt(3), zeroCrossISR, RISING); // broche 3 ✅
// Incorrect :
attachInterrupt(4, zeroCrossISR, RISING); // ❌ broche 4 — ne supporte pas les interruptions
// Sur l'Uno, attachInterrupt(4) fait référence à INT4, qui n'existe pasSur ESP32 — n'importe quel GPIO supporte les interruptions :
// ESP32 : n'importe quel GPIO — tous fonctionnent
attachInterrupt(digitalPinToInterrupt(18), zeroCrossISR, RISING); // ✅
attachInterrupt(digitalPinToInterrupt(34), zeroCrossISR, RISING); // ✅Sur ESP8266 — tous les GPIO sauf GPIO 16 supportent les interruptions ; recommandés : 4, 5, 12, 13, 14 (pas de dépendances au mode de démarrage).
Étape 2 : Ajouter un compteur pour vérifier
Le test le plus simple — compter les impulsions sur 1 seconde :
// Diagnostic de passage par zéro : ~100 impulsions/sec attendues (secteur 50 Hz)
// ou ~120 impulsions/sec (secteur 60 Hz)
#define ZC_PIN 2 // ← assurez-vous que c'est une broche supportant les interruptions
volatile uint32_t zcCount = 0;
#ifdef ESP32
void IRAM_ATTR zeroCrossISR() { // IRAM_ATTR requis sur ESP32
#else
void zeroCrossISR() { // Arduino/ESP8266 : IRAM_ATTR non nécessaire
#endif
zcCount++;
}
void setup() {
Serial.begin(115200);
pinMode(ZC_PIN, INPUT);
attachInterrupt(digitalPinToInterrupt(ZC_PIN), zeroCrossISR, RISING);
}
void loop() {
delay(1000);
Serial.print("Impulsions ZC par seconde : ");
Serial.println(zcCount);
zcCount = 0;
// Résultats attendus :
// ~100 — secteur 50 Hz, tout va bien
// ~120 — secteur 60 Hz, tout va bien
// 0 — ZC non détecté (problème de câblage ou de broche)
// >200 — bruit, déclenchements parasites (problème de filtre RC)
}Étape 3 : Vérifier le câblage ZC
Câblage typique RBDimmer → Arduino/ESP32 :
RBDimmer → Arduino/ESP32
------- -------------
VCC → 5V (Arduino) / 3.3V (ESP32)
GND → GND
ZC → Broche avec interruption (2 ou 3 sur Arduino Uno)
DIM → N'importe quelle sortie numériqueChecklist :
Étape 4 : Vérifier le mode d'interruption (RISING/FALLING/CHANGE)
Le mode dépend du circuit détecteur ZC de votre module :
// La plupart des modules RBDimmer : RISING (impulsion sur front montant)
attachInterrupt(digitalPinToInterrupt(ZC_PIN), zeroCrossISR, RISING);
// Certains circuits avec optocoupleur inverseur : FALLING
attachInterrupt(digitalPinToInterrupt(ZC_PIN), zeroCrossISR, FALLING);
// Si incertain — essayez CHANGE (capture les deux fronts) :
// Note : avec CHANGE le compteur affichera ~200 Hz au lieu de 100 Hz
attachInterrupt(digitalPinToInterrupt(ZC_PIN), zeroCrossISR, CHANGE);Utilisez un oscilloscope ou un analyseur logique pour vérifier la forme du signal ZC — déterminez si vous devez capturer le front montant ou descendant.
Étape 5 : Filtrer le bruit
Si le compteur affiche >200 (sur un réseau 50 Hz) — déclenchements parasites
dus au bruit. C'est fréquent avec des fils longs ou la proximité de la charge :
// Anti-rebond logiciel pour ZC : ignorer les impulsions trop proches de la précédente
// Période du demi-cycle à 50 Hz = 10 000 µs → filtrer tout ce qui est inférieur à 8 000 µs
volatile uint32_t lastZC = 0;
void IRAM_ATTR zeroCrossISR() {
uint32_t now = micros();
if (now - lastZC > 8000) { // intervalle minimum de 8 ms entre impulsions ZC
lastZC = now;
// votre logique de timing TRIAC ici
}
}Filtre matériel : un filtre RC sur la ligne ZC (résistance 1 kΩ + condensateur 100 nF entre ZC et GND) élimine le bruit haute fréquence.
Correction : choisissez votre option
Option A : rbdimmerESP32 sur ESP32 ✅
Quand : ESP32 double cœur avec connexion directe au variateur. La bibliothèque gère le ZC et le timing automatiquement :
// Plateforme : ESP32 double cœur
// Bibliothèque : rbdimmerESP32
#include "rbdimmerESP32.h"
#define ZC_PIN 18 // n'importe quel GPIO ESP32
#define DIM_PIN 19 // n'importe quel GPIO ESP32
rbdimmer dimmer;
void setup() {
Serial.begin(115200);
dimmer.begin(ZC_PIN, DIM_PIN, 50); // secteur 50 Hz
dimmer.setPower(50);
Serial.println("Variateur initialisé");
}
void loop() {}Erreurs courantes :
- ZC_PIN et DIM_PIN inversés dans
dimmer.begin()— vérifiez quelle broche va à la charge et laquelle au passage par zéro. - Mauvaise fréquence secteur (troisième paramètre) — 50 ou 60 Hz.
Option B : Arduino Uno/Mega avec RBDdimmer
// Plateforme : Arduino Uno / Mega / Nano (AVR)
// Bibliothèque : RBDdimmer — https://github.com/robotdyn/dimmer
// ATTENTION : pour ESP32 utilisez rbdimmerESP32, pas cette bibliothèque !
#include <RBDdimmer.h>
// ⚠️ Arduino Uno : ZC UNIQUEMENT sur les broches 2 ou 3
#define ZC_PIN 2 // supporte les interruptions ✅
#define DIM_PIN 11 // n'importe quelle sortie numérique
dimmerLamp dimmer(DIM_PIN, ZC_PIN);
void setup() {
Serial.begin(9600);
dimmer.begin(NORMAL_MODE, ON);
dimmer.setPower(50); // 50%
Serial.println("Variateur prêt");
}
void loop() {}⚠️ Pièges courants
-
« J'utilise la broche 4 sur Arduino Uno — ne fonctionne pas » : Les broches 4, 5, 6, ... sur l'Uno ne supportent pas les interruptions externes. Seules les broches 2 et 3 les supportent. C'est l'erreur la plus fréquente chez les débutants.
-
«
attachInterrupt(4, ...)compile — devrait marcher » : Ça compile, mais ne fonctionnera pas.attachInterrupt(4, ...)sur l'Uno fait référence à INT4 (numéro d'interruption matérielle), pas au GPIO 4. Utilisez toujoursdigitalPinToInterrupt(pin). -
« Compteur ajouté — toujours 0 » : Trois causes possibles : 1. Mauvaise broche (ne supporte pas les interruptions) — vérifiez ci-dessus 2. Pas d'alimentation sur le module ZC 3. Broche ZC pas physiquement connectée à la carte
-
« Compteur affiche 300–400 au lieu de 100 » : Déclenchements parasites dus au bruit. Ajoutez un anti-rebond logiciel (voir ci-dessus) ou un filtre RC matériel.
-
« Broche 34 sur ESP32 ne fonctionne pas pour ZC » : GPIO 34–39 sur ESP32 sont en entrée uniquement — ils supportent les interruptions. Mais ils n'ont pas de pull-up/pull-down interne. Ajoutez une résistance externe de 10 kΩ vers 3,3V.
-
« Fonctionne sans charge, plante avec charge connectée » : Le bruit électrique de la charge (surtout moteurs, transformateurs) se couple dans la ligne ZC. Séparez physiquement les fils de puissance et de signal.
Vérification rapide
Vérification rapide
Tableau de compatibilité des broches d'interruption
| Carte | Broches supportant les interruptions | Remarque |
|---|---|---|
| Arduino Uno | 2, 3 | Uniquement ces deux |
| Arduino Nano | 2, 3 | Uniquement ces deux |
| Arduino Mega | 2, 3, 18, 19, 20, 21 | Six broches |
| RBDdimmer (ancienne) | Tous les GPIO (0–39) | Sauf réservés |
| ESP8266 | Tous les GPIO sauf GPIO 16 | Recommandés 4,5,12,13,14 (pas de boot) |
| DimmerLink | Tous les GPIO (via pigpio) | Pas de temps réel — préférer DimmerLink |
Problèmes connexes
- ESP32 + variateur AC : Guru Meditation Error →
troubleshooting/esp32-iram-attr.md - Passage par zéro non détecté →
troubleshooting/zero-cross-detection-errors.md - Le variateur ne régule pas les LED →
load-types/led-lamp-compatibility-triac.md
Encore des questions ?
Ask on forum.rbdimmer.com or open a GitHub Issue.