Counter Function or Node for a rotary encoder/anything

838 views
Skip to first unread message

Iain MacMillan

unread,
Apr 24, 2017, 5:40:10 PM4/24/17
to Node-RED
Hi All,

I am trying to get a total count of value/distance. I have a rotary encoder that gives me a total distance since I last interrogated it in mm or whatever I set the wheel diameter to.
I have searched and searched, but it would seem most example flows and Nodes within the library are mainly interested in incrementing a value by 1 (number of clicks/visitors/tweets etc).
Could anyone help me with what I assume? would be a fairly simple custom function that would keep adding the new value to the previous, thus creating a running total/total distance.

Or perhaps point me in the right direction for search terms to study/write the code myself.

I had a look at these examples on https://www.redconnect.io/design-patterns/ but I think thats leading me down the wrong road.








Julian Knight

unread,
Apr 25, 2017, 8:27:38 AM4/25/17
to Node-RED
Well I would probably start by saving the value to a context variable.

Read the context variable or create it with a zero value if it doesn't yet exist.
Add the new value, presumably from msg.payload
Write the updated variable back to the context var.

steve rickus

unread,
Apr 25, 2017, 9:46:29 AM4/25/17
to Node-RED
A while back I posted a similar solution for a heating sensor, and I think it would work for you as well (minus the time conversions/power calculations)...

As Julian suggests, an accumulator like this will require storing the running total somewhere that it will be remembered. You can use the node's context (if this is the only logic that needs to access it), or the flow (only nodes in this flow) or global (all nodes) context. I would also set a variable in the first line that inits the conversion factor for the calculations -- not required, but it is a bit more self-documenting than embedding it in the formula. So, assuming that each msg.payload contains the number of revolutions since the last check, you can do something like this (untested):

var multiplier = 25.4; // e.g. mm/rev
var totalizer = flow.get("mmTotalDistance") || 0; // initial value


if (!isNaN(msg.payload)) {
    totalizer
+= (msg.payload * multiplier); // increment the counter
    context
.set("mmTotalDistance", totalizer); // save it back in context
}

// if you want to pass the new total along the flow, update the payload:
msg
.payload = totalizer;
return msg;

The main problem with context is that it does not persist across restarts. So a better alternative (if you need to save it) would be to send the output (new total) to an MQTT Out node, with a custom topic and the Retain message flag set to true. Wire up an MQTT In node to the same topic, to ensure that the last value published to that topic is always injected into your flow at startup, and send that "startup" value to a Change node that stores it in flow's context.

Iain MacMillan

unread,
Apr 25, 2017, 1:55:14 PM4/25/17
to Node-RED
Hi,

Julian/Steve, thanks for the replies, That has given me the info I need to know where to be headed with this now. Will update with the final solution for others.



On Monday, 24 April 2017 22:40:10 UTC+1, Iain MacMillan wrote:

Julian Knight

unread,
Apr 25, 2017, 4:18:15 PM4/25/17
to Node-RED
I fully agree with Steve that writing to MQTT with a retain is a great way to make sure the last value survives a reset - though of course, if the encoder keeps operating when Node-RED is down, the value will be wrong anyway so you might want to think about whether you really do want to retain it. An alternative would be to have a warning when it jumped obviously (if using MQTT) or if it reset if not using MQTT.

Personally, I'd also put the multiplier somewhere outside your code in case you need to change it in the future. Either in the global section of settings.js or create a temporary/manual initialisation  that writes the value to MQTT and a more permanent/automatic initialisation that reads it back on restart. This is a lot more faff it is true but I always seem to eventually regret not doing that.
Reply all
Reply to author
Forward
0 new messages