Node for multiple outputs based on single input

Could anyone recommend a node for controlling a fan based on a numeric range please?

The incoming number is from an air quality sensor, the output is a hepa filter fan.

I'd like to ensure there's not a "bouncing" effect, i.e.:
Sensor detects >500, turns fan to LOW, sensor drops to <500, fan goes OFF, sensor detects >500.......and so on...

So I think a switch might be problematic.

I'll also make it so if the LWT is offline, the fan runs at LOW speed, in case the sensor fails.

node-red-contrib-hysteresis should do what you want.
Or you can easily achieve the same thing in a function node.

For this insert a Switch node that only passes the message if Offline, then a Change node that sets the fan speed to low and then feed that to the fan.

1 Like

I did think of the word hysteresis but wasn’t sure it was the correct term, thanks for the link to the node.

I’m very interested in the function node code,
I can understand filtering for the range but not sure how it could handle the hysteresis type issue.

Looking more carefully I see you want three threshold values, so you would have to use three hysteresis nodes.
Here is a flow using a function node for one threshold. You could use three of those, or extend the code to include all three thresholds.

[{"id":"7ca3a3f733af8bae","type":"inject","z":"bdd7be38.d3b55","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"500","payloadType":"num","x":250,"y":3060,"wires":[["f43ec61481b0dd4c"]]},{"id":"550f755c18868c32","type":"inject","z":"bdd7be38.d3b55","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"501","payloadType":"num","x":250,"y":3020,"wires":[["f43ec61481b0dd4c"]]},{"id":"7719a3e86fce4df3","type":"inject","z":"bdd7be38.d3b55","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"499","payloadType":"num","x":250,"y":3100,"wires":[["f43ec61481b0dd4c"]]},{"id":"d0c8377bc31bb4df","type":"inject","z":"bdd7be38.d3b55","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"498","payloadType":"num","x":250,"y":3140,"wires":[["f43ec61481b0dd4c"]]},{"id":"f43ec61481b0dd4c","type":"function","z":"bdd7be38.d3b55","name":"Hysteresis 499:501","func":"// switch value\nconst setpoint = 500\n// hysteresis to apply around that value \nconst hyst = 2 // output will switch at 499 and 501\n// values to output when msg.payload is above/below setpoint\nconst highOutput = \"LOW\"\nconst lowOutput = \"OFF\"\n// get lastoutput value\nlet lastOutput = context.get(\"lastOutput\") ?? highOutput // default to highOutput the first time through\nlet newOutput\nif (msg.payload >= setpoint + hyst/2) {\n    // above threshhold\n    newOutput = highOutput\n} else if (msg.payload <= setpoint - hyst/2) {\n    newOutput = lowOutput\n} else {\n    // within hysteresis band, keep output at the last value\n    newOutput = lastOutput\n}\n// save the new output value\ncontext.set(\"lastOutput\", newOutput)\nmsg.payload = newOutput\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":480,"y":3080,"wires":[["932a6dfdcfcd6ebf"]]},{"id":"932a6dfdcfcd6ebf","type":"debug","z":"bdd7be38.d3b55","name":"debug 100","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":720,"y":3080,"wires":[]},{"id":"d70a158ce238f366","type":"inject","z":"bdd7be38.d3b55","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"502","payloadType":"num","x":250,"y":2980,"wires":[["f43ec61481b0dd4c"]]},{"id":"264da1332312f2fb","type":"inject","z":"bdd7be38.d3b55","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"497","payloadType":"num","x":250,"y":3180,"wires":[["f43ec61481b0dd4c"]]}]
1 Like

Working on PWM controlled TRV-valves and -ventilationFans. Temp & hum are collected via MQTT or Zigbee, and handled with function node to convert into 0-10 or 0-255. This goes to a filter node that only outputs RBE on changes, and payload to MQTT/Zigbee out.
For non-Zigbee, the (remote) fan is controlled by a ESP32 + PLC-LM358-PWM2V PWM to Voltage (0-10V).
For Zigbee, the PWM is messaged to a Zigbee-bridge, that controls the TRV/Fan
For this config i expect no hystereris-node or ranges needed.
As the sensor-reading is approaching the target, fans will slow down and TRVs gradually will close. For TRV... the CV/pump need to go OFF before reaching end point.
Cheers,
T