'ESP8266 running NodeMCU - Detect Pulse Stream Start/Stop
I've built an automatic, self-filling water bowl for my dogs that's working perfectly with a water level controller and I'd like to now add some monitoring capabilities using an ESP8266. Like detecting if water is flowing, or an overflow has occurred.
Watching the level sensors and an overflow sensor are no problem, but I'm stuck at detecting the water flow.
I have a hall-effect flow sensor that sends a 1/0 pulse stream when water is flowing through it, and I can detect it fine using an interrupt on a GPIO pin. My issue is that I can't wrap my head around a way to reliably detect when the pulses stop.
My solution so far is to count the pulses and write the value to a counter and then set a test counter equal to it. My thought being that, as long as the water is flowing, the count will continue to change and once the water stops, the counts will stay equal. This all happens using a timer that starts when the GPIO interrupt is triggered.
It works mostly as intended, but when the timer fires, it checks the two counter values, and for a moment they're the same, so it indicates that the flow has stopped for one cycle and then picks up the flow again. This is the behavior that I'm trying to overcome.
My code looks like this:
flow_sense_pin = 1
flow_counter = 0
test_counter = 0
flow = false
flow_timer = tmr.create()
flow_timer:register(4000, tmr.ALARM_AUTO, function() test_flow() end)
gpio.mode(flow_sense_pin,gpio.INT)
function flow_pin_cb(level)
gpio.trig(flow_sense_pin, level == gpio.HIGH and "down" or "up")
flow_counter = flow_counter + 1
test_counter = flow_counter
if flow == true then else print("Flow Detected") end
flow = true
flow_timer:start()
end
function test_flow()
if test_counter == flow_counter then flow = false end
if flow == false then flow_timer:stop() print("Flow Stopped") end
end
gpio.trig(flow_sense_pin, "down", flow_pin_cb)
And the output at the terminal is such:
I'm sure I'm overlooking something obvious but I've beat my head against it for hours and I'm not getting anywhere.
Solution 1:[1]
I'd take this simpler and probably more robust approach:
create the
flow_timer
object as you didin the function triggered by the flow pulse (
flow_pin_cb
), callflow_timer:alarm(timeout, tmr.ALARM_SINGLE, flow_stop)
where
timeout
is a time just a little longer than the maximum time between pulses of a continuous flow andflow_stop
is a function which is then called when the flow stoppeduse a flag, let's call it
flowing
in
flow_pin_cb
, ifflowing
is false,print("Flow Detected")
and setflowing
truein
flow_stop
,print("Flow Stopped")
and setflowing
false
Solution 2:[2]
I still need to do some pulse width testing but that works perfectly and the new code is MUCH simpler! Thank you!
The new code is MUCH simpler:
flow_sense_pin = 1
timeout = 1000
flow_timer = tmr.create()
flowing = false
gpio.mode(flow_sense_pin,gpio.INT)
function flow_pin_cb(level)
gpio.trig(flow_sense_pin, level == gpio.HIGH and "down" or "up")
if flowing == false then print("Flow Detected") flowing = true end
flow_timer:alarm(timeout, tmr.ALARM_SINGLE, flow_stop)
end
function flow_stop()
print("Flow Stopped")
flowing = false
end
gpio.trig(flow_sense_pin, "down", flow_pin_cb)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Armali |
Solution 2 | Jeff |