← All articles
Standards / DALI instances

DALI Input Devices — Part III: Occupancy Sensors

How a DALI occupancy sensor builds the occupied state, why the command that cancels the hold timer sometimes does nothing, and when to move the hold time into the application controller.

Occupancy-controlled lighting works in zones — when a zone goes dark is decided by a timer inside the sensor, not by the controller
Occupancy-controlled lighting works in zones — when a zone goes dark is decided by a timer inside the sensor, not by the controller

This series looks at DALI input devices. Part I covered push buttons, part II covered light sensors. This part covers occupancy sensors — instance type 3, defined in IEC 62386-303.

A light sensor sends a number. An occupancy sensor sends the occupancy state of the space it covers, and that state additionally depends on a time configured in the sensor's parameters. Every difference in how you handle it follows from that.

The four sensor states

Instance type 3 has resolution equal to 2, which means inputValue takes exactly four values:

inputValueAreaMovement
0x00vacantno
0x55vacantyes
0xAAoccupiedno
0xFFoccupiedyes

The standard describes two kinds of device: movement based sensors and presence sensors.

Movement based sensors go straight to 0xFF the moment they detect movement and treat the space as occupied. On their own they cannot tell whether anyone is still there — occupancy is sustained by a hold timer, restarted on every further detection. Only once that timer expires does the sensor report the space as vacant. State 0x55 (vacant with movement detected) is unreachable for them, since movement implies occupancy.

Presence sensors report the state of the space directly, without inferring it. They never start a hold timer — as soon as they stop detecting a person, they report vacant.

In the field, the sensors you meet most often use PIR (passive infrared). A pyroelectric element responds to changes in the infrared radiation reaching it, and a Fresnel lens divides the observed space into zones. A warm body crossing from one zone to the next produces a pulse; a person sitting still produces none. That is why PIR is always a device of the first kind — movement based.

Presence sensors are rare, and are usually radar based: they analyse the reflection of their own emitted wave and pick up movement small enough that a motionless person is still visible. That is not a rule, though — a radar sensor does not automatically report itself as a presence sensor in DALI.

The controller does not have to guess which it is talking to. Bit 3 of the event says which kind of sensor produced it, which is the same as saying whether a hold timer has already been applied.

The events a movement sensor reports

A sensor can send six events: movement, no movement, occupied, vacant, still occupied, still vacant. They are bitwise OR-ed into a single event, so one message carries both the movement information and the occupancy state of the space.

The factory event configuration, held in the eventFilter register, is 0000 0011b — only occupied and vacant are enabled. Movement, no movement and the repeat events default to off.

The reason is practical. The sensor moves between 0xAA and 0xFF every time it starts or stops detecting movement, and with someone walking around a room that happens continuously. Every transition is a frame on the bus. tDeadtime — the minimum gap between events — is what limits them, but its factory value of 100 ms limits practically nothing. A few sensors on one line with the movement event enabled and tDeadtime left at the factory value can take up enough bandwidth to delay the commands that actually drive the luminaires.

So the movement event should not be enabled as a matter of routine. If you need it — and with the hold logic in the controller you do — enable it deliberately and cap the frame rate with the tDeadtime timer, covered below.

Timers

TimerVariableDefaultIncrementRange
Hold timetHold15 min10 s1 s – 42.3 min
Cyclic reporttReport20 s1 s1 s – 4 min 15 s
Minimum gap between eventstDeadtime100 ms50 ms0 – 12.75 s

Time is the increment times a multiplier of 0–255, with ±5% tolerance. They are written with SET HOLD TIMER, SET REPORT TIMER and SET DEADTIME TIMER and read back with the matching QUERY commands. tHold applies to movement based sensors only — a presence sensor answers MASK to QUERY HOLD TIMER.

The hold time actually set on site is 5 to 15 minutes, depending on the room.

Two dependencies are worth knowing up front. If tReport is shorter than tDeadtime, tDeadtime wins. And if a sensor detects its own failure it sets the instance error flag and stops sending events altogether. A silent sensor therefore does not necessarily mean broken wiring — query the instance status first.

How the movement events are handled

The question is who counts the hold time, and which events the decision to switch on and off is based on. There are three approaches. Each produces a working installation with a different character — and the choice often is not the installer's to make, since it depends on what the manufacturer of the application controller implemented.

Logic in the sensor. Set a long tHold, leave the factory event filter alone, and the controller listens to two events: occupied switches on, vacant switches off. Simple to configure, minimal bus traffic.

The drawback is that the system state is held by the sensor. The controller counts nothing; it waits for a message. If that message fails to arrive for any reason, the logic drifts and nothing corrects it: the controller still believes the room is occupied, because it never received anything to the contrary.

Logic in the controller. Set a short tHold, enable the movement and no movement events, and the controller counts the hold time. The sensor stops being the source of decisions and becomes a source of raw movement information.

This is more reliable, because the state sits in the controller — it can be inspected, reconstructed and corrected. In exchange you have to keep the bus traffic in check, and that is what tDeadtime is for. Ten seconds works well: the time resolution is more than sufficient for lighting control, and the events stop saturating the DALI line.

Whichever of those two routes you take, one more door stays open. The CATCH MOVEMENT command forces a single movement event to be sent even when that event is disabled in the filter, without changing the filter itself. It is useful for an occasional state check — before a schedule switches a zone off, for instance. If the movement event is already enabled, the command is ignored.

Cyclic polling. The third approach is classic polling: instead of waiting for events, the controller queries each sensor for its current state (inputValue) at fixed intervals and runs its logic on that.

It works, but two drawbacks follow from the principle itself. How fast the installation reacts depends directly on the polling interval — between one query and the next the controller knows nothing, and a brief walk into a room may go unnoticed entirely. And the interval cannot be shortened freely, because every query and every answer is a frame on the bus, and with several dozen sensors on a line that grows faster than the sensor count. You end up choosing between a slower response and a busier line.

Three cases that are not what they look like

Cancelling the hold timer only works in one of the states

The room is empty and the lights are still on: the sensor holds the occupied state until the hold timer expires
The room is empty and the lights are still on: the sensor holds the occupied state until the hold timer expires

A frequent function in an office building: you leave a room, switch the light off manually, and expect the sensor to behave normally for the next person walking in ten seconds later. For that to work, the manual switch-off has to clear the hold timer — otherwise the sensor considers the room occupied for the next several minutes.

That is what CANCEL HOLD TIMER is for. And very often the report that comes back is that "the sensor reset doesn't work".

How do you recognise it? By its inconsistency. Same command, same device, same scenario — sometimes the light goes out, sometimes it doesn't. A wrong address, a wrong group or a mis-programmed button would fail every single time; here the outcome depends on the moment of the press and looks random.

How do you diagnose it? The standard says CANCEL HOLD TIMER clears the timer and generates a 'vacant' trigger — but only while the timer is running. A sensor in 0xFF restarts the hold timer on every movement detection. The command lands on a timer that is about to restart anyway, and the whole effect disappears. It only takes hold in 0xAA — occupied, but with no movement.

In 0xFF every movement detection restarts the hold timer, so cancelling it has nothing to cancel; the command only takes effect in 0xAA, where the timer is genuinely counting down
In 0xFF every movement detection restarts the hold timer, so cancelling it has nothing to cancel; the command only takes effect in 0xAA, where the timer is genuinely counting down

Hence the dependence on geometry. With a narrow detection field, the person standing at the light switch is already out of range, so the device has moved to 0xAA and the reset goes through. With a sensor covering the whole room, that same person is still generating movement — and the identical press does nothing.

How do you fix it? Enable the no movement event in the filter (off by default) and queue CANCEL HOLD TIMER: do not send it when the button is pressed, hold it until the sensor reports no movement. Then the command lands on a timer that is genuinely counting down.

That is effectively a step towards the second school. Move the hold logic into the controller entirely and the problem disappears, because the hold time is cleared in the controller rather than in the sensor.

Sensor optics matched to a different mounting height

The same optics cover a completely different detection field under a warehouse roof and under an office ceiling
The same optics cover a completely different detection field under a warehouse roof and under an office ceiling

The mistake itself is obvious and fairly common; what is not obvious is its effect in the DALI layer. A sensor designed for high-bay warehouses, mounted on a low ceiling, covers a far larger detection field than the design assumed — and conversely, a sensor meant for low mounting sees half the space in a hall.

The "too wide" case is the harder one to spot, because it does not show up as missing detection but as too much of it. The sensor barely ever leaves 0xFF, the hold timer is restarted continuously, and everything that depends on the occupied-but-no-movement state — CANCEL HOLD TIMER first among them — stops behaving predictably.

The sensor triggers at night with nobody in the building

A night-time trigger in an empty zone: a PIR sensor near a ventilation inlet responds to moving air the same way it responds to a person
A night-time trigger in an empty zone: a PIR sensor near a ventilation inlet responds to moving air the same way it responds to a person

A PIR sensor mounted near a ventilation inlet responds to moving air. During automatic night purge it looks exactly like a person walking down a corridor.

How do you diagnose it? Record the bus traffic overnight and note which sensors triggered and when. Then cross-check against CCTV to confirm the space really was empty, and map each device address to its physical location. In the case above the triggers lined up with the automatic ventilation schedule, and the sensor turned out to sit a few metres from a mechanical ventilation inlet.


None of these three cases can be settled from a datasheet or a drawing. Each of them needs two things in view: what the sensor has configured inside it, and what it actually puts on the bus.

That is what Pilo One is for. The Monitor module listens to the bus and shows every sensor's events over time — when it reports movement, when it goes vacant, how often it does so, and whether that lines up with anything happening in the building. Night-time triggers from ventilation, a sensor with too wide a detection field that never leaves the movement state, events dense enough to load the line: all of it reads straight off the timeline, with no laptop wired into the panel.

The instance configuration is there to read from every device on the line: event filter, tHold, tReport, tDeadtime. You see them side by side, so it is immediately clear which sensor differs from the rest, and you can change them on the spot — no manufacturer software, no project files, on site and from a phone.

Pilo Agent takes that one step further: it reads those parameters and checks whether the intended control logic can work with them at all. Where it cannot — when clearing the hold timer depends on an event disabled in the filter, say, or when the movement event is enabled while tDeadtime is still at the factory 100 ms — it says what is wrong, proposes concrete values and, once you agree, writes them to the devices.

Next in the series: absolute input devices — sliders and dimmer wheels (IEC 62386-302).

Pilo One

Tired of spending hours debugging DALI lines?

Pilo One combines a pocket-sized hardware analyzer with an AI diagnostic agent to resolve faults in minutes.