# Stage light dimmer — driving an old filament fixture from HA over Zigbee

**Short answer: a SONOFF MINI Extreme ZBDIM (400 W halogen rating) wired inline
into a short Schuko extension lead, paired to the existing Zigbee2MQTT instance.
Roughly €25, appears in HA as a normal dimmable `light` with no HA config at
all.** The only reason this needs a document is that the lamp has to be verified
*before* anything is bought — the wattage decides whether this is a €25 job or a
€100 one, and getting it wrong is the one path here with a real fire risk.

This is guidance, not automation — **nothing under this repo touches the fixture,
the dimmer, or the Zigbee pairing.** Same convention as `network-integration.md`:
you do this by hand, at move-in, after Phase 1 is up.

## 0. Prerequisite

Phase 1 must be running first: the Docker stack from
`tools/setup-container-host.sh`, with Mosquitto, Home Assistant, and
Zigbee2MQTT talking to the Haozee CC2652P dongle (`docs/project-plan.md:16`).
Nothing below works until `docker logs zigbee2mqtt` shows a healthy coordinator.

Everything in this doc stays on the Zigbee backbone rather than adding a WiFi
dimmer, for the reasons in `docs/components.md:208`.

## 1. Verify the lamp before buying anything

The fixture as measured in 2026: **19.6 cm lens diameter, ~15 Ω cold across the
lamp's own terminals, no transformer, no cooling fan.** That works out to roughly
a 250 W mains filament lamp. Re-verify at move-in — the fixture may have been
relamped, and the whole plan hangs on this number.

### 1a. Read the lamp first

The wattage is usually stamped on the pinch, base, or glass, and the fixture
nameplate states max lamp wattage and voltage. A type code is enough — CP60 /
CP61 / CP62 = 1000 W, CP95 = 500 W, HPL 575 = 575 W. **If you can read it, skip
to §2** — a printed number beats every estimate below.

### 1b. Or measure it running — better than any estimate

Not required, but it ends the guessing completely and costs almost nothing. A
plug-in energy meter (~€10, rated 16 A / 3680 W, so fine up to a 2 kW lamp)
reports true wattage directly: no tungsten coefficient, no lead nulling, no
arithmetic. A clamp meter (~€15) on the live lead does the same job.

Worth owning regardless — it's the same instrument you'll want the first time an
automation's power figures look wrong anywhere else in this project.

### 1c. Otherwise, estimate from cold resistance

Disconnected from mains, probe **across the lamp's own two pins** — not at the
plug. The plug reading includes the fixture's switch, wiring, and socket
contacts, which added ~4–5 Ω of error last time and made the lamp look half its
actual size.

    P ≈ V² / (R_cold × k)      →  at 230 V:  P ≈ 3530 / R_cold

`k` is tungsten's hot/cold resistance ratio, ~15 for theatre halogen (range
13–17). Expect ±25% overall.

| Cold reading | Likely lamp | | Cold reading | Likely lamp |
|---|---|---|---|---|
| ~18 Ω | 200 W | | ~5.4 Ω | 650 W |
| ~15 Ω | 250 W | | ~4.7 Ω | 750 W |
| ~12 Ω | 300 W | | ~3.5 Ω | 1000 W |
| ~7 Ω | 500 W | | ~1.8 Ω | 2000 W |
| open / ∞ | blown filament — **or a discharge lamp, see §1c** |

Null your leads first (short the probes, subtract that reading). Irrelevant at
15 Ω, critical below 5 Ω where lead resistance is a large fraction of the total.

A reading that wanders means bad probe contact, or that you're measuring a
winding rather than a filament. A good filament reads stable.

### 1d. Optional cross-check: fixture size

A sanity check on the estimate, not a rule. Lens diameter tracks wattage across
*professional theatrical* ranges, but older and budget fixtures routinely pair a
large lens with a modest lamp — lens size is set by the beam optics you want, not
the power. **Where this table disagrees with a terminal measurement, the
measurement wins.**

| Fresnel lens Ø | Typical lamp | | PAR can Ø | Typical lamp |
|---|---|---|---|---|
| 75 mm (3") | 150–300 W | | PAR36 · 114 mm | 6–12 V + **transformer** |
| 125 mm (5") | 500–650 W | | PAR56 · 178 mm | 300–500 W |
| 150 mm (6") | 1000 W | | PAR64 · 204 mm | 500–1000 W |
| 200 mm (8") | 2000 W | | | |

This fixture's 196 mm lens sits on PAR64, which would normally imply 500–1000 W,
while the terminal reading says ~250 W. That conflict is exactly what the caveat
above covers — but it's also why §1a/§1b are worth doing rather than trusting
either number alone.

### 1e. Three things that stop this plan dead

**Discharge lamp.** If the lamp or fixture says HMI, MSR, CSI, CDM, or HQI, or
there's a ballast/igniter in the base — **it cannot be phase-dimmed at all.**
Attempting it destroys the lamp and possibly the ballast. On/off relay only.

**Transformer in the fixture.** Confirm by pulling the lamp and re-measuring at
the plug: open circuit means the path was the filament and you're fine; a
remaining reading of tens of ohms means there's a winding in there. That's an
inductive load, generic dimmer modules are not automatically safe on it, and the
lamp is low-voltage rather than mains. Stop and reassess.

**Cooling fan.** If the fixture has one, it is usually wired in parallel with the
lamp downstream of the dimmer. Dim the circuit and the fan stalls while the lamp
still throws full heat. It must be fed from unswitched mains, ahead of the
dimmer.

## 2. Bill of materials — ~€25

| Item | Price | Note |
|---|---|---|
| [SONOFF MINI Extreme ZBDIM](https://www.amazon.de/SONOFF-elektronische-Halogenlampen-Neutralleiter-Leistungsmessung/dp/B0GFN145VT) | €15–20 | 400 W halogen, Zigbee 3.0, Z2M-supported, power monitoring, acts as a router |
| Short Schuko extension lead | ~€5 | Gets cut in half |
| Surface junction box (Abzweigdose) | ~€3 | Houses the module |
| Inline fuse holder + 2 A fuse | ~€3 | The module has no internal fuse |

At 250 W into a 400 W rating you sit at ~62% load — the headroom you want for
cold-filament inrush.

**Do not buy a plug-in Zigbee dimmer.** The whole category caps around 200 W
because a plug body has nowhere to dump triac heat. The
[AduroSmart ERIA dimmable plug](https://www.amazon.de/AduroSmart-Steckdose-Dimmbar-kompatibel-81855/dp/B08PKQVQTQ)
is the only real Schuko option and it's rated 200 W — *under* this lamp's draw.

[Candeo C204](https://www.amazon.de/Candeo-Dimmermodul-erforderlich-kompatibel-Smartthings/dp/B091GTK61Y)
(~€35) is an equally valid module if the SONOFF is unavailable. Same 400 W
halogen rating, same build job, no power monitoring.

## 3. Build the inline dimmer

Cut the extension lead, wire the module in a junction box: Schuko plug in, Schuko
socket out. The module needs neutral, which an extension lead has.

- Proper enclosure, no exposed conductors.
- Strain relief on **both** cable entries.
- Fuse in the live leg, upstream of the module.
- Don't bury the box anywhere unventilated. Thermal is the dominant failure mode.

If cutting mains cable isn't something you want to do, this is a 15-minute job
for an electrician — and there's no off-the-shelf product that avoids it, given
the 200 W plug ceiling above.

## 4. Pair with Zigbee2MQTT

`tools/setup-container-host.sh:503` sets `permit_join: false`, which is the right
default and means pairing is a deliberate act:

1. Z2M web UI → **Permit join**, scoped to the coordinator.
2. Power the module. It should appear within ~30 s.
3. Let permit-join time out. Don't leave it open.
4. **Rename it immediately** — `stage_lamp` or similar. Otherwise
   `light.0x00124b00...` ends up baked into every automation you write.

`tools/setup-container-host.sh:502` already sets `homeassistant: true`, so MQTT
discovery creates the HA `light` entity automatically. **No HA YAML, no manual
entity definition, nothing to commit to this repo** — the pairing lives in Z2M's
`database.db`, which the restic backups already cover
(`docs/project-plan.md:459`).

If Z2M reports the device as unsupported, pull a newer image rather than writing
a converter — the compose file already tracks `koenkk/zigbee2mqtt:latest`
(`tools/setup-container-host.sh:1184`).

## 5. Configure

One setting genuinely matters:

- **`power_on_behavior` → `off`.** Defaults are often `previous` or `on`, which
  means a power blip or a Z2M container restart brings a 250 W stage lamp to full
  brightness in an empty room.

Three worth doing:

- **Tune `min_brightness` by walking it down.** The default is set to stop LEDs
  flickering at the bottom of the range, and a filament doesn't need that
  protection — it dims smoothly to near-zero. But don't just set it to 1: at very
  low phase angles the triac stops latching reliably, which shows up as flicker
  or dropout rather than a dim glow. On the Z2M device page, lower it a step at a
  time until the lamp goes unstable, then back off one step. That point is the
  real bottom of the usable range, and it's fixture-specific — worth writing the
  final value down.
- **Cap `max_brightness` at 90%.** Filament life is brutally sensitive to
  voltage: roughly `life ∝ V⁻¹³` against `light ∝ V³·⁴`. Running at 90% buys
  about **4× the lamp life for ~30% less light** — a strong trade on a fixture
  whose lamp type may well be discontinued (§6), and this is a mood/accent light
  rather than something being asked to actually illuminate a room. Back off to
  95% (≈2× life, ~15% less light) if it turns out dimmer than you want. Rules of
  thumb, not exact, but the direction is very strong.
- **Pass `transition: 2` in `light.turn_on` calls.** Ramping over a couple of
  seconds cuts the cold-filament inrush, which is the biggest single wear event
  on the lamp and the main stress on the triac.

Optional and situational:

- **`switch_type`** — only relevant if a physical wall switch is wired to the
  module's input. Irrelevant for an inline extension-lead build; set it if the
  fixture ever gets a permanent installation.
- **Edge mode**, if the module exposes it. Trailing edge (Phasenabschnitt) and
  leading edge (Phasenanschnitt) both work fine on a pure resistive filament, so
  leave the default alone. It only becomes a real decision if a transformer ever
  enters the picture (§1e), where leading edge is the more tolerant of the two.
- **Surface the power reading in HA.** The ZBDIM's power monitoring arrives as
  its own sensor entity. A dashboard card, or a template alert if draw exceeds
  the expected figure, is cheap early warning on a failing lamp or a wrong
  relamp — and it's the only thing here that would catch someone plugging a
  bigger fixture into this dimmer.
- **Don't bother with a dimming curve.** Filament light output is very nonlinear
  against phase angle, so the HA brightness slider won't feel perceptually even.
  Correcting it is fiddly and buys little on a fixture like this; live with it
  unless it actually bothers you.

## 6. First run

- Non-flammable surface, module in open air, not boxed into anything yet.
- RCD-protected circuit, ideally on a 6 A or 10 A MCB rather than 16 A.
- Stay with it for the first 30 minutes and sweep the full dim range rather than
  parking at one level — **mid-dim is peak triac dissipation, not full-on**.
- **Check the power reading against the ~250 W estimate.** This is what the
  SONOFF's power monitoring is for; it replaces the resistance estimate with a
  direct measurement. Materially higher than expected → stop, reassess headroom.
- Check the fixture's clearance. Old stage cans run 200 °C+ housings and want
  ~0.5 m from anything flammable. If the triac ever fails short, the lamp sits at
  100% indefinitely — fine for the fixture, less fine for a curtain.

Worth doing once while the lamp is out: clean the lamp socket contacts. The
~4–5 Ω gap between the plug and terminal readings in 2026 was fixture wiring and
contacts, dissipating several watts as heat inside an already-hot fixture.

Two more that aren't required but pay for themselves:

- **Buy a spare lamp at the same time.** Theatre lamp types get discontinued and
  an old fixture is worth nothing without one. Record the exact type code once
  you've read it in §1a.
- **Label the finished dimmer box** with both numbers — lamp draw and module
  rating (250 W / 400 W). Future-you plugging a different fixture into a box that
  looks like a generic extension lead is the most plausible way this ends up
  overloaded.

## 7. If the lamp turns out bigger than ~400 W

Everything above is void; a 1 kW lamp pulls ~4.3 A steady and 50 A of cold
inrush, well past any in-wall module. Two routes, both built around a used
theatrical dimmer pack (€50–100 for 4×1200 W), which handles inrush, fusing,
heatsinking, and EMI properly:

| | Approach | Cost | Note |
|---|---|---|---|
| **B** | Zigbee 0–10 V dimmer (YSRSAI YSR-Mini-01 or Lonsonho VM-Zigbee-S02, ~€20–25) into the pack's **0–10 V analog input** | €75–125 | Stays on the Zigbee backbone. Most analog packs already have this input. |
| **C** | ESP32 + RS485 module (~€10) running [andyboeh/esphome-dmx512](https://github.com/andyboeh/esphome-dmx512) driving the pack over DMX512 | €60–110 | Cheapest, fits the existing `firmware/` ESPHome pattern, but breaks the Zigbee-only lighting rule in `docs/components.md:208`. |

Prefer **B** — €20 more to keep lighting on one backbone is noise, and either
way you get three spare channels for future fixtures.

## 8. Troubleshooting

| Symptom | Likely cause |
|---|---|
| Device never appears in Z2M | Permit-join timed out; module has no neutral; too far from coordinator for its first hop |
| Appears in Z2M, not in HA | `homeassistant: true` missing, or Mosquitto auth failing — check `docker logs zigbee2mqtt` |
| Lamp stuck at full, unresponsive | Triac failed short. Unplug at the wall. Usually means the load exceeded rating — re-measure before replacing |
| Buzzing or humming from the lamp | Normal for phase-cut dimming of big filaments (magnetostriction). Worse at mid-dim. A dimmer pack's choke fixes it; an inline module won't |
| Flicker at low brightness | Raise `min_brightness` |
| Module warm to the touch | Expected. Hot enough to be uncomfortable means it's under-rated for the load |
| Resistance readings that don't reconcile | A parallel path can never *raise* total resistance. If pulling the lamp makes the reading go **down**, the two measurements weren't the same configuration — re-probe both at the lamp terminals |
| Lamp reads open but fixture still conducts | The lamp is blown *and* there's a fan or transformer across the input. Both §1e cases at once — replace the lamp, then re-read §1e before wiring anything |
