En bref :
analogWrite()et le PWM ne fonctionnent pas avec un variateur AC TRIAC. Un TRIAC n'est ni une résistance ni un transistor DC. Il régule la puissance par commande de phase : il s'ouvre à un moment précisément calculé de chaque demi-cycle, synchronisé avec le signal de passage par zéro. Sans passage par zéro et la bonne bibliothèque — la charge sera seulement en marche ou à l'arrêt, sans valeurs intermédiaires.
Description du problème
Vous avez connecté un variateur AC, trouvé la broche DIM — et essayé de le contrôler avec
analogWrite() comme une sortie PWM classique. Ou utilisé ledc sur ESP32.
Résultat : la charge est soit à 100 %, soit complètement éteinte. Aucune luminosité intermédiaire.
Parfois le comportement est encore plus inattendu :
- À faibles valeurs PWM, la charge ne s'allume pas du tout
- À valeurs élevées — elle passe directement à pleine puissance
- Une valeur de 50 % (128 sur 255) ne donne pas 50 % de luminosité
Ce n'est pas un bug dans le code ni un module défectueux. C'est une incompatibilité fondamentale entre la méthode de contrôle et le type de charge.
Situations typiques sur les forums :
- « J'ai connecté la broche DIM du variateur au PWM, analogWrite(128), mais la lampe est à fond »
- « PWM essayé sur un variateur TRIAC, mais aucun effet de variation »
- « ESP32 ledc sur la broche du variateur — la lumière s'allume et s'éteint, c'est tout »
- « Pourquoi analogWrite ne fonctionne pas avec le variateur AC ? »
- Broche ZC pas connectée du tout — seulement DIM sur une sortie PWM
Cause profonde
PWM — pour le courant continu (DC)
Le PWM (modulation de largeur d'impulsion) contrôle la puissance par commutation rapide : un transistor s'ouvre et se ferme des milliers de fois par seconde, et la charge reçoit une tension moyenne proportionnelle au rapport cyclique.
PWM 50 % rapport cyclique (charge DC — ruban LED, moteur, chauffage DC) :
Tension :
┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐
─┘ └──┘ └──┘ └──┘ └──┘ └─
│←ON→│←OFF→│ ← fréquence 1–20 kHz
Puissance moyenne = 50 % ✅Cela fonctionne parce qu'une charge DC réagit à la tension moyenne. Un chauffage chauffe à puissance moyenne ; une LED clignote assez vite pour que l'œil ne le remarque pas.
TRIAC — pour le courant alternatif (AC) : fonctionne différemment
Un TRIAC est un thyristor bidirectionnel pour l'AC. Il se comporte de manière fondamentalement différente :
- Se verrouille — une fois que le courant commence à circuler (et dépasse le courant de maintien), le TRIAC reste ouvert jusqu'à la fin du demi-cycle, même si le signal de gâchette est retiré.
- S'éteint automatiquement au passage par zéro de la sinusoïde — quand le courant tombe sous le courant de maintien.
- Ne répond pas au PWM rapide : une seule impulsion de gâchette de n'importe quelle durée ouvre le TRIAC jusqu'à la fin du demi-cycle. 10 µs ou 5 ms — le résultat est le même.
Sinusoïde AC (50 Hz) :
╭──────╮ ╭──────╮
│ │ │ │
────╯ ╰────────╯ ╰────
↑ ↑ ↑ ↑
ZC ZC(-) ZC ZC(-)
(100 impulsions par seconde)TRIAC s'ouvre au ZC — la charge reçoit le demi-cycle COMPLET (100 %) :
╭──────╮ ╭──────╮
│//////│ │//////│
────╯ ╰────────╯ ╰────
↑ s'ouvre ↑ s'ouvre au ZCTRIAC s'ouvre avec 5 ms de délai — la charge reçoit la MOITIÉ du demi-cycle (~50 %) :
──────╮ ──────╮
│ │
──────╯──────── ─────╯──────
↑ ↑ ↑ ↑
ZC s'ouvre ZC s'ouvre
(après 5 ms) (après 5 ms)Pourquoi le PWM « ne voit pas » le TRIAC
Lorsque vous appliquez 50 % de PWM (par ex. 500 Hz) sur la broche DIM du TRIAC :
- Le PWM commute 500 fois par seconde
- La première impulsion HIGH ouvre le TRIAC
- Les impulsions LOW suivantes n'ont aucun effet — le TRIAC est déjà verrouillé
- Il reste ouvert jusqu'à la fin du demi-cycle (10 ms à 50 Hz)
- La charge se retrouve à pleine puissance
Pas de passage par zéro — pas de timing — pas de variation.
Tableau : PWM vs découpe de phase
| Paramètre | PWM (DC) | Découpe de phase (AC TRIAC) |
|---|---|---|
| Type de signal | Commutation continue | Impulsion de gâchette unique |
| ZC nécessaire ? | Non | Oui — obligatoire |
| Bibliothèque nécessaire ? | Non (analogWrite) |
Oui |
| Type de charge | DC (ruban LED, moteur, chauffage) | AC (lampe, halogène, chauffage) |
| Méthode de contrôle | Rapport cyclique | Délai de gâchette relatif au ZC |
| Fréquence de commutation | 1–20 kHz | 100–120 Hz (une fois par demi-cycle) |
| Plage de fonctionnement | 0–100 % | ~10–95 % (limitation du TRIAC) |
Solutions
🟢 Pour les débutants : DimmerLink — branchez et utilisez
Vous ne voulez pas vous occuper du passage par zéro, de l'angle de phase et des ISR ? DimmerLink gère toute la logique en interne — il suffit de définir un niveau.
❌ non supporté is a controller with its own zero-cross detector and TRIAC phase control. Your microcontroller only sends a brightness level (0–100%) via I2C or UART. No PWM, no zero-cross on the MCU side.
Quand choisir :
Câblage :
DimmerLink → Arduino/ESP32
VCC → 3.3V (ESP32) / 5V (Arduino)
GND → GND
SDA → SDA (GPIO 21 sur ESP32, A4 sur Uno)
SCL → SCL (GPIO 22 sur ESP32, A5 sur Uno)Code :
// DimmerLink — régler la luminosité comme une simple valeur 0–100
// Pas de PWM, passage par zéro ou ISR — tout est géré dans DimmerLink
// Doc : 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();
setLevel(0); // éteint
delay(2000);
setLevel(50); // luminosité 50 %
delay(2000);
setLevel(100); // pleine luminosité
}
void loop() {}🔵 Pour les utilisateurs avancés : commande de phase correcte
Vous voulez travailler directement avec le variateur sans DimmerLink ? Vous devez connecter le passage par zéro et utiliser une bibliothèque.
Ce qu'il faut connecter :
| Broche du variateur | Connecter à |
|---|---|
| VCC | 5V (Arduino) / 3.3V (ESP32) |
| GND | GND |
| ZC | Broche compatible interruption (2 ou 3 sur Arduino Uno ; tout GPIO sur ESP32) |
| DIM | Toute sortie numérique |
Différence clé avec le PWM : la broche DIM reçoit une seule impulsion courte (~100 µs) au bon moment, calculé par rapport au ZC. Pas de signal PWM continu.
Option A : ESP32 avec rbdimmerESP32 ✅ Recommandé
// Plateforme : ESP32 double cœur
// Bibliothèque : rbdimmerESP32 — découpe de phase, pas PWM
// https://github.com/robotdyn-dimmer/rbdimmerESP32
#include "rbdimmerESP32.h"
#define ZC_PIN 18 // passage par zéro — OBLIGATOIRE
#define DIM_PIN 19 // commande TRIAC
rbdimmer dimmer;
void setup() {
dimmer.begin(ZC_PIN, DIM_PIN, 50); // secteur 50 Hz
dimmer.setPower(50); // 50 % — fonctionne par découpe de phase
}
void loop() {
// Balayage progressif de luminosité
for (int p = 10; p <= 95; p++) {
dimmer.setPower(p);
delay(30);
}
for (int p = 95; p >= 10; p--) {
dimmer.setPower(p);
delay(30);
}
}Ce qui se passe dans la bibliothèque :
1. L'interruption ZC se déclenche (t=0)
↓
2. Calcul du délai de gâchette (front montant, 50 Hz) :
delay_us = (100 - power%) × 78
Exemple : 50 % → delay = 50 × 78 = 3 900 µs
↓
3. Timer matériel : se déclenche après 3 900 µs
↓
4. Envoi d'une impulsion courte sur DIM (~100 µs)
↓
5. Le TRIAC s'ouvre et reste ouvert jusqu'au prochain ZC
⚠️ Plage de fonctionnement — pas 0–100 %, mais ~10–95 % :
100 % → delay = 0 µs (s'ouvre au ZC, puissance maximale) ✅
0 % → delay = 7 800 µs (78 % du demi-cycle) → la charge reçoit 22 %,
pas 0 %. Pour éteindre — ne pas ouvrir le TRIAC du tout.
< 10 % — le TRIAC s'ouvre si tard que le courant ne peut pas dépasser
le courant de maintien → scintillement instable.
Les bibliothèques limitent donc la plage : setPower(0) = éteint,
setPower(1–9) ≈ 10 %, setPower(95–100) ≈ 95 %.Option B : Arduino Uno/Mega avec RBDdimmer
// Plateforme : Arduino Uno / Mega / Nano (AVR)
// Bibliothèque : RBDdimmer — https://github.com/robotdyn/dimmer
// ZC EST OBLIGATOIRE ! Arduino Uno : uniquement broches 2 ou 3
#include <RBDdimmer.h>
#define ZC_PIN 2 // passage par zéro — broche 2 (compatible interruption sur Uno)
#define DIM_PIN 11 // commande TRIAC
dimmerLamp dimmer(DIM_PIN, ZC_PIN);
void setup() {
dimmer.begin(NORMAL_MODE, ON);
dimmer.setPower(50); // 50 %
}
void loop() {}⚠️ Pièges courants
-
« DIM connecté au PWM, ZC pas connecté du tout » : Sans ZC, la découpe de phase est physiquement impossible. La broche ZC est une partie obligatoire du circuit, pas une option.
-
«
analogWrite(DIM_PIN, 128)— la lampe ne scintille pas, reste allumée » : C'est le comportement attendu.analogWriteouvre le TRIAC dès la toute première impulsion HIGH et il reste verrouillé. Utilisez une bibliothèque avec ZC. -
« Fréquence PWM réglée à 100 Hz — rien n'a changé » : Faire correspondre la fréquence PWM au taux de ZC n'aide pas. Le TRIAC se verrouille quand même au premier pulse.
-
« Le PWM fonctionnait avec une charge DC — pourquoi pas avec AC ? » : Les charges DC (rubans LED 12V, moteurs DC) utilisent un contrôle par transistor et réagissent à la tension moyenne. Le TRIAC AC est une physique différente. Voir le tableau ci-dessus.
-
« Puis-je laisser DIM en PWM juste pour allumer/éteindre ? » : Techniquement oui — vous pouvez allumer/éteindre la charge avec un simple HIGH/LOW. Mais ce n'est pas de la variation. Et sans ZC, le TRIAC peut se déclencher à un point aléatoire de la sinusoïde, causant des interférences et du stress sur le TRIAC.
Vérification rapide
Problèmes connexes
- Passage par zéro non détecté →
troubleshooting/zero-cross-detection-errors.md - ESP32 + TRIAC : Guru Meditation Error →
troubleshooting/esp32-iram-attr.md - Scintillement LED avec variateur →
load-types/led-flicker-triac-dimmer.md
Encore des questions ?
Ask on forum.rbdimmer.com or open a GitHub Issue.