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.

Thanks in advance.
(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 new_value = parseInt(msg.payload);

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});

//msg.payload = 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);
    msg.payload = 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);
    msg.payload = 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.

Thanks in advance.

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);
    msg.payload = 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.

Thanks for the reply.

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);
    msg.payload = current_value;
    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.

Ok. (My bad)

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);
    msg.payload = 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.

Bad programming? Can't say.

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. :wink: But until then I can dream.

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