Best practice to create infinite loop

Hi,
I want to run a js function forever, but it seems that nodered crashes after some loop if I add a "while" in the node.

var increment = 0;
function Looper() {
       increment = increment +1;
       console.log("i'm running"+increment);
       return increment
}


while(true)
  {
    msg = { payload: Looper() }
    node.send(msg);   
}

FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
get those row in console outpus then it stop and need to restart nodered:

feb 17 15:55:24 Node-RED[1484]: i'm running2546
feb 17 15:55:24 Node-RED[1484]: i'm running2547
feb 17 15:55:24 Node-RED[1484]: i'm running2548
feb 17 15:55:24 Node-RED[1484]: i'm running2549
feb 17 15:55:24 Node-RED[1484]: i'm running2550
feb 17 15:55:24 Node-RED[1484]: i'm running2551
feb 17 15:55:24 Node-RED[1484]: i'm running2552
feb 17 15:55:24 Node-RED[1484]: i'm running2553
feb 17 15:55:24 Node-RED[1484]: i'm running2554
feb 17 15:55:24 Node-RED[1484]: i'm running2555

FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory

Am I doing a wrong approach?
Thank you, BR

Hi,

yes, this will be the wrong approach.

Node.js is single threaded. If you create an infinite loop, then you essentially prevent the whole node-red runtime from doing anything.

What do you want to do with the loop? If you want to trigger something at regular intervals, you can use the Inject node.

Thanks for the reply and informations, I need to send to GPIO a PWM output, that should run forever with a increment/decrement, based on the value a user input from the dashboard.

I get the value from the ui in the function node with "global.get()" so the last thing to do is understand how to make the loop run forever.

Every advice is really appreciated

The pi-gpio nodes support PWM output - you just send it the value you want it to use, and it takes care of the rest.

That's probably a better choice than trying to drive PWM manually in the flow.

Thank you, I'm already using it, but my problem is beyond, it's the genereator of the values that should run forever, in my example it is the Looper() function, it return the msg to GPIO only when needed.
But the looper should continue to calculate increment/decrement.
Is there any way to keep a background task running?

node-red is event based. Is there a condition you can identify to run your code? I dont understand (from your example code) why you need to continuously loop.

No condition, just need an infinite loop, like arduino loop() does.

But thats the thing, arduino needs a loop as it is not event driven. node-red is event driven & as Nick already pointed out (and as you have already witnessed) you will cause issues with a continuous loop.

You need to approach this from a different mindset. Event driven. Use the various nodes and events that occur to do your work as they occur, not in a loop.

So again, why you need to continuously loop? If you can answer that, we might be able to see the pattern you are trying to achieve and suggest a solution (or not)?

Imagine to control a LED by the GPIO PWM output, the LED should turn on gradually, then turn off gradually, the ui dashboard will allow to control the time of the transition.
But the transition on/off should always run, even if no one is looking at dashboard.

So a user would set a brightness, then the LED would change (smoothly) to the set brightness - correct?

No the user would control the time for transition to on and off.
It's like a semaphore, the user control the time needed for the ligth to change.

getting there.

So the user adjusts a time value that dictates how long an LED transistions from OFF-->ON and ON --> OFF

Does this ON/OFF/ON/OFF/ON... continue forever (based on the transision time entered by the user)?

That's it, and it should continue on forever.

The result is a street semaphore, but the concept is that a Looper function in node-red isn't a good choice.
Sorry for the trouble, thank you for the time, I'll look to other solutions.

ok, go ya.

So, as nick pointed out before, the node-red-node-pi-gpiod node can take care of this for you. Reading the readme for that node it states...

In servo mode you can also preset the minimum and maximum pulse times as required by your servo in order to reach its full range. Minimum of 5mS, maximum of 25 mS - defaults to 10 and 20 mS respectively.

So this is how I would approach it...
Assuming a default transition time of 100ms - this means you sent (alternatively) 0 brightness and 100 brightness every 0.1s with the pulse time set accordingly.

If the user changes the time, you adjust the time between sending the brightness and the pulse time.

This can be achieved with the trigger node
image

a separate flow can prepare the servoParams stored in flow context & if the user enters a change of rate, update this memory based context value & send a new calculated value to msg.delay to change the rate.

something like this...
image

This is one event based approach.


But, TBH, this might be better as a separate process (e.g. a python app) that you simply send a rate of change value to it & it just does its thing.

I am still not absolutely sure I get it. Do you mean the LED should cycle on/off/on for ever, with a user defined rate of increase and decrease of brightness?
Edit
Just to clarify further, the brightness is controlled by PWM so what you are trying to generate is a triangular wave with an adjustable ramp rate.

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