Increment or decrement a value between two ranges

@davidcgu note you can edit previous posts to fixup markup - those using this forum as a mailing list won’t get the edit, but those coming to view the post in the future will. In this instance, I’ve gone back and edited the post to fixup the ``` (backticks) around your code blocks.

If your function is a direct copy and paste from your editor, then it appears you have some smart quotes wrapping the increment and decrement strings - if you look back at your post which I’ve edited, now it has syntax highlighting in place, you can see they are not recognised as strings. You need to replace the smart quotes - and with normal quotes ".

AMAZING!!!!!!! Thanks you guys for your patience, nice exercise

image

[{"id":"9606d127.d944f","type":"debug","z":"3a79879.af7b678","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":570,"y":80,"wires":[]},{"id":"1227b68f.ead989","type":"function","z":"3a79879.af7b678","name":"counter","func":"// Get the current value of the 'count' context property - default to 0\nvar count = flow.get(\"count\")||0;\n\nif (msg.topic === \"init\") {\n // set its value locally\n count = msg.payload;\n \n} else if ((msg.topic === \"increment\") && (count< 10)) {\n count++;\n} else if ((msg.topic === \"decrement\") && (count > 0)) {\n count--;\n}\n// Save the new value back to context so it will be available next time\nflow.set('count',count);\n// Update the message payload and return - no need to create a new msg\nmsg.payload = count;\nreturn msg;","outputs":1,"noerr":0,"x":380,"y":80,"wires":[["9606d127.d944f"]]},{"id":"749c878c.234b48","type":"inject","z":"3a79879.af7b678","name":"","topic":"init","payload":"7","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":130,"y":40,"wires":[["1227b68f.ead989"]]},{"id":"5905f8b1.98de18","type":"inject","z":"3a79879.af7b678","name":"","topic":"increment","payload":"","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":140,"y":80,"wires":[["1227b68f.ead989"]]},{"id":"41054bc1.6ff844","type":"inject","z":"3a79879.af7b678","name":"","topic":"decrement","payload":"","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":140,"y":120,"wires":[["1227b68f.ead989"]]}]

// Get the current value of the 'count' context property - default to 0
var count = flow.get("count")||0;

if (msg.topic === "init") {
  // set its value locally
  count = msg.payload;
  
}  else if  ((msg.topic === "increment") && (count< 10)) {
  count++;
} else if ((msg.topic === "decrement") && (count > 0)) {
  count--;
}
// Save the new value back to context so it will be available next time
flow.set('count',count);
// Update the message payload and return - no need to create a new msg
msg.payload = count;
return msg; ```

For me to finish the exercise from today (I know already there is a specific counter node) I made the function to get externally defined from topic the max and min limit and the offset (between steeps) considering it will not return any value unless it change in reference to the previous one and latest upper or lower value will be the limits (even if is not matching with the steeps defined)

[{"id":"9606d127.d944f","type":"debug","z":"3a79879.af7b678","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":590,"y":220,"wires":[]},{"id":"1227b68f.ead989","type":"function","z":"3a79879.af7b678","name":"counter","func":"// Get the current value of the 'count' context property - default to 0\nvar count = flow.get(\"count\")||0;\nvar offset = flow.get(\"offset\")||1;\nvar upperlimit = flow.get(\"upperlimit\")||10;\nvar lowerlimit = flow.get(\"lowerlimit\")||0;\nvar previous_count = flow.get(\"previous_count\")||0;\n\nif (msg.topic === \"upperlimit\") {\n // set its value locally\n upperlimit = msg.payload;\n}\n flow.set('upperlimit',upperlimit);\n\n\n\n if (msg.topic === \"lowerlimit\") {\n // set its value locally\n upperlimit = msg.payload;}\n flow.set('lowerlimit',lowerlimit);\n\n\n\nif (msg.topic === \"offset\") {\n // set its value locally\n offset = msg.payload;}\n flow.set('offset',offset);\n\n\n\nif (msg.topic === \"init\") {\n // set its value locally\n count = msg.payload;\n \n \n} else if ((msg.topic === \"increment\") && (count< upperlimit)) {\n count =(count + offset);\n} else if ((msg.topic === \"decrement\") && (count > lowerlimit)) {\n count = (count - offset);\n}\n\nif (count > upperlimit) { count = upperlimit; }\nif (count < lowerlimit) { count = lowerlimit; }\n// Save the new value back to context so it will be available next time\nflow.set('count',count);\n\n// Update the message payload and return - no need to create a new msg\nif ((count <= upperlimit) && (count >= lowerlimit) && (count != previous_count) ) {\n msg.payload = count;\n flow.set('previous_count',count);\nreturn msg;\n}\n\nelse { flow.set('previous_count',count);}\nreturn null\n","outputs":1,"noerr":0,"x":420,"y":220,"wires":[["9606d127.d944f"]]},{"id":"749c878c.234b48","type":"inject","z":"3a79879.af7b678","name":"","topic":"init","payload":"7","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":230,"y":20,"wires":[["1227b68f.ead989"]]},{"id":"5905f8b1.98de18","type":"inject","z":"3a79879.af7b678","name":"","topic":"increment","payload":"","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":120,"y":60,"wires":[["1227b68f.ead989"]]},{"id":"41054bc1.6ff844","type":"inject","z":"3a79879.af7b678","name":"","topic":"decrement","payload":"","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":120,"y":100,"wires":[["1227b68f.ead989"]]},{"id":"c2c5272f.aa9128","type":"inject","z":"3a79879.af7b678","name":"","topic":"offset","payload":"5","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":200,"wires":[["1227b68f.ead989"]]},{"id":"20b0d88b.6e82b8","type":"inject","z":"3a79879.af7b678","name":"","topic":"offset","payload":"1","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":160,"wires":[["1227b68f.ead989"]]},{"id":"a1d4d485.501828","type":"inject","z":"3a79879.af7b678","name":"","topic":"offset","payload":"7","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":240,"wires":[["1227b68f.ead989"]]},{"id":"85740ede.cc574","type":"inject","z":"3a79879.af7b678","name":"","topic":"upperlimit","payload":"20","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":400,"wires":[["1227b68f.ead989"]]},{"id":"219dbf9f.aa5b4","type":"inject","z":"3a79879.af7b678","name":"","topic":"upperlimit","payload":"30","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":440,"wires":[["1227b68f.ead989"]]},{"id":"a7373bd3.2d5fd8","type":"inject","z":"3a79879.af7b678","name":"","topic":"upperlimit","payload":"10","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":360,"wires":[["1227b68f.ead989"]]},{"id":"ae72aa3.9ab8158","type":"inject","z":"3a79879.af7b678","name":"","topic":"lowerlimit","payload":"10","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":110,"y":320,"wires":[["1227b68f.ead989"]]},{"id":"9672da7b.56de58","type":"inject","z":"3a79879.af7b678","name":"","topic":"lowerlimit","payload":"0","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":100,"y":280,"wires":[["1227b68f.ead989"]]}]

Function re-addressed with some comments to help if someone else is interested

[{"id":"1227b68f.ead989","type":"function","z":"3a79879.af7b678","name":"counter","func":"// Get the current values based on context property - set defaults is not existing\nvar count = flow.get(\"count\")||0;\nvar offset = flow.get(\"offset\")||1;\nvar upperlimit = flow.get(\"upperlimit\")||10;\nvar lowerlimit = flow.get(\"lowerlimit\")||0;\nvar previous_count = flow.get(\"previous_count\")||0;\n\n//set upper limit as per msg.topic received\n\nif (msg.topic === \"upperlimit\") {\n // set its value locally\n upperlimit = msg.payload;\n}\n\nflow.set('upperlimit',upperlimit);\n\n//set lower limit as per msg.topic received\n\n if (msg.topic === \"lowerlimit\") {\n // set its value locally\n upperlimit = msg.payload;\n \n }\n\nflow.set('lowerlimit',lowerlimit);\n\n //set offset between steps as per msg.topic received\n \nif (msg.topic === \"offset\") {\n // set its value locally\n offset = msg.payload;\n}\n \nflow.set('offset',offset);\n\n//set fixed actual count if received as per msg.topic \nif (msg.topic === \"init\") {\n // set its value locally\n count = msg.payload;\n} \n\n// increment or decrement count as per msg.topic if between limits\n \n else if ((msg.topic === \"increment\") && (count< upperlimit)) {\n count =(count + offset);\n} else if ((msg.topic === \"decrement\") && (count > lowerlimit)) {\n count = (count - offset);\n}\n// Set count to upper or lower limit if overshoot\n\nif (count > upperlimit) { count = upperlimit; }\nif (count < lowerlimit) { count = lowerlimit; }\n\n// Save the new value back to context so it will be available next time\nflow.set('count',count);\n\n// Update the message payload and return - no need to create a new msg\nif ((count <= upperlimit) && (count >= lowerlimit) && (count != previous_count) ) {\n msg.payload = count;\n// set previous_count to compare with operation in progress\n\nflow.set('previous_count',count);\nreturn msg;\n}\n\n//Return nothing if not required\nelse { flow.set('previous_count',count);}\nreturn null\n","outputs":1,"noerr":0,"x":420,"y":220,"wires":[["9606d127.d944f"]]}]

Great work above!

I have also made a flow with a single increment and decrement button, feeding into multiple counters that each control separate but coordinated motor activities, some stepping up and some stepping down (owing to servo direction), and in different increments. Think of an arm stretching out, the shoulder, elbow, wrist and hand all moving in coordination to grasp an object.

Now to figure out how to put stored data into some sort of array and feed it in at a controllable rate to produce a repetitive motion.

Maybe you can be storing data on different variables and then recall them on a function when you need, you can do flow or global set and get later on.

Will be nice if you share your project once is working :wink:

Regards