Using Context variables

Hello everyone,

I am new to Node-Red and am trying out a project with the EmotivBCI toolbox. I am trying to get a servo running using the Arduino nodes (running Firmata). The EmotivBCI node that I am using basically returns a value between 0-100. Basically, I want the servo position stored in a variable that is initialized when I deploy the flow as 'pos=0'. I then use an if condition to increase the value of 'pos' by 1 as long as the BCI node returns a value greater than 50.

My problem is, I don't know how to initialize and store the value of the variable (for the duration of the deployment) and call it inside a function node. I noticed that the context variable does something similar, but I was not able to figure it out.

This is my current setup.

image

Any guidance would be greatly appreciated!

https://nodered.org/docs/user-guide/context

Some clues...

var pos = context.get("pos");
if(pos == null) pos = 0;

Also note - if a is greater than 50, this line while (a>50) {...} will run forever & will crash node-red.

Thanks, Steve. I tried this, but as you said, it crashed because of the while loop. Also, I'm not sure if I'm using the context variables right. Could you take a look?

And do you have any suggestions on how I might go about getting my function to work?

I split my function into two, one to calculate pos values, and another to send it to the Arduino pin.

However, I'm not sure if I'm doing it right, and because of the while loop, I can't even get there.

image

No, you are not.

I dont think the function or loop are necessary at all, but I cant cant understand what you need nor do i know what these pink nodes output.

Can you provide details (use debug nodes from the pink nodes) and a step by step expectation of your final outcome?

PS: Loops (in particular while loops) are never recommended and hardly ever required in node red as it is an event driven system.

About the pink nodes:

The important one is the third one that says 'push'. I have a slider on another app called EmotivBCI where I control the output of the Mental Commands: push node and it returns a value between 0-100.

What I want to do is control a servo motor's motion based on the slider. Basically, if the push node returns anything between 50 and 100, the pos should increment by 1 every time the node returns a value greater than 50. If I keep the slider below 50, then the function should do nothing. The pos needs to be returned to the Arduino pin which is connected to NodeRed via Firmata (I've used the debug here to see my output rather than the Arduino pin for now).

Also, I see what you mean about the while loop, and I get why it's not advisable to use it, but in this case, I can't think of an alternative. Do you think I could call msg.payload inside the while loop to check 'a' has dipped below 50 so it can safely exit the loop ?

Does the Push node send you regular updates? If so then why do you need a loop? Can't you just look at the value sent by the push node and send on the appropriate value each time?

A function node of the following will do...

var pos = context.get("pos") || 0; //get pos from context
var sendIt = false; //default to NOT sending msg on to next node
var pushValue = msg.payload;
if(pushValue > 50 && pushValue < 100) {
    pos++;
    sendIt = true;
}
context.set("pos", pos);//store pos

//check and send to next node (or not)
if(sendIt) {
    msg.payload = pos;
    return msg;
}

chrome_aCk8GYiaHC

Many thanks! It worked out. And I also understood how to set up the context variables now.
One question, am I correct in saying that the context variable will only save state inside a function, while a flow variable will save state inside the entire flow?

the (node) context is just within the node.... the flow context is available across any nodes in that editor tab, and global context is available across all tabs (the overall flow file)

1 Like

Possibly that should be
if(pushValue >= 50 && pushValue <= 100) {
It depends what was meant by between 50 and 100

It works both ways since I'm running a simulation at the moment, but the value never really goes up to 100 in real-time. But yes, to be accurate, the = sign should be there. However, my struggle was with initializing and using the context variables, which has thankfully been resolved.

How does pos ever go down again?

I basically duplicated the first set of nodes and changed the script inside to count down rather than up and of course there's another input signal to trigger this. Changed the context variable to a flow variable to communicate the same value of pos between the nodes.

Here's my set-up and the code for the reverse POS.

My final goal is to be running a 6 jointed robotic arm using NodeRed as the go-between(EmotivBCI to Arduino). So right now, I'm basically thinking of duplicating this flow 6 times for the 6 different servos on the motor. I'm not sure if that's the most efficient way to do it.

I'm a total newbie to this, so any comments for improvements, or suggestions would be most helpful.

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