10kHz frequency signal

Hi all

Is there a way to produce a 10kHz frequency signal to count up a counter with?

Thanks for your help,
Mark

Can you clarify exactly what you mean please? Are you talking about a hardware output or what?

Im just talking about a counter as a node msg.payload. Target is to build a digital twin of flow meter.

Mark

I doubt this would be easily achievable within a flow, given that you need to send a payload every 100 microseconds, and the operating system is not "realtime".

There are highly accurate oscillators you can buy that output 10k, and depending on how fancy you want to get there are both fixed and digital controlled frequency outputs

Eventually you could look into making a signal generator using an ESP32 device. Then sending the signals to Node-RED; MQTT, GPIO....

Or this, even simpler I think:

Theoretically, this should do what you want

Whether it'll do what you need in practice is another matter :slight_smile:

[{"id":"759e555cfae5e864","type":"inject","z":"80a5a214f02754bd","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"0.0001","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"1","payloadType":"num","x":130,"y":120,"wires":[["6d8ee7259f9862a1"]]},{"id":"084186bdde00fd4e","type":"debug","z":"80a5a214f02754bd","name":"debug 467","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":510,"y":120,"wires":[]},{"id":"6d8ee7259f9862a1","type":"trigger","z":"80a5a214f02754bd","name":"","op1":"","op2":"0","op1type":"pay","op2type":"num","duration":"0.05","extend":false,"overrideDelay":false,"units":"ms","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":300,"y":120,"wires":[["084186bdde00fd4e"]]}]

This seems to work but for some reason I was not able to create a up-counter from this 10kHz output. My application would be as follows:

  • Getting a Frequence Value from 5Hz-10kHz e.g. 550Hz.
  • Building de cycle time for the counter which shall count-up in given frequence e.g. 1/550 = 0.001818
  • Reset Counter if a reset signal comes

Target is to build kind of flow meter as digital twin. Such flow meters provide flow as Frequence-Signal

Regards Mark

No one here who could help me in this case?

Regards, Mark

In what case Mark?

Some guys have given you sound advice already.

Do you have a specific question (as opposed to a wish list)?

Do you have something sorta working that you need a little help with - if yes, post your work and clarify the ask.

My last post might not be visible to you, sorry.

I wrote about having an up-counter that dynamically changes its counting interval depending on a variable frequency of 5Hz-10kHz. E.g. current frequency 550Hz, calculate the interval 1/550 = 0.001818s. The counter should now count with a period of 0.001818 seconds. If the frequency changes, this should always lead to the period duration of the counter being updated.

Ultimately, I want to be able to reset the counter at time x (but I can do that myself)

Regards, Mark

Not clear I'm afraid.

Let me ask another way.

Are you still attempting to achieve your original brief of...

And do you expect to be sending msgs through Node-RED flows at a frequency up-to 10khz?

I ask because:

  1. As other have pointed out, achieving this on a non-realtime OS is pretty much never going to work.
  2. Asking for an "an up-counter" is not something that really makes sense. I mean, you could turn on the count mode in a debug node and it will show a count value whenever a msg arrives but it is fairly pointless for anything except debugging.

Now if you are only wanting this value for display purposes & don't mind in-between values being skipped, it might be possible to achieve something appoximating a "counter" that increases at a particular frequency, but it will be far from accurate and will NOT be realtime (i.e. its update frequency may be far less than what you expect, but its value should track when it updates.

does any of that ^ make sense?

Here is my best guess at what you want without grinding Node-RED to a halt.

It uses a time difference from poll to poll to avoid jitter errors and calculate what would have passed in order to approximate realtime counting at such high frequencies.

chrome_kllLjua6rH

NOTE: When I say it approximates I mean since it calculates the count based on time since the last update, in-between will be skipped:

Demo flow (use CTRL-i to import)

[{"id":"2e37e7e4caafc2d6","type":"function","z":"3567e03e18126502","name":"freq sim","func":"const INTERVAL = 500; // Interval in milliseconds\nlet FREQ = BigInt(flow.get('FREQ') || 5000); // Frequency in Hz\nlet counter = BigInt(context.get('counter') || 0)\nlet lastTime = context.get('lastTime') || process.hrtime.bigint()\n\nif (msg.topic === 'reset') {\n    counter = 0n\n}\n\nconst currentTime = process.hrtime.bigint();\nconst timeElapsed = (currentTime - BigInt(lastTime)) / BigInt(1e6) // Convert nanoseconds to milliseconds\ncontext.set('lastTime', lastTime)\n// Increment the counter based on time elapsed and frequency\nconst change =  (FREQ * timeElapsed) / 1000n; // FREQ in Hz, so we scale by 1000 to convert to milliseconds\ncounter = counter + change\ncontext.set('counter', counter)\ncontext.set('lastTime', currentTime)\n\nmsg.payload = {\n    FREQ: Number(FREQ),\n    counter: Number(counter),\n    change: Number(change)\n}\n\nreturn msg","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[{"var":"process","module":"process"}],"x":1930,"y":260,"wires":[["93f8de66b1605ca4","f4c320026c297d9b","1b3ee499fa0f9e40","7cb84fbf78a774d2"]]},{"id":"e12da0ddecf28e5d","type":"inject","z":"3567e03e18126502","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":1760,"y":140,"wires":[["654acc9063136b67"]]},{"id":"654acc9063136b67","type":"change","z":"3567e03e18126502","name":"FREQ 7500","rules":[{"t":"set","p":"FREQ","pt":"flow","to":"7500","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":1920,"y":140,"wires":[[]]},{"id":"6ce46172e7f7bebf","type":"change","z":"3567e03e18126502","name":"FREQ 9999","rules":[{"t":"set","p":"FREQ","pt":"flow","to":"9999","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":1920,"y":180,"wires":[[]]},{"id":"45cb99c8060b5717","type":"inject","z":"3567e03e18126502","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":1760,"y":180,"wires":[["6ce46172e7f7bebf"]]},{"id":"5ca4917b33d96ec3","type":"change","z":"3567e03e18126502","name":"FREQ 5000","rules":[{"t":"set","p":"FREQ","pt":"flow","to":"5000","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":1920,"y":100,"wires":[[]]},{"id":"f55ae02c566cf220","type":"inject","z":"3567e03e18126502","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":1760,"y":100,"wires":[["5ca4917b33d96ec3"]]},{"id":"93f8de66b1605ca4","type":"debug","z":"3567e03e18126502","name":"counter","active":false,"tosidebar":false,"console":false,"tostatus":true,"complete":"payload.counter","targetType":"msg","statusVal":"payload","statusType":"auto","x":2160,"y":260,"wires":[]},{"id":"20f3b0edb68e3cd1","type":"inject","z":"3567e03e18126502","name":"poll at 250ms ","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"0.25","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":1730,"y":260,"wires":[["2e37e7e4caafc2d6"]]},{"id":"38268a2df2305709","type":"inject","z":"3567e03e18126502","name":"reset","props":[{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"reset","x":1760,"y":300,"wires":[["2e37e7e4caafc2d6"]]},{"id":"f4c320026c297d9b","type":"debug","z":"3567e03e18126502","name":"last amount change","active":false,"tosidebar":false,"console":false,"tostatus":true,"complete":"payload.change","targetType":"msg","statusVal":"payload","statusType":"auto","x":2190,"y":320,"wires":[]},{"id":"1b3ee499fa0f9e40","type":"debug","z":"3567e03e18126502","name":"set FREQ","active":false,"tosidebar":false,"console":false,"tostatus":true,"complete":"payload.FREQ","targetType":"msg","statusVal":"payload","statusType":"auto","x":2160,"y":200,"wires":[]},{"id":"7cb84fbf78a774d2","type":"debug","z":"3567e03e18126502","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":2170,"y":140,"wires":[]}]

Hi Steve

Thank you so much for your help.

The final value of the up-counter is taken once when a corresponding measuring time has elapsed. Filan counter value multiplied by the pulse value then corresponds to the measured mass flow in the device (in this case the DigitalTwin). The secondary purpose of the counter is simply to display a value that counts upwards. The fact that individual runs do not display the correct counter will not be noticed by the user.

It should work the way you have programmed it. I hope I will be able to program and test it with your example this week.

I am very grateful for your help,
Mark