# Node maths help with two values

I seem to really be suffering today with thinking.

What I want to do in a `function` node:
Get a context variable. (Say: `value1`)
`msg.payload` is the second variable. (`value2`)

Say they are both between `1` and `10`.

Get the difference. There is no which is bigger than the other.
Loop the difference number of times sending the numbers and send that value as `payload`.

Eg 1:

Value1 = 2
Value2 = 8

output:
2, 3, 4, 5, 6, 7, 8

Eg 2:

Value 1 = 9
Value 2 = 5

output:
9, 8, 7, 6, 5

I'm stuck on how to get the `value1`-`value2` to be an `+` number.
Brain failure.

(Trying in the mean time)

Math.abs

``````var posNo = Math.abs(5 - 10) // == 5
``````
1 Like

It is stupid of me as I have actually been down this path before I have since found/seen.

But thanks Steve.

1 Like

(If someone could......)

Ok, I have the maths right - I think.
Had me going in circles for a good while.

It seems to work as expected. But I wanted to add a bit more polish to the functions and so I want to control the speed of the output.

Look at the code for the `function` node.
Given the incoming message is a valid value and all the contexts are set....

Why isn't `flow.DELAY` slowing down the output?

I had it fixed at 300 - the commented line - but wanted to allow external adjustment of the value.
Thus the line above. But I am not sure it works as expected.
Yes, I am sure I have asked this before. I have forgotten. I am not using this in every day use. So: it happens.

``````//  Get the values
var current_value = flow.get("ALL_BULB_BRIGHTNESS") || 0;

var time_delay = flow.get("DELAY") || 300;
//var time_delay = 300;

var x = 0;
var y = 0;

var difference = Math.abs(current_value - new_value);

node.status({text:difference});

if (new_value < current_value)
{
//
//node.warn("DOWN");
fd(new_value,current_value,time_delay);
} else
{
//
//node.warn("UP");
fu(new_value,current_value,time_delay);
}

//node.warn("EXITING");

return;
///////////////////

function fu(x,y,z) {
y += 1;
//    node.warn("x " + x);
//    node.warn("y " + y);
node.send(msg);
if(y < x){
setTimeout( fu, z, x, y );
}
}

function fd(x,y,z) {
y -= 1;
//    node.warn("new value - x " + x);
//    node.warn("exiting value - y " + y);
node.send(msg);
if(x < y){
setTimeout( fd, z, x, y );
}
}
``````

Walk through:
A `flow` variable holds the `ALL_BULB_BRIGHTNESS` value.
A payload comes in with a new value.
It calculates the difference and steps between the current value and the new value.
That is done by the `fu` and `fd` functions at the speed determined by the flow context: `DELAY`.

So, I am missing something, as it doesn't seem to make a difference me adjusting the flow context to like..... 1000.

If someone could have a look and tell me where I am missing the knowledge needed.

``````function fu(x,y,z) {
...
}

...

setTimeout( fu, z, x, y );
``````

It would help if you gave the arguments more meaningful names, but the issue is this: The `fu` and `fd` function take three arguments, `x`, `y`, and `z`. It looks like `z` is meant to be the desired time delay.

When you call `setTimeout`, you give it the function to call, `fu` in the example above, the time delay to use, `z`, and then the arguments to pass to `fu` when it gets called... `x, y`.... but your `fu` function expects three arguments - `x, y, z`.

This means the second time the function is called, the `z` parameter is not defined so the timeout doesn't have a valid delay value.

You need to change the two `setTimeout` lines to be:

``````setTimeout( fu, z, x, y, z );

setTimeout( fd, z, x, y, z );
``````
1 Like

Ok.

I know what I am doing is going to be said as wrong. But it is all I can .... do.

I had the basic function working with:

``````let x = msg.payload;
let y = 0;

function f(x,y) {
y += 1;
//    node.warn(y);
node.send(msg);
if(y < x){
setTimeout( f, 1000, x, y );
}
}

f(x,y);
``````

It is very basic. But I sat down and sort of worked how it works.

I wasn't helped by this not working in either direction depending which is the bigger value.
So I had to duplicate it to u for up and d for down.
Then change the `+=` to `-=` for the down.
And there was all the fun of the `if (y<x){` line too.

So as given, the `setTimeout(` line only has the `( f, 1000,x,y );`

I wasn't wanting to get too excited with the names there as they worked as were.
I did do a better job with the names given to the bigger part of the code.

I am failing to see how you worked out how the extra `z` is needed in the `setTimeout` lines.
Because to the best of my use, the block of code works. But knowing my luck it won't.

Ok. So, stepping back.... Do I need to add the extra `1000` to the `setTimeout` line in the second block of code also? (I'm guessing it will be a `yes` reply.) I just want to check.

Given the line, `setTimeout( fu, z, x, y );`, you are asking the code to do:

After `z` millisecs, call `fu(x,y)`

But the function now expects three arguments, so you want it to do:

After `z` millisecs, call `fu(x,y,z)`

Which translates to `setTimeout( fu, z, x, y, z);`

But, as you suggest, stepping back, I can't see any reason to bother with the `z` argument at all. You have the delay defined in the variable `time_delay` - so you can just use that directly.

``````setTimeout( fu, time_delay, x, y );
``````

Why the `z` (ok, can't compound styles)

I (again) don't know if it is good/bad or indifferent that I did that.

When messing around with Arduino code and you call a function I get that external variables are visible in there, but it is ...... good practice (?) to call a function with variables and then in the function have them as locals.

Ok, another angle:

`fd(x,y)` The most basic.

That is the definition of the function - yes?

It is actually called with:

`fd(new_value,current_value);`

Earlier in the code.

So, taking what you say - and this is just talking - to the next level:

Why wouldn't (couldn't?) I just `fd()`?
Then in the `fd` part it would be:

``````    current_value -= 1;
//    node.warn("new value - x " + x);
//    node.warn("exiting value - y " + y);
node.send(msg);
if(new_value < current_value){
setTimeout( fd, z, new_value, current_value );
}
``````

(Ok, I did mess it up a bit.....) But can you see where/how I am confused?

That function (`fd` in this case) has a world of its own variables and so I thought to be in keeping with how things are done, that the time_delay should be done in the same way.

I do get that `time_delay` could be used as you showed. I guess I am in a bit of a rut and may be sticking to detaching variables from themselves in routines/functions.

Good, bad? I don't know and would like to learn. But I don't have any .... mentors at hand.
So I just go with what is at the particular time of writing, and hope that one way prevails, or gets established as the better way.

Again: Thanks. I did what you said and it does work. (Like it wouldn't). (Sorry. Toung in cheek there. Just to clarify.)

I think I have attacked this long enough for today (well: now speaking it is yesterday) and may need to get some down time.

In closing: So I do need to add the extra `1000` in the original block of code at the end of the `setTimeout` line?

I don't understand what you mean by that. It could be interpreted in lots of different ways and if I just answered "yes" or "no", I'm not clear what code changes you'd make.

I have a working (well, now unsure) block that is:

``````let x = msg.payload;
let y = 0;

function f(x,y) {
y += 1;
//    node.warn(y);
node.send(msg);
if(y < x){
setTimeout( f, 1000, x, y );
}
}

f(x,y);

``````

Should the line be:

` setTimeout( f, 1000, x, y, 1000 );` in light of what you said?

(I'll try to get in quickly. before you reply again.)

Again, going on what I know, the function part is not seen by the code and it is the last line:

`f(x,y)` which is parsed and calls the function defined above.

But the function is shown in the middle of the .... code.

Clearer?

In this latest code, your function `f` takes two arguments - `x` and `y`.

The line `setTimeout(f,1000,x,y)` translates to:

After 1000ms, call `f(x,y)`

If you change it to `setTimeout(f,1000,x,y,1000)` then it translates to:

Afer 1000ms, call `f(x,y,1000)`

But your function only expects two arguments, so adding the extra `1000` does absolutely nothing useful and would be pointless.

1 Like

Bingo!

Sorry. Yeah. Eureka!

Fell into place now.

I think time for bed.

Thanks again. Maybe one day I will be able to write code. But until then I can dream.

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