Kurzfassung: Ein AC-Dimmer kann die Last nicht regeln, wenn der Mikrocontroller das Nulldurchgangssignal (den Nulldurchgang der Sinuswelle) nicht empfängt. Ohne dieses Signal ist es unmöglich, den TRIAC-Zündzeitpunkt zu berechnen. Ursachen: falscher Pin (nicht interrupt-fähig), fehlerhafte ZC-Verdrahtung, Störungen auf der Signalleitung oder ein Softwarefehler (falscher Interrupt-Modus). Arbeiten Sie die Checkliste unten Schritt für Schritt ab.
Problembeschreibung
Sie haben einen AC-Dimmer angeschlossen, Beispielcode hochgeladen — aber die Last reagiert nicht oder ist immer auf voller Helligkeit. Die Verdrahtung sieht korrekt aus, keine Kompilierungsfehler.
Die häufigste Ursache ist, dass der Nulldurchgang vom Mikrocontroller nicht erkannt wird. Phasenanschnitt-Dimmung funktioniert nach diesem Prinzip: Nulldurchgang der Sinuswelle erkennen → berechnete Verzögerung abwarten → TRIAC zünden. Ohne Nulldurchgang gibt es kein Timing, und der Dimmer schaltet die Last entweder gar nicht ein oder hält sie bei 100% ohne Regelung.
Typische Symptome:
- Last ist immer auf voller Helligkeit (TRIAC immer offen)
- Last schaltet sich gar nicht ein
setPower(50)hat keine Wirkung — Last ist entweder voll an oder aus- Nulldurchgangszähler erhöht sich nicht im seriellen Monitor (bei Debug-Ausgabe)
- Code kompiliert fehlerfrei, aber der Dimmer „funktioniert nicht"
Typische Forenbeiträge:
- „Dimmer dimmt nicht — Lampe immer volle Helligkeit"
- „setPower hat keine Wirkung"
- „Nulldurchgang-Interrupt löst nicht aus"
- „Dimmer funktioniert manchmal, zufällig"
Grundursache
Das Nulldurchgangssignal wird von einer Nulldurchgangsdetektorschaltung erzeugt, die in den AC-Dimmer eingebaut oder extern angeschlossen ist. Typischerweise ist es ein Optokoppler + Widerstandsteiler, der bei jedem Nulldurchgang der Sinuswelle einen kurzen Impuls erzeugt.
Impulsfrequenz: 100 Hz (50-Hz-Netz) / 120 Hz (60-Hz-Netz). Ein Impuls pro Halbzyklus.
Um diese Impulse zu empfangen, verwendet der Mikrocontroller einen
externen Interrupt (attachInterrupt()). Wenn der Interrupt nicht
korrekt konfiguriert ist oder das Signal nicht den richtigen Pin erreicht —
wird der ISR-Handler nie aufgerufen, das Timing kann nicht berechnet werden,
und der Dimmer funktioniert nicht.
Hauptursachen für den Fehler:
- Falscher Pin (nicht interrupt-fähig) — häufigster Fehler bei Arduino
- Fehlerhafte ZC-Verdrahtung — Signal erreicht den Pin nicht
- Falscher Interrupt-Modus (
FALLINGstattRISINGoder umgekehrt — abhängig von der Schaltung) - Störungen — mehrfache Fehlauslösungen pro Halbzyklus
- Stromversorgungsproblem der ZC-Schaltung — kein VCC am Nulldurchgangsdetektor
Lösungen
🟢 Für Einsteiger: DimmerLink — Nulldurchgang integriert
Sie möchten sich nicht mit Interrupt-Pins, RISING/FALLING und elektrischen Störungen beschäftigen? DimmerLink hat einen eigenen Nulldurchgangsdetektor und steuert den TRIAC autonom.
Jeder ESP32 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.
Wann diese Lösung wählen:
DimmerLink → Arduino/ESP32 Verdrahtung:
- VCC → 3.3V (ESP32) oder 5V (Arduino)
- GND → GND
- SDA → SDA (GPIO 21 auf ESP32, A4 auf Arduino Uno)
- SCL → SCL (GPIO 22 auf ESP32, A5 auf Arduino Uno)
Code:
// DimmerLink — Nulldurchgangsdetektor und TRIAC-Steuerung im Modul
// Mikrocontroller setzt nur die Helligkeit
// Dokumentation: 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(); // Standard-SDA/SCL für Ihr Board
setLevel(50); // 50% Helligkeit
}
void loop() {
// Kein ISR, keine Interrupts, kein Nulldurchgang am MCU
}Ergebnis: Dimmer funktioniert ohne Abhängigkeit von Interrupt-Pins oder Nulldurchgangssignal am Mikrocontroller.
🔵 Für Fortgeschrittene: ZC diagnostizieren und beheben
Sie möchten die direkte ISR-Verbindung beibehalten? Folgen Sie den Diagnoseschritten.
Diagnose: Schritte 1–5
Schritt 1: Prüfen Sie, ob der Pin interrupt-fähig ist
Dies ist Ursache Nr. 1 bei Arduino.
// Arduino Uno / Nano / Mini:
// ✅ Interrupt-fähig: NUR Pins 2 und 3
// ❌ Alle anderen Pins (4, 5, 6...) — Interrupts nicht unterstützt
// Richtig:
attachInterrupt(digitalPinToInterrupt(2), zeroCrossISR, RISING); // Pin 2 ✅
attachInterrupt(digitalPinToInterrupt(3), zeroCrossISR, RISING); // Pin 3 ✅
// Falsch:
attachInterrupt(4, zeroCrossISR, RISING); // ❌ Pin 4 — nicht interrupt-fähig
// Auf dem Uno verweist attachInterrupt(4) auf INT4, der nicht existiertAuf ESP32 — jeder GPIO unterstützt Interrupts:
// ESP32: jeder GPIO — alle funktionieren
attachInterrupt(digitalPinToInterrupt(18), zeroCrossISR, RISING); // ✅
attachInterrupt(digitalPinToInterrupt(34), zeroCrossISR, RISING); // ✅Auf ESP8266 — alle GPIOs außer GPIO 16 unterstützen Interrupts; empfohlen werden 4, 5, 12, 13, 14 (keine Boot-Modus-Abhängigkeiten).
Schritt 2: Zähler zur Überprüfung hinzufügen
Der einfachste Test — Impulse über 1 Sekunde zählen:
// Nulldurchgangsdiagnose: erwartet ~100 Impulse/Sek. (50-Hz-Netz)
// oder ~120 Impulse/Sek. (60-Hz-Netz)
#define ZC_PIN 2 // ← stellen Sie sicher, dass dies ein interrupt-fähiger Pin ist
volatile uint32_t zcCount = 0;
#ifdef ESP32
void IRAM_ATTR zeroCrossISR() { // IRAM_ATTR auf ESP32 erforderlich
#else
void zeroCrossISR() { // Arduino/ESP8266: IRAM_ATTR nicht nötig
#endif
zcCount++;
}
void setup() {
Serial.begin(115200);
pinMode(ZC_PIN, INPUT);
attachInterrupt(digitalPinToInterrupt(ZC_PIN), zeroCrossISR, RISING);
}
void loop() {
delay(1000);
Serial.print("ZC-Impulse pro Sekunde: ");
Serial.println(zcCount);
zcCount = 0;
// Erwartete Ergebnisse:
// ~100 — 50-Hz-Netz, alles in Ordnung
// ~120 — 60-Hz-Netz, alles in Ordnung
// 0 — ZC nicht erkannt (Verdrahtungs- oder Pin-Problem)
// >200 — Störungen, Fehlauslösungen (RC-Filter-Problem)
}Schritt 3: ZC-Verdrahtung prüfen
Typische RBDimmer → Arduino/ESP32 Verdrahtung:
RBDimmer → Arduino/ESP32
------- -------------
VCC → 5V (Arduino) / 3.3V (ESP32)
GND → GND
ZC → Interrupt-fähiger Pin (2 oder 3 bei Arduino Uno)
DIM → Beliebiger digitaler AusgangCheckliste:
Schritt 4: Interrupt-Modus prüfen (RISING/FALLING/CHANGE)
Der Modus hängt von der ZC-Detektorschaltung Ihres Moduls ab:
// Die meisten RBDimmer-Module: RISING (Impuls bei steigender Flanke)
attachInterrupt(digitalPinToInterrupt(ZC_PIN), zeroCrossISR, RISING);
// Einige Schaltungen mit invertierendem Optokoppler: FALLING
attachInterrupt(digitalPinToInterrupt(ZC_PIN), zeroCrossISR, FALLING);
// Wenn unsicher — versuchen Sie CHANGE (fängt beide Flanken):
// Hinweis: mit CHANGE zeigt der Zähler ~200 Hz statt 100 Hz
attachInterrupt(digitalPinToInterrupt(ZC_PIN), zeroCrossISR, CHANGE);Verwenden Sie ein Oszilloskop oder einen Logikanalysator, um die ZC-Signalform zu prüfen — bestimmen Sie, ob Sie die steigende oder fallende Flanke erfassen müssen.
Schritt 5: Störungen filtern
Wenn der Zähler >200 zeigt (bei 50-Hz-Netz) — Fehlauslösungen durch Störungen.
Dies ist besonders häufig bei langen Kabeln oder Nähe zur Last:
// Software-Entprellung für ZC: Impulse zu nahe am vorherigen ignorieren
// Halbzyklusperiode bei 50 Hz = 10 000 µs → alles unter 8 000 µs filtern
volatile uint32_t lastZC = 0;
void IRAM_ATTR zeroCrossISR() {
uint32_t now = micros();
if (now - lastZC > 8000) { // 8 ms Mindestintervall zwischen ZC-Impulsen
lastZC = now;
// Ihre TRIAC-Timing-Logik hier
}
}Hardware-Filter: Ein RC-Filter auf der ZC-Leitung (1 kΩ Widerstand + 100 nF Kondensator zwischen ZC und GND) entfernt Hochfrequenzstörungen.
Lösung: Wählen Sie Ihre Option
Option A: rbdimmerESP32 auf ESP32 ✅
Wann: Dual-Core-ESP32 mit direkter Dimmerverbindung. Die Bibliothek übernimmt ZC und Timing automatisch:
// Plattform: Dual-Core-ESP32
// Bibliothek: rbdimmerESP32
#include "rbdimmerESP32.h"
#define ZC_PIN 18 // beliebiger ESP32-GPIO
#define DIM_PIN 19 // beliebiger ESP32-GPIO
rbdimmer dimmer;
void setup() {
Serial.begin(115200);
dimmer.begin(ZC_PIN, DIM_PIN, 50); // 50-Hz-Netz
dimmer.setPower(50);
Serial.println("Dimmer initialisiert");
}
void loop() {}Häufige Fehler:
- ZC_PIN und DIM_PIN in
dimmer.begin()vertauscht — prüfen Sie, welcher Pin zur Last und welcher zum Nulldurchgang geht. - Falsche Netzfrequenz (dritter Parameter) — 50 oder 60 Hz.
Option B: Arduino Uno/Mega mit RBDdimmer
// Plattform: Arduino Uno / Mega / Nano (AVR)
// Bibliothek: RBDdimmer — https://github.com/robotdyn/dimmer
// WARNUNG: Für ESP32 verwenden Sie rbdimmerESP32, nicht diese Bibliothek!
#include <RBDdimmer.h>
// ⚠️ Arduino Uno: ZC NUR auf Pins 2 oder 3
#define ZC_PIN 2 // interrupt-fähig ✅
#define DIM_PIN 11 // beliebiger digitaler Ausgang
dimmerLamp dimmer(DIM_PIN, ZC_PIN);
void setup() {
Serial.begin(9600);
dimmer.begin(NORMAL_MODE, ON);
dimmer.setPower(50); // 50%
Serial.println("Dimmer bereit");
}
void loop() {}⚠️ Häufige Fallstricke
-
„Verwende Pin 4 auf Arduino Uno — funktioniert nicht": Pins 4, 5, 6, ... auf dem Uno unterstützen keine externen Interrupts. Nur Pins 2 und 3. Dies ist der häufigste Anfängerfehler.
-
„
attachInterrupt(4, ...)kompiliert — sollte funktionieren": Es kompiliert, funktioniert aber nicht.attachInterrupt(4, ...)auf dem Uno verweist auf INT4 (Hardware-Interrupt-Nummer), nicht auf GPIO 4. Verwenden Sie immerdigitalPinToInterrupt(pin). -
„Zähler hinzugefügt — immer 0": Drei mögliche Ursachen: 1. Falscher Pin (nicht interrupt-fähig) — siehe oben 2. Keine Stromversorgung am ZC-Modul 3. ZC-Pin nicht physisch mit dem Board verbunden
-
„Zähler zeigt 300–400 statt 100": Fehlauslösungen durch Störungen. Software-Entprellung hinzufügen (siehe oben) oder Hardware-RC-Filter.
-
„Pin 34 auf ESP32 funktioniert nicht für ZC": GPIO 34–39 auf ESP32 sind nur Eingang — sie unterstützen Interrupts. Aber sie haben keinen internen Pull-up/Pull-down. Fügen Sie einen externen 10 kΩ Widerstand an 3,3V hinzu.
-
„Funktioniert ohne Last, mit Last bricht es ab": Elektrische Störungen von der Last (besonders Motoren, Transformatoren) koppeln in die ZC-Leitung ein. Trennen Sie Leistungs- und Signalleitungen physisch.
Schnell-Check
Vor dem Posten im Forum überprüfen Sie:
Interrupt-Pin-Kompatibilitätstabelle
| Platine | Interrupt-fähige Pins | Hinweis |
|---|---|---|
| Arduino Uno | 2, 3 | Nur diese zwei |
| Arduino Nano | 2, 3 | Nur diese zwei |
| Arduino Mega | 2, 3, 18, 19, 20, 21 | Sechs Pins |
| ❌ nein | Alle GPIO (0–39) | Außer reservierten |
| ESP8266 | Alle GPIO außer GPIO 16 | Empfohlen 4,5,12,13,14 (kein Boot) |
| — (kein ISR) | Alle GPIO (über pigpio) | Keine Echtzeit — DimmerLink bevorzugen |
Verwandte Probleme
- ESP32 + AC-Dimmer: Guru Meditation Error →
troubleshooting/esp32-iram-attr.md - Trailing vs Leading Edge →
load-types/trailing-vs-leading-edge.md - Dimmer regelt LED nicht →
load-types/led-lamp-compatibility-triac.md
Noch Fragen?
Ask on forum.rbdimmer.com or open a GitHub Issue.