There is probably a very obvious solution for this, but I cant find it…
I have a motion sensor that generate a quite short pulse for around 100us when movement is detected.
What’s the best way to detect this pulse reliably and use it as a trigger for an automation in ESPHome?
It looks like the standars gpio binary sensor is not fast enough to catch it.
What’s the limits for that?
I have also tried to use the Pulse Counter function and it can of course detect the pulses, but I have not found any way to trig on a single pulse at the input as all triggers even on_raw_value seems to be based on the sensor update interval.
One workaround may be to set an ridiculous low update interval, but that will totally flood the logs.
Is it possible create a template sensor that reads the hardware counter directly ?
Is it possible to create an interrupt for a pin that can be used as a trigger?
If you are into diy then you can use a transistor and a condensator or small elco on the gpio to extent the uptime. The pulse opens the transistor and that one charge the elco. That wil keep the gpio pin high longer.
Yes, an external hardware pulse extender is of cause a solution that will work, but it will be the last option for me as an ESP32 is more than capable to handle this without yawning - if just a few lines of the right code is added.
What do you consider ridiculously low? The pulse counter does seem to log unnecessarily at DEBUG level but you can filter that out with the logs: option in the logger, or just set the logger level to INFO.
Yes, that the way I went together with a 100ms sensor update time.
I must say I’m a little bit surprised that it doesn’t seems to exist any dedicated interrupt functions in ESPHome as everything else I have been looking for so far has been covered in some clever way.
Well, all the components work on a single-threaded cooperative loop. So the pulse counter uses interrupts to record the pulse, but to read it you have to wait until the loop thread gets back to that component, so there’s probably no better way to handle it.
The pulse counter code could probably be improved to handle the case where you just want know if a pulse occurred rather than actually counting them, and the logging level should be changed, but otherwise I think it’s fit for your purpose.
What is this sensor your using? Some information like product name/model # or a product link would be useful to us, especially in this case where the state change duration is ridiculously short like that.
How are you verifying that binary_sensor isn’t catching the state change?
Have you tried using Sensor Filters to do some Debouncing or to Settle the gpio state?
When you tried using a binary_sensor did you also try using any of it’s sensor filters such as, delayed_off: or delayed_on_off: ?? That will cause the sensor to continue showing On/Detected for the time you specify, even if the physical gpio state already switch back OFF which makes it’s speed a non issue as long as it can detect the initial pulse to the gpio.
No, has nothing to do with update_interval. That’s just the time frame at which it shows or sends a state change update back to the UI or HA. It can and does see state changes if they happen faster than the update_interval
That won’t help with anything. You need to use the sensor filters as mentioned above. Sensor Filters can be used with any types of Sensor’s and doesn’t matter if your’re using a binary_sensor or you’re using a pulse_count sensor because filters apply to all of them.
If binary_sensor actaully doesn’t work, which I would be absolutely surprised if it doesn’t while you also configure it with a delay_on_off filter but, in the case that it doesn’t the, the simplist option would be to create a simple filter that uses a lambda to do some conditions like to tell it to ignore values except the initial one that was 0 and changed to 1 while any values that come in back to back and greater than 1 within a time frame and if the last value is older then another time frame then reset it back to 0.
By ignoring values coming in faster than say 250ms it allows you to filter out repeat triggers and stabilize the sensor state. By checking if the last value was 0 to 1 and is older than say 2s that tells you that the motion sensor is clear/stable and to reset itself back to 0 and get ready again. The reason for resetting it is it would be of no value or help to keep counting or adding up the total number of pulses because you are only interested when it initially changes from 0/Off to 1/On and everthing not a 0 or 1 isn’t needed here.
ESPHome has no hardware interrupt ability so your solution has to be external.
You can make an SR flip-flop using a 74HC74 IC. Or you can make an SR latch using a pair of transistors. It wouldn’t matter when the pulse arrives, it latches the output of the RS flip-flop which you can pick up with a GPIO input. Another GPIO output can be used to reset the FF.
I don’t know for a fact that the sensor pulses at 100us and can’t be changed internally or via a trim-pot first of all and is why I asked for details about this sensor unlike yourself and others who just assume all OP’s are correct and know what they are talking about.
I also suggested making the equivalent of a delay_on_off filter while using Pulse_counter since OP says it is counting pulses with an unknown esp but, if they are using an esp32 that it certainly can catch 100us pulses within the 16ms loop interval and if you would have read the whole comment I would have made, then you could have avoided wasting your time and more importantly avoided wasting my time with such a dumb comment that isn’t applicable to all the suggestions I made to OP and now have to make a rebuttal to something no one else would have commented on if they had read the whole comment but, A+ for your big boy effort and 2 gold star stickers!!
Since pulse counter can catch it, I would probably use GPIO switch. But I would first make sure there is a requirement to really catch a 100us pulse, because that is going to have be one clean signal to catch without catching any kind of noise.
It looks the GPIO pins do support interrupts, so it just needs an edge.
Not true, the pulse counter uses interrupts (or the hardware pulse counter) and can count pulses with periods shorter than 100 microseconds. There are several other components that use interrupts, but the gpio binary_sensor does not, it just polls in the loop, so is not suitable for detecting short pulses.
I love to waste my time with my dumb comments. And it’s less wasted time than trying to catch 100us pulse looping it every 16ms.
Feel free to spend your time better than I do though.
The sensor in this case is Excelitas PYD 1598 and it is a part of a sensor for an occupancy system that I’m hacking/investigating.
The sensor pulls a line high when occupancy is detected and the internal micro confirm/reset the sensor by pulling the same line low, which happens around 100us later in this case, according to my measurements.
This makes the puls clean and sharp with very little noise so the detection should be quite straight forward if it’s in the detectible timeframe.
I have no problem to build some pulse extension hardware but as mentioned earlier, this should not be necessary with an ESP32, and I think it’s an interesting problem to solve if needed somewhere else too.
The ESPHome documentation claims that the Pulse Counter are able to catch pulses down to at least 13us (default internal_filter and max value for ESP32 hw counter) and I expect the standard input functions like Switch and Button to be significant slower as they are not ment to be used with such fast signals.
But I maybe have to try and play a little bit more with the Switch/Button functions to see what can be done.
I just set it up and blinked a LED (turn_on - delay - turn_off) using the on_press trigger, but that did not work for me and that was not a total surprise as a 100us puls is just cached by pure luck if it’s checked by a ms loop without any interrupts.
You are correct about that. That is why you HAVE to use interrupts. I linked the code that handles setting up pins and shows the interrupt attachment. Exactly how you specify this in esphome YAML is less clear.
esphome provides an abstraction layer which is designed to hide the underlying complexity. Sometimes this works well. Sometimes it makes things harder, because there is more that you need to understand.
Looks like esphome does NOT actually use interrupts, so not sure what the code I linked actually does.
This seems like a problem you will need to solve with a different solution.
What you mean with does NOT?
Pulse counter, rotary encoder, software uart, remote receiver, AC-dimmer etc
all use interrupts (at least on boards that don’t have specific peripherals for specific use).
Gpio binary sensor does not use.
Since the discussion was about switches (and buttons) it seemed unnecessary to be more specific. The linked post indicated interrupts are not generally used.
I know software serial uses interrupts, but isn’t generally available on the esp32. I suspect HW serial doesn’t, since it has a buffer it can just check every loop().
Pulse counter (on the esp32) uses the HW pulse counter, so again probably no interrupts needed.
I am confident it would be possible to create a component that uses interrupts to make something like the binary sensor that would respond (with some latency) to the quick change on the input pin. But it does not appear to be possible with the existing component.
Esp32 uses mainly peripherals, but Esp8266 uses interrupts. Same thing in practice.
I agree that there should be option for gpio binary sensor to use interrupts.
Even better if you could get trigger and the pulse length.
Pulse counter can be used in case of this topic, but it’s kind of work around for a simple task.
I guess, it would make a problem if some user decides to set all gpios as “interrupt binary sensor”.