Adding the first 5 values to compute offset

Hi,

I have a load cell which a receive the value using MQQT (from my python script), then I would like to save the first 5 value coming from MQTT to compute the offset of my load cell. Then when I will have my offset, I can substract it from my msg.payload to set the load cell to 0.

I have tried to make a while loop to accumulate the first 5 value but the result is updating even if the first 5 values are gone. It looks like it applied the computation that is inside my loop even if the loop is over.

Here is the flow.

Thank you

[{"id":"a5e41128.abfc1","type":"function","z":"2260626b.09998e","name":"","func":"var offset0 = 0;\nvar i = 0;\n\n\nwhile (i < 5) {\n offset0 = parseFloat(msg.payload) + offset0;\n i = i + 1;\n}\noffset0 = offset0 / 5;\n\n\nmsg.payload = offset0;\nreturn msg;","outputs":1,"noerr":0,"x":590,"y":240,"wires":[["1746d743.04c6c9"]]}]

Couple of things. You could use a for loop rather than while which would be easier to follow and also quicker.

Secondly, you are just adding the current msg payload 5 times and then output it. I don't think that is what you meant?

If you want to accumulate the last 5 messages from an MQTT topic, you will need to store the accumulation somewhere and you will need a method of dropping the oldest value before doing the calculation otherwise your number will continue to grow, also not what you want.

So you need to store an array in a context variable. When a new msg comes in, you will need to retrieve the context variable, add the new msg's payload as a new entry to the array, drop the first entry from the array (only if the array length is >5) then write the array back to the context variable. Then loop through each entry in the array accumulating the numbers and replace the msg.payload with the final total.

Note that, to start with, you will have fewer than 5 numbers and you will have to decide if you want to process them anyway or wait until you have 5.

Also asked at the same time on Stack Overflow - https://stackoverflow.com/questions/59820595/adding-the-first-5-values-to-compute-offset

Ok thank you, I got it. I have tried to begin, here is what I have in my function node :
I saved the value inside an array, but it keeps in memory all the value from my last trials, or I'd like to empty the array at each new run of the code. So I will get the new value for my offset.

If I keep all the value, the offset will always be the same, of it changes...

Hope I have explained my toruble correctly.

var offset0 = flow.get('offset0')|| [];

offset0 += [msg.payload,];
offset0 += ",";
flow.set(["offset0"], [offset0]);

msg.payload = offset0;
return msg;

Please read the other recent thread on array's. It has the information you need. For example, you haven't written the context variable back so it will never change.

Ok thank you, where can I read that ? I am starting with node-red, trying to learn...

Thank you for this link and your help, I got what I wanted !

1 Like

So, at the end of the day all you want is to average the first five incoming values and store the result in the context ? If this is the case you could alternatively try using the batch node along with the join node. The batch node would group each 5 messages, without overlap. The join node would be configured in the reduce mode. The help information of the join node shows how to average values. If that works you would not need to use the function node with complex code.

[{"id":"95869add.add8e8","type":"tab","label":"Flow 3","disabled":false,"info":""},{"id":"34578513.102c0a","type":"batch","z":"95869add.add8e8","name":"","mode":"count","count":"5","overlap":"0","interval":10,"allowEmptySequence":false,"topics":[],"x":350,"y":240,"wires":[["191888d6.f8a5a7"]]},{"id":"191888d6.f8a5a7","type":"join","z":"95869add.add8e8","name":"Average","mode":"reduce","build":"string","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"$A+payload","reduceInit":"0","reduceInitType":"num","reduceFixup":"$A/$N","x":490,"y":240,"wires":[["5b3665cd.b82f0c"]]},{"id":"cf40d469.6e72d8","type":"inject","z":"95869add.add8e8","name":"","topic":"","payload":"1.93","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":170,"y":160,"wires":[["34578513.102c0a"]]},{"id":"42b67723.f5fc18","type":"inject","z":"95869add.add8e8","name":"","topic":"","payload":"1.94","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":170,"y":200,"wires":[["34578513.102c0a"]]},{"id":"cb97a1fa.c398f","type":"inject","z":"95869add.add8e8","name":"","topic":"","payload":"1.95","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":170,"y":240,"wires":[["34578513.102c0a"]]},{"id":"586079a3.2b7738","type":"inject","z":"95869add.add8e8","name":"","topic":"","payload":"1.96","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":170,"y":280,"wires":[["34578513.102c0a"]]},{"id":"a329c062.1979e","type":"inject","z":"95869add.add8e8","name":"","topic":"","payload":"1.88","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":170,"y":320,"wires":[["34578513.102c0a"]]},{"id":"76059e54.a743","type":"debug","z":"95869add.add8e8","name":"Average","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","x":660,"y":300,"wires":[]},{"id":"5b3665cd.b82f0c","type":"change","z":"95869add.add8e8","name":"","rules":[{"t":"set","p":"offset","pt":"global","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":660,"y":240,"wires":[["76059e54.a743"]]},{"id":"cab12b.d79baed8","type":"inject","z":"95869add.add8e8","name":"Read offset","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":170,"y":460,"wires":[["5cf7613f.c676f"]]},{"id":"5cf7613f.c676f","type":"change","z":"95869add.add8e8","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"offset","tot":"global"}],"action":"","property":"","from":"","to":"","reg":false,"x":360,"y":460,"wires":[["6a2b8243.c5041c"]]},{"id":"6a2b8243.c5041c","type":"debug","z":"95869add.add8e8","name":"offset","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","x":520,"y":460,"wires":[]}]
1 Like

The node node-red-contrib-calculate looks as if it may do exactly what you want (if that is to average a reading over five samples).

1 Like

Thank you. Not completly but at least it makes the mean of a number of point, then I need to get only one result to have my offset, but it's useful. Thanks