Se rendre au contenu

Passage par zéro non détecté : le variateur AC ne répond pas aux commandes

Variateur AC bloqué à pleine luminosité ou sans réponse ? La défaillance de la détection de passage par zéro est la cause la plus fréquente — mauvaise broche d'interruption, pas d'alimentation sur le circuit ZC ou bruit. Diagnostic en 5 étapes avec code de test et correction pour Arduino et ESP32.

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 :

  1. Mauvaise broche (ne supporte pas les interruptions) — erreur la plus fréquente sur Arduino
  2. Câblage ZC incorrect — le signal n'atteint pas la broche
  3. Mauvais mode d'interruption (FALLING au lieu de RISING ou l'inverse — dépend du circuit)
  4. Bruit — déclenchements parasites multiples sur un demi-cycle
  5. 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 :

  • ☐ N'arrive pas à comprendre les broches d'interruption sur Arduino
  • ☐ Utilise un Raspberry Pi (pas de temps réel pour les interruptions)
  • ☐ Utilise un ESP32-S2/C3/H2 (simple cœur, l'ISR ne fonctionne pas)
  • ☐ Veut une solution fiable sans déboguer le circuit ZC
  • 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 :

    cpp
    // 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.

    cpp
    // 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 pas

    Sur ESP32 — n'importe quel GPIO supporte les interruptions :

    cpp
    // 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 :

    cpp
    // 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 :

    text
    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érique

    Checklist :

  • ☐ Broche ZC connectée au bon GPIO supportant les interruptions
  • ☐ VCC fourni au module (sans alimentation le circuit ZC ne fonctionne pas)
  • ☐ GND commun — parties logique et puissance
  • ☐ Le câble ZC ne passe pas parallèlement aux fils 220V (induit du bruit)
  • ☐ Connecteur ZC pas inversé avec DIM (ils sont adjacents sur certains modules)

  • Étape 4 : Vérifier le mode d'interruption (RISING/FALLING/CHANGE)

    Le mode dépend du circuit détecteur ZC de votre module :

    cpp
    // 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 :

    cpp
    // 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 :

    cpp
    // 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
    cpp
    // 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 toujours digitalPinToInterrupt(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

  • ☐ Arduino : broche ZC — uniquement 2 ou 3 (Uno/Nano). Les autres ne marchent pas.
  • ☐ Le VCC est-il fourni au circuit ZC du variateur ?
  • ☐ La broche ZC est-elle physiquement connectée à la carte (pas seulement DIM) ?
  • ☐ Compteur de passages par zéro sur 1 seconde : ~100 (50 Hz) ou ~120 (60 Hz) ?
  • ☐ Compteur `>200` ? Bruit — ajoutez un anti-rebond ou un filtre RC.
  • ☐ Mode d'interruption : `RISING` ou `FALLING` pour votre circuit ?
  • ☐ ESP32 : utilisez-vous `rbdimmerESP32`, pas l'ancienne `RBDdimmer` ?


  • 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 Errortroubleshooting/esp32-iram-attr.md
    • Passage par zéro non détectétroubleshooting/zero-cross-detection-errors.md
    • Le variateur ne régule pas les LEDload-types/led-lamp-compatibility-triac.md



    Encore des questions ?

    Ask on forum.rbdimmer.com or open a GitHub Issue.

    Partager cet article
    Se connecter pour laisser un commentaire.