Does any GPIO node support edge events, rising or falling state changes?

That doesn't seem to be what the code is doing, it appears to be just measuring the time between two pulses and working it out from that, though perhaps I am misinterpreting something. If I am right I am not surprised there is a lot of noise on the output.
How often do you need a reading? If, for example, you want an update once a second it would be much better to count pulses until a second is up and work it out from that.

Oh, actually you are right. Brain fart on my part. Should be time frame between pulses.

Pulses per time is a different implementation strategy. Or beam breaks. Thought of using a IR transmitter and receiver to 'watch' the blades turning, for a fan that I have that lacks a pulse signal.

Fastest solution is write the input edge checking program in
c or c++. The task must run in thread and you can get the data by shared memory and syncronize with mutex.
But one problem is that the the time cycle isn't very accurate because linux isnĀ“t a realtime OS.
The best and accurate solution is to make this with hardware.
It exist chips that convert frequency to voltage.
This cips are very accurate. You can measure the voltage with an analog digital converter.

Try something like this in the function, in the flow below it counts zero transitions over a period of two seconds in a rolling buffer and provides a current frequency every second.

buffer = context.get("buffer") || []
const interval = 2000       // number of msec to count over

const now = new Date().getTime()
stripMessages(buffer, now)     // remove old messages from the buffer
if (msg.topic == "trigger") {
    msg.payload = buffer.length*1000/interval  // number of messages/sec in interval
} else if (msg.payload === 0) {
    // only count messages where payload is 0
    buffer.push(now)
    msg = null
}
context.set("buffer", buffer)
return msg;

function stripMessages( buffer, now ) {
    // strips messages off the front that are too old
    const earliest = now - interval
    while (buffer[0] && buffer[0] <= earliest) {
        buffer.shift()
    }
}

image

[{"id":"52bd5022.fb4568","type":"inject","z":"bdd7be38.d3b55","name":"5/sec","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"0.2","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"0","payloadType":"num","x":140,"y":4720,"wires":[["33040f7e.97a0c8"]]},{"id":"e1d9ea3c.cc2b08","type":"inject","z":"bdd7be38.d3b55","name":"1 second trigger","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"1","crontab":"","once":false,"onceDelay":0.1,"topic":"trigger","payload":"","payloadType":"date","x":310,"y":4780,"wires":[["33040f7e.97a0c8"]]},{"id":"33040f7e.97a0c8","type":"function","z":"bdd7be38.d3b55","name":"Frequency","func":"buffer = context.get(\"buffer\") || []\nconst interval = 2000       // number of msec to count over\n\nconst now = new Date().getTime()\nstripMessages(buffer, now)     // remove old messages from the buffer\nif (msg.topic == \"trigger\") {\n    msg.payload = buffer.length*1000/interval  // number of messages/sec in interval\n} else if (msg.payload === 0) {\n    // only count messages where payload is 0\n    buffer.push(now)\n    msg = null\n}\ncontext.set(\"buffer\", buffer)\nreturn msg;\n\nfunction stripMessages( buffer, now ) {\n    // strips messages off the front that are too old\n    const earliest = now - interval\n    while (buffer[0] && buffer[0] <= earliest) {\n        buffer.shift()\n    }\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","x":370,"y":4720,"wires":[["8b917023.bc2818"]]},{"id":"8b917023.bc2818","type":"debug","z":"bdd7be38.d3b55","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":400,"y":4680,"wires":[]}]
1 Like

@iiot2k, You are correct, using C would be better for better accuracy, any interrupt based hardware dedicated to the task, etc., things already mentioned in this thread, would in each method get more accurate results. Using an Arduino or ESP32 (or ESP8266) would be such. Of course a dedicated circuit even better. However, it is the desire to not do such, but still get something approximately accurate, and thus acceptable is fine in my use case. This started as just a simple check for the fan is spinning or not, to well how well is the fan running. To is the fan degrading, type of progression. The fan is in a very dirty environment, and it tends to slow over time until cleaned (again).

@Colin, nice idea. I use a python list as the sampling store in the python script as well. I had not worried about it as yet with the initial NR flow. I was gong to add mean, variance, and standard deviation, to the flow, just to provide context like the python script does. Your suggestion make that simplistic.

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.