13 KiB
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 | €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 is the only real Schuko option and it's rated 200 W — under this lamp's draw.
Candeo C204 (~€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:
- Z2M web UI → Permit join, scoped to the coordinator.
- Power the module. It should appear within ~30 s.
- Let permit-join time out. Don't leave it open.
- Rename it immediately —
stage_lampor similar. Otherwiselight.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 oftenpreviousoron, which means a power blip or a Z2M container restart brings a 250 W stage lamp to full brightness in an empty room.
Two worth doing:
- Lower
min_brightness. Defaults are tuned to stop LEDs flickering at the bottom of the range. A filament dims smoothly to near-zero, so dropping it recovers the usable low end. - Pass
transition: 2inlight.turn_oncalls. 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 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 |