Zum Inhalt springen

AC TRIAC-Dimmer ist kein PWM: So funktioniert Phasenanschnitt-Dimmung

analogWrite oder ledc am DIM-Pin Ihres AC-Dimmers ergibt nur volle Helligkeit — TRIAC reagiert nicht auf PWM. Phasenanschnitt-Dimmung erfordert ein Nulldurchgangssignal und eine geeignete Bibliothek. Mit ASCII-Diagrammen und funktionierendem Code erklärt.

Kurzfassung: analogWrite() und PWM funktionieren nicht mit einem AC TRIAC-Dimmer. Ein TRIAC ist kein Widerstand und kein DC-Transistor. Er regelt die Leistung mittels Phasensteuerung: Er öffnet in einem präzise berechneten Moment jeder Halbwelle, synchronisiert mit dem Nulldurchgangssignal. Ohne Nulldurchgang und die richtige Bibliothek — ist die Last nur voll ein oder voll aus, ohne Zwischenwerte.



Problembeschreibung

Sie haben einen AC-Dimmer angeschlossen, den DIM-Pin gefunden — und versucht, ihn mit analogWrite() wie einen normalen PWM-Ausgang zu steuern. Oder ledc auf ESP32 verwendet. Ergebnis: Die Last ist entweder auf 100% oder komplett aus. Keine Zwischenhelligkeit.

Manchmal ist das Verhalten noch unerwarteter:

  • Bei niedrigen PWM-Werten schaltet sich die Last gar nicht ein
  • Bei hohen Werten — springt sie sofort auf volle Leistung
  • Ein Wert von 50% (128 von 255) ergibt nicht 50% Helligkeit

Dies ist kein Code-Fehler und kein defektes Modul. Es ist ein grundlegendes Missverhältnis zwischen der Steuermethode und dem Lasttyp.

Typische Forum-Situationen:

  • „Dimmer DIM-Pin an PWM angeschlossen, analogWrite(128), aber Lampe auf voller Leistung"
  • „PWM am TRIAC-Dimmer probiert, aber kein Dimmeffekt"
  • „ESP32 ledc am Dimmer-Pin — Licht schaltet nur ein und aus"
  • „Warum funktioniert analogWrite nicht mit dem AC-Dimmer?"
  • ZC-Pin überhaupt nicht angeschlossen — nur DIM an einem PWM-Ausgang



Grundursache


PWM — für Gleichstrom (DC)

PWM (Pulsweitenmodulation) steuert die Leistung durch schnelles Schalten: Ein Transistor öffnet und schließt tausende Male pro Sekunde, und die Last erhält eine mittlere Spannung proportional zum Tastverhältnis.

text
PWM 50% Tastverhältnis (DC-Last — LED-Streifen, Motor, DC-Heizung):
Spannung:
 ┌──┐  ┌──┐  ┌──┐  ┌──┐  ┌──┐
─┘  └──┘  └──┘  └──┘  └──┘  └─
│←EIN→│←AUS→│   ← Frequenz 1–20 kHz
Mittlere Leistung = 50% ✅

Das funktioniert, weil eine DC-Last auf die mittlere Spannung reagiert. Ein Heizgerät wärmt bei mittlerer Leistung; eine LED flackert schnell genug, dass das Auge es nicht bemerkt.


TRIAC — für Wechselstrom (AC): funktioniert anders

Ein TRIAC ist ein siliziumgesteuerter Gleichrichter für AC. Er verhält sich grundlegend anders:

  1. Verriegelt sich — sobald Strom fließt (und den Haltestrom überschreitet), bleibt der TRIAC bis zum Ende der Halbwelle offen, auch wenn das Gate-Signal entfernt wird.
  2. Schaltet sich selbst ab beim Sinuswellen-Nulldurchgang — wenn der Strom unter den Haltestrom fällt.
  3. Reagiert nicht auf schnelles PWM: Ein einzelner Gate-Impuls beliebiger Länge öffnet den TRIAC bis zum Ende der Halbwelle. 10 µs oder 5 ms — das Ergebnis ist dasselbe.
text
AC-Sinuswelle (50 Hz):
    ╭──────╮         ╭──────╮
    │      │         │      │
────╯      ╰────────╯      ╰────
    ↑      ↑         ↑      ↑
   ZC    ZC(-)      ZC    ZC(-)
   (100 Impulse pro Sekunde)
text
TRIAC öffnet bei ZC — Last bekommt die VOLLE Halbwelle (100%):
    ╭──────╮         ╭──────╮
    │//////│         │//////│
────╯      ╰────────╯      ╰────
↑ öffnet               ↑ öffnet bei ZC
text
TRIAC öffnet mit 5 ms Verzögerung — Last bekommt HALBE Halbwelle (~50%):
    ──────╮         ──────╮
          │               │
    ──────╯────────  ─────╯──────
    ↑     ↑          ↑    ↑
   ZC   öffnet      ZC  öffnet
        (nach 5 ms)     (nach 5 ms)


Warum PWM den TRIAC „nicht sieht"

Wenn Sie 50% PWM (z.B. 500 Hz) am DIM-Pin des TRIAC anlegen:

  • PWM schaltet 500 Mal pro Sekunde
  • Der erste HIGH-Impuls öffnet den TRIAC
  • Nachfolgende LOW-Impulse sind bedeutungslos — der TRIAC hat sich bereits verriegelt
  • Er bleibt bis zum Ende der Halbwelle offen (10 ms bei 50 Hz)
  • Die Last läuft auf voller Leistung

Kein Nulldurchgang — kein Timing — kein Dimmen.



Tabelle: PWM vs Phasenanschnitt

Parameter PWM (DC) Phasenanschnitt (AC TRIAC)
Signaltyp Kontinuierliches Schalten Einzelner Gate-Impuls
ZC benötigt? Nein Ja — zwingend erforderlich
Bibliothek benötigt? Nein (analogWrite) Ja
Lasttyp DC (LED-Streifen, Motor, Heizung) AC (Lampe, Halogen, Heizung)
Steuerungsmethode Puls-Tastverhältnis Gate-Verzögerung relativ zu ZC
Schaltfrequenz 1–20 kHz 100–120 Hz (einmal pro Halbwelle)
Arbeitsbereich 0–100% ~10–95% (TRIAC-Begrenzung)



Lösungen



🟢 Für Einsteiger: DimmerLink — anschließen und loslegen

Möchten Sie sich nicht mit Nulldurchgang, Phasenwinkel und ISR beschäftigen? DimmerLink übernimmt die gesamte Logik intern — setzen Sie einfach einen Wert.

Jeder ESP32 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.

Wann zu wählen:

  • ☐ Einfach nur Helligkeit einstellen ohne Phasenanschnitt zu lernen
  • ☐ Raspberry Pi (kein Echtzeit-ISR)
  • ☐ ESP32-S2/C3/H2 (Single-Core, ISR nicht unterstützt)
  • ☐ Gleichzeitige WiFi/MQTT-Steuerung ohne Abstürze benötigt
  • Verdrahtung:

    text
    DimmerLink → Arduino/ESP32
    VCC → 3.3V (ESP32) / 5V (Arduino)
    GND → GND
    SDA → SDA (GPIO 21 auf ESP32, A4 auf Uno)
    SCL → SCL (GPIO 22 auf ESP32, A5 auf Uno)

    Code:

    cpp
    // DimmerLink — Helligkeit als einfacher 0–100-Wert setzen
    // Kein PWM, Nulldurchgang oder ISR — alles intern von DimmerLink verarbeitet
    // Doku: 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);    // aus
        delay(2000);
        setLevel(50);   // 50% Helligkeit
        delay(2000);
        setLevel(100);  // volle Helligkeit
    }
    void loop() {}


    🔵 Für fortgeschrittene Anwender: korrekte Phasensteuerung

    Möchten Sie direkt mit dem Dimmer arbeiten, ohne DimmerLink? Sie müssen den Nulldurchgang anschließen und eine Bibliothek verwenden.

    Was Sie anschließen müssen:

    Dimmer-Pin Verbinden mit
    VCC 5V (Arduino) / 3.3V (ESP32)
    GND GND
    ZC Interrupt-fähiger Pin (2 oder 3 auf Arduino Uno; jeder GPIO auf ESP32)
    DIM Beliebiger digitaler Ausgang

    Hauptunterschied zu PWM: Der DIM-Pin erhält einen einzelnen kurzen Impuls (~100 µs) zum richtigen Zeitpunkt, berechnet relativ zu ZC. Kein kontinuierliches PWM-Signal.


    Option A: ESP32 mit rbdimmerESP32 ✅ Empfohlen

    cpp
    // Plattform: Dual-Core ESP32
    // Bibliothek: rbdimmerESP32 — Phasenanschnitt, kein PWM
    // https://github.com/robotdyn-dimmer/rbdimmerESP32
    #include "rbdimmerESP32.h"
    #define ZC_PIN  18  // Nulldurchgang — ERFORDERLICH
    #define DIM_PIN 19  // TRIAC-Steuerung
    rbdimmer dimmer;
    void setup() {
        dimmer.begin(ZC_PIN, DIM_PIN, 50);  // 50 Hz Netz
        dimmer.setPower(50);                 // 50% — funktioniert über Phasenanschnitt
    }
    void loop() {
        // Sanfter Helligkeitsverlauf
        for (int p = 10; p <= 95; p++) {
            dimmer.setPower(p);
            delay(30);
        }
        for (int p = 95; p >= 10; p--) {
            dimmer.setPower(p);
            delay(30);
        }
    }

    Was innerhalb der Bibliothek passiert:

    text
    1. ZC-Interrupt wird ausgelöst (t=0)
       ↓
    2. Gate-Verzögerung berechnen (Vorderflanke, 50 Hz):
       delay_us = (100 - power%) × 78
       Beispiel: 50% → delay = 50 × 78 = 3 900 µs
       ↓
    3. Hardware-Timer: löst nach 3 900 µs aus
       ↓
    4. Kurzen Impuls an DIM senden (~100 µs)
       ↓
    5. TRIAC öffnet und bleibt bis zum nächsten ZC offen
    ⚠️ Arbeitsbereich — nicht 0–100%, sondern ~10–95%:
       100% → delay = 0 µs (öffnet bei ZC, maximale Leistung) ✅
         0% → delay = 7 800 µs (78% der Halbwelle) → Last bekommt 22%,
               nicht 0%. Zum Abschalten — TRIAC gar nicht öffnen.
       < 10% — TRIAC öffnet so spät, dass Strom den Haltestrom nicht
               überschreiten kann → instabiles Flackern.
       Bibliotheken begrenzen daher den Bereich: setPower(0) = aus,
       setPower(1–9) ≈ 10%, setPower(95–100) ≈ 95%.


    Option B: Arduino Uno/Mega mit RBDdimmer

    cpp
    // Plattform: Arduino Uno / Mega / Nano (AVR)
    // Bibliothek: RBDdimmer — https://github.com/robotdyn/dimmer
    // ZC IST ERFORDERLICH! Arduino Uno: nur Pins 2 oder 3
    #include <RBDdimmer.h>
    #define ZC_PIN   2   // Nulldurchgang — Pin 2 (interrupt-fähig auf Uno)
    #define DIM_PIN  11  // TRIAC-Steuerung
    dimmerLamp dimmer(DIM_PIN, ZC_PIN);
    void setup() {
        dimmer.begin(NORMAL_MODE, ON);
        dimmer.setPower(50);  // 50%
    }
    void loop() {}


    ⚠️ Häufige Fallstricke

    • „DIM an PWM angeschlossen, ZC überhaupt nicht verbunden": Ohne ZC ist Phasenanschnitt physikalisch unmöglich. Der ZC-Pin ist ein zwingender Teil der Schaltung, keine Option.

    • analogWrite(DIM_PIN, 128) — Lampe flackert nicht, leuchtet einfach": Das ist das erwartete Verhalten. analogWrite öffnet den TRIAC mit dem allerersten HIGH-Impuls und er bleibt verriegelt. Verwenden Sie eine Bibliothek mit ZC.

    • „PWM-Frequenz auf 100 Hz gesetzt — nichts geändert": Das Anpassen der PWM-Frequenz an die ZC-Rate hilft nicht. Der TRIAC verriegelt sich trotzdem beim ersten Impuls.

    • „PWM hat mit DC-Last funktioniert — warum nicht mit AC?": DC-Lasten (12V LED-Streifen, DC-Motoren) verwenden Transistorsteuerung und reagieren auf Durchschnittsspannung. AC TRIAC ist andere Physik. Siehe Tabelle oben.

    • „Kann ich DIM auf PWM lassen, nur für Ein/Aus?": Technisch ja — Sie können die Last mit einem einzelnen HIGH/LOW ein-/ausschalten. Aber das ist kein Dimmen. Und ohne ZC kann der TRIAC an einem zufälligen Punkt der Sinuswelle zünden, was Störungen und Belastung des TRIAC verursacht.




    Schnell-Check

  • ☐ ZC-Pin an einem interrupt-fähigen GPIO angeschlossen? Ohne das funktioniert nichts.
  • ☐ Verwenden Sie eine Nulldurchgangs-Bibliothek (rbdimmerESP32 / RBDdimmer / DimmerLink)?
  • ☐ `analogWrite()` / `ledc` vom DIM-Pin entfernt?
  • ☐ Arduino Uno: ZC auf Pin 2 oder 3 (nicht 4, 5 oder andere)?
  • ☐ Single-Core ESP32 (S2/C3/H2)? → DimmerLink verwenden.


  • Verwandte Probleme

    • Nulldurchgang nicht erkannttroubleshooting/zero-cross-detection-errors.md
    • ESP32 + TRIAC: Guru Meditation Errortroubleshooting/esp32-iram-attr.md
    • Trailing vs Leading Edgeload-types/trailing-vs-leading-edge.md



    Noch Fragen?

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

    Diesen Beitrag teilen
    Anmelden , um einen Kommentar zu hinterlassen