So I followed the general idea of wiring a cheap aerosol dispenser up to an ESP32 and running it through ESPHome so Home Assistant can decide when to spritz. Got the whole thing working, mostly. The little motor presses the button fine, the binary_sensor shows up in HA, all good there. The weird part is the timing. I wanted it to only spray when the room is empty, since my cat is terrified of the noise, so I added a presence check before the spray action. But now every time she strolls past the coffee table the thing puffs right at her. The logic in my yaml looks right to me, something like 'if motion for less than 5 seconds then delay and spray', but it seems like it always sees her as 'just left' and sprays anyway. Am I thinking about the delay wrong? Does the motion sensor need a reset timer or something in ESPHome before the condition ever turns false? I've watched the logs and the state seems to flip back to off while she's clearly still sitting in the room, which makes me suspect the sensor itself, not the yaml. Or maybe both. Happy to paste my config if that helps anyone spot the dumb mistake I'm obviously making.
Why does my ESP32 spray trigger keep firing when my cat walks past instead of when she's on the other side of the room?
Oct 26, 2026
Last reply: 20 hours ago
5 Replies
First reply
Your yaml is probably fine, the sensor is lying to you. That's the classic PIR problem: those cheap motion modules only see movement, not a warm body sitting still. So the cat walks in, gets detected, then the second she settles on the couch the sensor drops back to off, and…
Read the full replyYour yaml is probably fine, the sensor is lying to you. That's the classic PIR problem: those cheap motion modules only see movement, not a warm body sitting still. So the cat walks in, gets detected, then the second she settles on the couch the sensor drops back to off, and your 'less than 5 seconds' condition happily passes. The logs showing off while she's clearly there is the giveaway. Two things fix this. First, in ESPHome put a delayed_off filter on the binary_sensor, something like 1 or 2 minutes. That smooths over the dropouts so the sensor reports on continuously while anyone's actually in the room, instead of flickering. Second, don't trigger the spray off a short 'motion for less than 5 seconds' window. Make the condition require the sensor to have been off for a good stretch, several minutes at least, before you consider the room empty. A cat strolling past for three seconds shouldn't clear the room in your logic.
Also worth doing: run the spray as a script in ESPHome rather than firing it straight from an automation. The script waits a few seconds, re-checks the motion sensor right before pressing the button, and stops if motion came back during the wait. That closes the gap where she wanders in between your check and the puff. You can loop that check a couple times too.
One more gotcha if you're still troubleshooting: most of those PIR boards have a sensitivity pot and a time pot, and people mistake the board's own hold time for ESPHome behavior. The sensor will hold its output high for that time after the last trigger no matter what your yaml says, so fiddling with delays in config alone won't help until you know what the board itself is doing. If PIR keeps being flaky even with the filters, a millimeter-wave presence sensor that detects stationary people and pets is a big step up, though pricier. For a spray schedule it's honestly overkill, the delayed_off approach usually does the job.
I've been thinking about the power part of this whole setup. I used a cheap 5 volt power block to run the ESP32 and the little motor for the sprayer. I worry that when the motor actualy tries to push the dispenser button, it might draw enough power that the voltage drops, right? If the power dips when it sprays, is that going to mess up the timing or make the ESP32 unstable while it is trying to execute the command?
The advice about using a delayed off filter is spot on. The PIR units just aren't reliable for 'presence' detection, only 'activity' detection, so you have to account for the board's own response time. I ran into this exact issue a while back when I first started doing this type of DIY home automation. I found that setting the delay too high felt like I was waiting forever for the room to be clear, but setting it just right at about 30 seconds solved the problem perfectly. That window gave the sensor time to settle without unnecessarily long waits.
The issue with basing the trigger on a simple state check after a delay, even with a delayed off filter implemented, is that it doesn't account for sensor hysteresis. If the PIR flips momentarily due to ambient light or heat variation while you are waiting for the condition to become true, the spray mechanism will initiate prematurely regardless of the intended long clear period. Consider structuring the logic to require continuous absence over a defined minimum time span before the action is permitted. This approach validates the stable enviornment before committing to the spray sequence, wich is far more robust than relying on a single instantaneous off state.
Update: the delayed off filter fixed the worst of it. She can settle on the couch now without getting a puff to the face. Still an occasional spray when she darts thru fast, which matches what one of you said about the sensor flickering on heat changes while the delay is running. Is there a clean way to require the room to stay empty for the whole delay window, or do I just accept a misting now and then?
Join the Discussion
Have something to add? Share your thoughts — no account required.
Didn't find your answer?
Ask the community — no account required