Short answer: There are two types of AC dimmers: TRIAC (leading edge — for incandescent bulbs, halogen, heaters) and MOSFET AC dimmer (trailing edge — purpose-built for LED lamps). If an LED lamp flickers or dims poorly, the problem is usually the dimmer type, not the lamp. A MOSFET AC dimmer fixes this at the hardware level. If you must use TRIAC, you need a lamp labeled «TRIAC dimmable» from Philips, Osram, or Ikea.
The Problem
Users connect an LED lamp to an AC dimmer on Arduino or ESP32 — and instead of smooth brightness control they get problems: the lamp ignores commands, cuts out sharply below 50%, flickers, or buzzes.
The instinct is to debug the code or buy a «better» lamp. But the root cause is usually something else: a TRIAC AC dimmer is physically not designed for LED lamps. It was built for resistive loads — incandescent filaments and heating elements. For LED there is a fundamentally different type: the MOSFET AC dimmer.
Typical symptoms from the forums:
- «LED strings don't dim completely off, and don't ramp up to bright» (Arduino Forum, 2024)
- «works until 70%, then drops intensity, starts buzzing, blinks up full power every few seconds» (Arduino Forum, 2026)
- «The bulb is off when the power is on the lower end of the sine wave and then on when the power is at the higher end. There are no intermediate brightnesses» (Arduino Forum, 2019)
- «Triac boards drive incandescent lights very well. But LED lights don't behave» (Arduino Forum, 2024)
Two Types of AC Dimmers: TRIAC vs MOSFET
Both types use phase-cut control (phase angle control): they chop part of the AC sine wave to reduce average voltage. The difference is which part they chop and how that affects LED lamps.
| Parameter | TRIAC AC Dimmer | MOSFET AC Dimmer |
|---|---|---|
| Control method | Leading edge (forward phase-cut) | Trailing edge (reverse phase-cut) |
| Designed for | Incandescent, halogen, heaters | LED lamps, electronic loads |
| Voltage waveform | Sharp spike at start of half-cycle | Smooth rising edge from zero |
| With dimmable Philips/Osram LED | ✅ Works | ✅ Works great |
| With cheap dimmable LED | ⚠️ Flicker < 40% | ✅ Stable |
| With non-dimmable LED | ❌ Won't work | ❌ Won't work |
| Holding current (light load problem) | ✅ Yes — a problem | ❌ None |
| LED dimming range | 20–95% | 5–95% |
Why MOSFET is better for LED: the MOSFET opens at the very start of the half-cycle — voltage rises smoothly along the sine wave. The LED driver sees a familiar rising edge with no abrupt spike. Result: stable operation with any dimmable LED lamp, significantly less flicker.
Root Cause
Background theory: AC Dimmer: Zero-Cross and TRIAC — How It Works.
The TRIAC problem with LED: the TRIAC fires after a delay following zero-cross. At the moment it fires, voltage jumps abruptly from zero to tens or hundreds of volts — a sharp leading edge. Many LED drivers interpret this spike as interference or a power surge, trigger protection circuits, and operate erratically.
An LED lamp is not a simple resistive load. Inside every LED lamp is a driver (a switching power supply) that rectifies AC and converts it into a stable DC current for the LEDs. How that driver reacts to a TRIAC-cut sine wave:
- Non-dimmable LEDs — treat the voltage drop as «power lost» and activate protection. The lamp only runs at full power or won't start.
- Cheap dimmable LEDs — do dim, but without filtering the pulsating current. Flicker at 100/120 Hz is visible to the naked eye.
- Quality TRIAC-compatible LEDs (Philips, Osram, Ikea TRÅDFRI) — specifically engineered for phase-cut TRIAC. They work, but the range is limited: 20–95%. Below that, holding current causes instability.
The holding current problem: every TRIAC requires a minimum current to stay on. A single 5–9 W LED lamp draws too little — the TRIAC randomly turns off, missing half-cycles. Result: random flashes and buzzing at low brightness. MOSFET dimmers have no holding current.
MOSFET solves both problems in hardware: no sharp spike, no holding current.
Solutions
🟢 Hardware Solution 1: MOSFET AC Dimmer ✅ Best Choice for LED
Want to use LED lamps without restrictions? The MOSFET AC dimmer is built exactly for that.
The MOSFET AC dimmer uses trailing edge control: the MOSFET transistor opens at the start of the half-cycle and closes at the calculated moment. Voltage rises smoothly — the LED driver operates correctly, flicker is minimal even at 5–10% brightness.
When to choose a MOSFET AC dimmer:
Compatible with any LED lamp labeled «dimmable» — including cheap no-name lamps that misbehave with TRIAC.
The code is identical to a TRIAC dimmer — same zero-cross interrupt, same library API. The difference is inside the hardware module:
// MOSFET AC dimmer — trailing edge
// Same code as TRIAC; the hardware difference is inside the module
// Library: rbdimmerESP32 (for ESP32)
#include "rbdimmerESP32.h"
#define ZC_PIN 18
#define DIM_PIN 19
rbdimmer dimmer;
void setup() {
dimmer.begin(ZC_PIN, DIM_PIN, 50); // 50 Hz mains
dimmer.setPower(50); // 50% brightness
}
void loop() {}Range: 5–95% brightness with any dimmable LED lamp.
🟢 Hardware Solution 2: DimmerLink (No ISR, Any Platform)
Don't want to deal with interrupts? DimmerLink controls the dimmer over I2C or UART — works with both TRIAC and MOSFET modules.
DimmerLink handles zero-cross synchronization and phase control internally. You simply send a command «set brightness to 50%» — everything else happens inside.
When to choose DimmerLink:
Wiring (I2C):
DimmerLink VCC → 3.3V
DimmerLink GND → GND
DimmerLink SDA → SDA (ESP32: GPIO21, Arduino: A4)
DimmerLink SCL → SCL (ESP32: GPIO22, Arduino: A5)// DimmerLink via I2C — no ISR, no zero-cross in your code
// Docs: https://www.rbdimmer.com/docs/dimmerlink-I2CCommunication
#include <Wire.h>
#define DIMMER_ADDR 0x50
#define REG_LEVEL 0x10
void setLevel(uint8_t level) {
Wire.beginTransmission(DIMMER_ADDR);
Wire.write(REG_LEVEL);
Wire.write(level);
Wire.endTransmission();
}
void setup() {
Wire.begin();
setLevel(50); // 50% brightness
}
void loop() {}🟡 Stuck with TRIAC: Choosing the Right Lamp
Can't replace the dimmer? Choose a lamp specifically rated for TRIAC.
Not all LED lamps respond the same way to TRIAC phase-cut. Some brands specifically engineer certain product lines for phase-cut compatibility.
Look for on the packaging:
- «TRIAC dimmable» or «phase-cut compatible»
- «leading edge compatible»
- Dimmer symbol with the letter «L» (leading edge)
Tested brands for TRIAC:
| Brand | Series | Range with TRIAC |
|---|---|---|
| Philips | SceneSwitch, WarmGlow, Master LED | 20–100% |
| Osram | CLASSIC, SUPERSTAR | 20–100% |
| Ikea TRÅDFRI | Dimmable range | 20–100% |
| GE / Cree | LED+ Dimmable | 25–100% |
TRIAC + LED limitations: even with quality lamps, the 0–20% range is unstable due to holding current. With loads under 15 W, random flashes may appear — add a ballast resistor (100–150 Ω / 20 W) in parallel, or increase the number of lamps. This problem does not exist with a MOSFET dimmer.
🔵 Advanced: Software Solution with TRIAC
Using a TRIAC dimmer with quality LED lamps?
Option A: ESP32 with rbdimmerESP32 ✅ Recommended
When: dual-core ESP32 + Philips/Osram/Ikea lamps Library: rbdimmerESP32
// Platform: dual-core ESP32
// Library: rbdimmerESP32
// For LED: use range 20–95% (below 20% is unstable with TRIAC)
#include "rbdimmerESP32.h"
#define ZC_PIN 18
#define DIM_PIN 19
rbdimmer dimmer;
void setup() {
dimmer.begin(ZC_PIN, DIM_PIN, 50);
dimmer.setPower(30); // start at 30%, not 0%
}
void loop() {
// Smooth ramp from 20% to 95%
for (int i = 20; i <= 95; i++) {
dimmer.setPower(i);
delay(30);
}
for (int i = 95; i >= 20; i--) {
dimmer.setPower(i);
delay(30);
}
}Option B: Arduino AVR (Uno, Mega, Nano)
For AVR boards only — do not use on ESP32! Library: RBDdimmer (legacy)
// Platform: Arduino Uno / Mega / Nano (AVR only)
// WARNING: for ESP32 use rbdimmerESP32 — not this library
#include <RBDdimmer.h>
#define ZC_PIN 2 // zero-cross — pins 2 or 3 only on Uno/Nano
#define DIM_PIN 11
dimmerLamp dimmer(DIM_PIN, ZC_PIN);
void setup() {
dimmer.begin(NORMAL_MODE, ON);
dimmer.setPower(50);
}
void loop() {}⚠️ Common Mistakes from the Forums
Real errors from 4 forum threads (2019–2026).
-
Trying to dim a non-dimmable LED through TRIAC: a lamp without a «dimmable» label is not designed for any phase-cut control. Neither TRIAC nor MOSFET will help. You need a different lamp.
-
«Cheap dimmable» lamp + TRIAC = flicker below 40%: the lamp is technically compatible, but its cheap driver doesn't filter TRIAC pulsations. Fix: MOSFET AC dimmer (no restrictions) or switch to Philips/Osram.
-
Load too light: TRIAC requires a minimum holding current. A single 5–7 W lamp causes random flashes. Below 15 W total load, add a ballast resistor (100–150 Ω / 20 W) in parallel. No such problem with MOSFET.
-
LED with active PFC driver (smart home lamps): incompatible with TRIAC phase-cut. Risk of damage. MOSFET dimmer also does not guarantee compatibility with active-PFC lamps.
Quick Checklist
Before posting to the forum, verify:
Compatibility Table
| Load type | TRIAC AC Dimmer | MOSFET AC Dimmer | Notes |
|---|---|---|---|
| Incandescent bulb 40–150 W | ✅ | ✅ | TRIAC ideal |
| Halogen 230V | ✅ | ✅ | TRIAC ideal |
| Heater / resistive element | ✅ | ⚠️ | TRIAC preferred |
| Philips/Osram «TRIAC dimmable» LED | ✅ | ✅ | MOSFET gives wider range |
| Cheap «dimmable» LED (no-name) | ⚠️ | ✅ | TRIAC: flicker < 40% |
| «Dimmable» LED, type unspecified | ⚠️ | ✅ | MOSFET more reliable |
| Non-dimmable LED | ❌ | ❌ | Neither type works |
| LED with active PFC driver (smart home) | ❌ | ❌ | Incompatible |
| Transformer halogen 12V | ⚠️ | ⚠️ | Depends on transformer |
Related Topics
- LED Flickering with AC Dimmer: TRIAC or MOSFET — Causes and Fixes
- Trailing Edge vs Leading Edge: Which Dimmer Method to Choose
Still Have Questions?
Post on rbdimmer.com forum or open a GitHub Issue.