Main

Why Your Motion Automations Lag After Dark and How to Fix the Timing

Motion automations that snap on instantly during the day but drag after sunset aren’t some unsolvable riddle. They’re a sign the system was never tuned for the sensor physics and network conditions that shift once the lights go out. In locally controlled smart homes, this is a familiar failure mode: the passive infrared (PIR) sensor’s internal gain adjustment, the microcontroller’s polling loop, and the mesh network’s route-rebuild behavior all change in the dark. If your timing thresholds were set under daytime conditions, you’re now running outside the calibration envelope. The answer isn’t a faster hub or a cloud subscription. It’s a methodical re-audit of sensor placement, firmware timing parameters, and the local Zigbee or Z-Wave route table.

For operators who stick with open-source firmware and local-only logic, this article walks through the diagnostic sequence I use when a client reports that their hallway lights take two seconds instead of two hundred milliseconds to fire after dusk. We’ll cover the hardware-level reasons for the lag, how to measure it without expensive tools, and the tradeoffs you make when you adjust debounce timers, retrigger lockouts, and reporting intervals. The goal isn’t zero latency—it’s predictable, bounded latency that you understand and control.

What Changes in the Sensor at Night

A passive infrared sensor doesn’t see light; it sees changes in infrared radiation against a background. During the day, the background is warm and dynamic—sunlight through windows, thermal currents from radiators, even the heat signature of a pet walking across a sun-warmed floor. The sensor’s onboard amplifier automatically adjusts its gain to avoid saturating on that noisy background. When ambient light drops, the background cools and stabilizes, and the gain creeps up to maintain sensitivity. That’s by design, but it introduces a side effect: the sensor’s noise floor rises, and the onboard digital filter takes longer to distinguish a real motion event from a random thermal fluctuation. The result is a delay that can range from 200 milliseconds to over a second, depending on the sensor’s firmware and the quality of its Fresnel lens.

In open-source firmware like Tasmota or ESPHome running on a PIR-equipped board, you can observe this directly. The raw ADC readings from the PIR element will show a wider spread of noise after dark, and the digital filter’s settling time increases. If you’ve set a short debounce period—say, 50 milliseconds—to get snappy daytime response, that same threshold may now be too tight, causing the sensor to miss the initial edge of a valid trigger and wait for the next one. The result is a perceived lag that isn’t a network problem at all; it’s a front-end detection delay.

PIR motion sensor mounted on a wall in a dimly lit hallway

How the Microcontroller’s Polling Loop Adds Jitter

Most DIY sensors run on ESP8266 or ESP32 boards with a main loop that polls the PIR pin, checks Wi-Fi or Zigbee queues, and services other tasks. In ESPHome, the default loop() iteration is fast, but if you’ve added multiple sensors, deep sleep logic, or blocking operations, the time between PIR pin reads can stretch. During the day, the PIR signal is strong enough that a 50-millisecond polling gap doesn’t matter—the pin is already high when the loop checks. At night, with a weaker, slower-rising signal, that same gap can mean the difference between catching the event in one loop iteration or two, adding 50–100 milliseconds of jitter.

Zigbee sensors have a similar issue, but it’s hidden inside the chip’s firmware. The CC2530 or EFR32 MCU inside a typical Zigbee motion sensor runs a real-time operating system (usually Z-Stack or EmberZNet) that schedules the PIR interrupt, the radio stack, and the reporting logic. When the sensor’s reporting interval is set to a conservative 60 seconds to save battery, the radio may be in a sleep state when motion occurs. Waking the radio, re-joining the network if the parent node has changed, and sending the report can add 100–300 milliseconds. During the day, the sensor may have been reporting more frequently due to constant triggers, keeping the radio awake. After dark, with fewer triggers, the radio sleeps deeper, and the first motion event pays a wake-up penalty.

Measuring the Real Delay with MQTT Timestamps

You don’t need a logic analyzer to quantify the lag. If your automation controller runs Home Assistant, open the MQTT integration’s debug log or use mosquitto_sub on the broker to capture the exact timestamp when the motion topic is published. Then trigger the sensor with a known event—a hand clap near the sensor while watching a clock with a second hand, or better, a smartphone video recording the sensor’s LED and the resulting light activation. Subtract the MQTT timestamp from the video timestamp to get the end-to-end delay. Do this at noon and again at midnight, with the same trigger method. The difference is your nighttime penalty.

For Zigbee sensors, use the zha_event or z2m_event listener in Home Assistant to capture the Zigbee cluster report timestamp. Compare that to the MQTT publish time to see how much delay is inside the coordinator versus the network. If the Zigbee timestamp is already 300 milliseconds old when it hits the coordinator, the problem is in the sensor or the mesh; if the Zigbee-to-MQTT gap is large, your coordinator or broker is the bottleneck.

Network Route Flapping After Dark

Zigbee and Z-Wave meshes are not static. When a mains-powered repeater (a smart plug or light bulb) is turned off at night—because someone physically switched off a lamp, or an automation cut power to a standby load—the mesh topology changes. Battery-powered sensors that were routing through that now-offline node must find a new parent. The route discovery process in Zigbee can take 500 milliseconds to several seconds, depending on the network size and the number of retries. During the day, that same repeater was powered on, and the route was stable. The lag you see at night may be a route rebuild, not a sensor issue.

Check your Zigbee coordinator’s neighbor table and route table before and after dark. In Zigbee2MQTT, the network map shows parent-child relationships. If a motion sensor’s parent changes between day and night, you’ve found the culprit. The fix is to ensure that critical sensors have a stable, always-powered parent within direct range. That might mean adding a dedicated Zigbee repeater (not a bulb that can be switched off) or relocating the sensor closer to the coordinator. In Z-Wave, run a network heal after any change to powered-node status, and consider setting the motion sensor’s wake-up interval to a shorter value if battery life allows.

Close-up of a Zigbee USB coordinator plugged into a home server

When the Hub’s Logic Introduces Its Own Delay

Even with perfect sensor hardware and a stable mesh, the automation controller can add latency based on time-of-day conditions. Home Assistant’s state machine processes events in order, but if you have a heavy nighttime automation load—sunset triggers, light transitions, thermostat setbacks—the event queue can back up. A motion event that arrives during a burst of state changes may wait 50–200 milliseconds before being evaluated. This is rarely the dominant factor, but it’s worth checking: in Home Assistant, the automation.trigger trace timeline shows the time between trigger and action. If the “triggered” timestamp is close to the MQTT timestamp but the “action” timestamp is delayed, your automation is waiting on something—a condition template that queries a slow sensor, a script that’s still running from a previous trigger, or a queue full of light.turn_on service calls with long transitions.

One specific gotcha: if your automation uses a sun condition or a template that checks sun.sun elevation, that entity updates only once per minute by default. If the motion event arrives just before the sun entity updates, the condition may evaluate with stale data, causing a missed trigger or a fallback to a slower code path. Switch to using the sun trigger platform’s before/after offset directly, or increase the sun component’s update frequency if you need finer granularity.

Firmware Parameters That Control Timing

If you’re running open-source firmware, you have direct control over the parameters that matter. Here are the ones I adjust when chasing nighttime lag, with the tradeoffs for each:

  • Debounce time (PIR pin filter): The number of milliseconds the pin must remain high before the firmware considers it a valid trigger. Lower values (10–30 ms) give faster response but more false triggers from noise. At night, you may need to raise this to 50–80 ms to avoid false triggers, but that directly adds to the perceived lag. The better fix is to improve the analog front end—add a small capacitor (0.1–1 µF) across the PIR output to smooth the signal without relying solely on digital debounce.
  • Retrigger lockout (occupancy timeout): The period after a trigger during which the sensor will not report a new motion event. On many Zigbee sensors, this is hard-coded to 60–120 seconds to save battery. If someone walks through the space, triggers the sensor, and then another person follows 30 seconds later, the second event is suppressed. At night, when traffic patterns change, this can make the system feel unresponsive. In ESPHome, you can set this to a low value (1–5 seconds) and handle occupancy logic in the controller. The tradeoff is more radio transmissions and faster battery drain.
  • Reporting interval (Zigbee/Z-Wave): The maximum time between sensor reports, even if no motion is detected. A long interval (e.g., 3600 seconds) lets the radio sleep deeply, saving battery but increasing the wake-up delay on the first trigger. Shortening this to 300–600 seconds keeps the radio more responsive at a cost of roughly 5–10% battery life per year, depending on the sensor. For mains-powered sensors, set this to the minimum allowed.
  • Illuminance threshold (if equipped): Some motion sensors include a lux sensor and only report motion when ambient light is below a threshold. If that threshold is set near twilight, the sensor’s internal logic may delay motion reporting while it decides whether the light level qualifies. Disable this feature in the sensor and handle day/night logic in the controller, where you have more control over hysteresis and timing.

Practical Calibration Sequence

Here’s the step-by-step process I follow when a client reports nighttime lag. It assumes you have local access to the sensor’s firmware configuration (ESPHome, Tasmota, or Zigbee2MQTT device options) and a way to monitor MQTT or Zigbee events in real time.

1. Log Baseline Daytime Latency

Trigger the sensor 10 times during daylight hours, recording the end-to-end time from physical motion to automation action. Use a smartphone video recording the sensor’s LED and the controlled light, with an MQTT log running on a laptop. Calculate the median and 95th percentile. A well-tuned PIR sensor on a stable mesh should show a median under 300 ms and a 95th percentile under 500 ms for local-only automations.

2. Log Nighttime Latency

Repeat the same test after the space has been dark and unoccupied for at least 30 minutes—long enough for the sensor’s gain to stabilize and the mesh to settle into its nighttime topology. Compare the median and 95th percentile. If the nighttime median is more than 100 ms higher, you have a sensor or firmware issue. If the 95th percentile is more than 500 ms higher, you likely have a network route-flapping problem.

3. Isolate the Sensor

Temporarily move the sensor to a test bench with a known-good power supply and a direct, short-range Zigbee or Wi-Fi connection to the coordinator. Trigger it in the dark using a consistent heat source (a hand waved at a fixed distance). If the lag disappears, the problem is environmental or network-related. If the lag persists, the problem is in the sensor’s firmware or hardware.

4. Adjust One Parameter at a Time

Start with the debounce time. Reduce it by 10 ms increments until false triggers appear, then back off by 20 ms. Next, shorten the reporting interval on battery sensors. Finally, if you’re using a lux-based lockout, disable it and replicate the logic in your automation controller. After each change, repeat the nighttime latency test. Document the results—this becomes part of your system’s calibration record, which is invaluable when you add new sensors or change the physical layout. For more on maintaining that record, see How to Audit the Small Systems That Quietly Run Your Week.

When the Fix Requires Hardware Changes

Sometimes the sensor’s analog front end is simply not designed for the environment. Cheap PIR modules often use a BISS0001 or similar chip with a fixed gain and a mediocre Fresnel lens. In a long hallway or a room with large windows, the sensor may never achieve a clean signal at night, no matter how you tune the firmware. In that case, consider replacing the sensor element itself. Panasonic’s EKMC series and Murata’s IRA-S series offer better signal-to-noise ratios and more consistent gain over temperature. They’re drop-in replacements for many common modules and cost under $10. Pair one with an ESP8266 running ESPHome, and you have a sensor that outperforms most off-the-shelf Zigbee units.

Placement matters as much as the sensor itself. A PIR sensor aimed at a window will see the cold sky at night, which can pull the background temperature so low that the gain maxes out and the sensor saturates on its own noise. Aim sensors away from windows and exterior walls, or use a mask on the Fresnel lens to block those zones. If you must cover a window-adjacent area, consider a microwave (radar) sensor instead, which is immune to thermal background shifts but introduces its own set of false-trigger challenges from walls and moving air.

Person adjusting a smart home sensor on a wall with a screwdriver

FAQ

Why does my motion sensor work fine during the day but miss events entirely at night?

This is often a gain-stabilization problem. When the background temperature drops, the sensor’s amplifier increases gain to compensate, which also amplifies noise. If the digital threshold is set too high, the sensor may never register a valid trigger. Lower the threshold in firmware, or add a hardware low-pass filter (a capacitor across the PIR output) to clean up the signal before it reaches the microcontroller.

Can a weak Zigbee mesh cause motion lag only at night?

Yes, and it’s common. During the day, a repeater that’s powered on provides a stable route. At night, if that repeater is switched off, the sensor must find a new parent, which can take several hundred milliseconds. Check your Zigbee network map at night to see if the sensor’s parent has changed. If it has, add a dedicated always-powered repeater or relocate the sensor.

How much battery life will I lose by shortening the reporting interval?

It depends on the sensor, but a rough estimate: reducing the reporting interval from 3600 seconds to 300 seconds increases radio transmissions by a factor of 12, but the radio is only active for a few milliseconds per transmission. Overall battery life might drop from 2 years to 1.5 years. For a CR2450-powered sensor, that’s a tradeoff many operators accept for more responsive nighttime performance. If you’re using rechargeable batteries, the cost is negligible.

Is it better to handle day/night logic in the sensor or the controller?

In the controller, almost always. Sensors with built-in lux thresholds add a black-box delay and make it harder to tune hysteresis. By moving the logic to Home Assistant or Node-RED, you can use the sun’s elevation, a separate lux sensor, or a time-based schedule, and you can adjust it without reconfiguring each sensor. The one exception is a battery-powered sensor where you want to suppress reports entirely during the day to save power; in that case, use the sensor’s built-in threshold but test it thoroughly for timing impacts.