Flow with RS flip-flop

How to realize flow with really working RS flip-flow?
I've tested redPLC SR flip-flop but I don't know how to set .S and .R inputs and how to read .Q output.

Can you provide a bit more information as I've never heard of an SR flip-flop in the Node-RED context, in particular can you explain what "RS flip-flow" and "redPLC SR flip-flop" means?

Note:
I know what an S-R Latch is in respect of logic gates.
Are you trying to model the behaviour of such a device?

Here's an example of a Node-RED flow to model the behaviour of an S-R Latch as if it was built using cross-coupled NOR gates. (i.e. Active-High logic) Modify the flow if using NAND gates.


Here's the Node-RED flow in json format so you can Import it and try it out.

[{"id":"f1f0c712c2f414f8","type":"tab","label":"SR Latch (NOR Logic)","disabled":false,"info":""},{"id":"9c0eac47ed33e06a","type":"inject","z":"f1f0c712c2f414f8","name":"Set (S=1, R=0)","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"S\":1,\"R\":0}","payloadType":"json","x":160,"y":80,"wires":[["8e54f27e3d18c002"]]},{"id":"ed4d5ec647aeed45","type":"inject","z":"f1f0c712c2f414f8","name":"Reset (S=0, R=1)","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"S\":0,\"R\":1}","payloadType":"json","x":160,"y":120,"wires":[["8e54f27e3d18c002"]]},{"id":"c17e0bc5b6bfc78a","type":"inject","z":"f1f0c712c2f414f8","name":"Hold (S=0, R=0)","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"S\":0,\"R\":0}","payloadType":"json","x":160,"y":160,"wires":[["8e54f27e3d18c002"]]},{"id":"1525a0097dc0e7fd","type":"inject","z":"f1f0c712c2f414f8","name":"Invalid (S=1, R=1)","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"S\":1,\"R\":1}","payloadType":"json","x":170,"y":200,"wires":[["8e54f27e3d18c002"]]},{"id":"8e54f27e3d18c002","type":"function","z":"f1f0c712c2f414f8","name":"SR Latch (NOR logic)","func":"// Extract S and R from msg.payload\nconst { S = 0, R = 0 } = msg.payload || {};\n\n// Get previous Q from flow context, default to 0\nlet Q = flow.get(\"Q\") ?? 0;\n\n// Apply NOR SR latch logic\nlet result = {};\n\nif (S === 1 && R === 1) {\n    result = { Q: \"Invalid\", status: \"Invalid: S=1, R=1\" };\n    node.status({ fill: \"red\", shape: \"ring\", text: result.status });\n} else if (S === 0 && R === 0) {\n    result = { Q: Q, status: `Hold Q=${Q}` };\n    node.status({ fill: \"yellow\", shape: \"dot\", text: result.status });\n} else if (S === 1 && R === 0) {\n    Q = 1;\n    result = { Q: Q, status: \"Set Q=1\" };\n    node.status({ fill: \"green\", shape: \"dot\", text: result.status });\n} else if (S === 0 && R === 1) {\n    Q = 0;\n    result = { Q: Q, status: \"Reset Q=0\" };\n    node.status({ fill: \"blue\", shape: \"dot\", text: result.status });\n}\n\n// Save Q if valid\nif (result.Q !== \"Invalid\") {\n    flow.set(\"Q\", Q);\n}\n\n// Only output if Q changed or state is Invalid\nlet lastQ = flow.get(\"lastQ\");\nif (result.Q === \"Invalid\" || result.Q !== lastQ) {\n    if (result.Q !== \"Invalid\") {\n        flow.set(\"lastQ\", result.Q);\n    }\n    msg.payload = result;\n    msg.topic = \"SR_Latch\";\n    return msg;\n} else {\n    return null;\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":430,"y":140,"wires":[["4fc0f3f1b4e20cc8"]]},{"id":"4fc0f3f1b4e20cc8","type":"debug","z":"f1f0c712c2f414f8","name":"Q Output","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":640,"y":140,"wires":[]}]

:white_check_mark: NOR Truth Table

S R Q (next) Comment
0 0 Q (prev) Hold (no change)
0 1 0 Reset
1 0 1 Set
1 1 Invalid Forbidden state
1 Like

Thank you for your replay. I've tested your flow - it's fine. But I need typical SR flip-flop this means with two separate inputs: S and R and Q output.
Node-Red SR flip-flop is available here: node-red-redplc (node) - Node-RED.
Description of the SR flip-flop node isn't clear for me. I don't know how to send input S and input R. I've tried with topic .S and .R but didn't work.

Instead of trying to use something that might not be the right fit, please explain what you are attempting to achieve. It may turn out core nodes are all you need in this instance.

If you are new to node-red, I recommend watching this playlist: Node-RED Essentials. The videos are done by the developers of node-red. They're nice & short and to the point. You will understand a whole lot more in about 1 hour. A small investment for a lot of gain.

1 Like

In Node-RED, each node has exactly one input — but that doesn’t mean you can’t receive data from multiple sources.

:white_check_mark: Ways to simulate multiple inputs into a node:

1. Use a function node with multiple wires connected to its input

  • You can wire multiple nodes into the same node (e.g., a function node).
  • All messages from those inputs will arrive on that node, one at a time.
  • You can distinguish messages by their msg.topic or custom fields (like msg.source).

The original flow I posted can be adapted to split out S and R into separate signals (wires).



Note: If required, the JavaScript inside the function can be adapted to output just a plain 0 or 1

As @Steve-Mcl said... "if you can explain what your objective is - I'm sure some Forum members may be able to give you more focused help".

Here's a "fudged" body shape for the S-R Latch.


The "fill" color for the Group can be altered to obscure the contents.

[{"id":"8c7a1a257ced701a","type":"debug","z":"f1f0c712c2f414f8","name":"The Q output port","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":910,"y":660,"wires":[]},{"id":"66460bf7f60a30d6","type":"inject","z":"f1f0c712c2f414f8","name":"Set (S=1)","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"S\":1}","payloadType":"json","x":280,"y":620,"wires":[["36680f49b4040b43"]]},{"id":"3df45654f9996689","type":"inject","z":"f1f0c712c2f414f8","name":"Reset (R=1)","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"R\":1}","payloadType":"json","x":290,"y":700,"wires":[["0833887341be3b9c"]]},{"id":"de7643f8f9556783","type":"comment","z":"f1f0c712c2f414f8","name":"A \"fudged\" body shape to make it look like an S-R Latch","info":"","x":580,"y":520,"wires":[]},{"id":"7c4d4084b4a0201a","type":"comment","z":"f1f0c712c2f414f8","name":"There are port-labels on S, R and Q","info":"","x":580,"y":560,"wires":[]},{"id":"68afd6604b566ae2","type":"group","z":"f1f0c712c2f414f8","name":"","style":{"stroke":"#000000","fill":"#7fb7df","label":true},"nodes":["36680f49b4040b43","01429639664f4dec","0833887341be3b9c","5787cd164d8cde68","88d8eb7713eac260"],"x":394,"y":579,"w":392,"h":162},{"id":"36680f49b4040b43","type":"link out","z":"f1f0c712c2f414f8","g":"68afd6604b566ae2","name":"S_in","mode":"link","links":["01429639664f4dec"],"x":435,"y":620,"wires":[],"inputLabels":["S"]},{"id":"01429639664f4dec","type":"link in","z":"f1f0c712c2f414f8","g":"68afd6604b566ae2","name":"link in 3","links":["36680f49b4040b43"],"x":505,"y":620,"wires":[["88d8eb7713eac260"]]},{"id":"0833887341be3b9c","type":"link out","z":"f1f0c712c2f414f8","g":"68afd6604b566ae2","name":"R_in","mode":"link","links":["5787cd164d8cde68"],"x":435,"y":700,"wires":[],"inputLabels":["R"]},{"id":"5787cd164d8cde68","type":"link in","z":"f1f0c712c2f414f8","g":"68afd6604b566ae2","name":"link in 5","links":["0833887341be3b9c"],"x":505,"y":700,"wires":[["88d8eb7713eac260"]]},{"id":"88d8eb7713eac260","type":"function","z":"f1f0c712c2f414f8","g":"68afd6604b566ae2","name":"SR Latch (NOR logic)","func":"// Extract S and R from msg.payload\nconst { S = 0, R = 0 } = msg.payload || {};\n\n// Get previous Q from flow context, default to 0\nlet Q = flow.get(\"Q\") ?? 0;\n\n// Apply NOR SR latch logic\nlet result = {};\n\nif (S === 1 && R === 1) {\n    result = { Q: \"Invalid\", status: \"Invalid: S=1, R=1\" };\n    node.status({ fill: \"red\", shape: \"ring\", text: result.status });\n} else if (S === 0 && R === 0) {\n    result = { Q: Q, status: `Hold Q=${Q}` };\n    node.status({ fill: \"yellow\", shape: \"dot\", text: result.status });\n} else if (S === 1 && R === 0) {\n    Q = 1;\n    result = { Q: Q, status: \"Set Q=1\" };\n    node.status({ fill: \"green\", shape: \"dot\", text: result.status });\n} else if (S === 0 && R === 1) {\n    Q = 0;\n    result = { Q: Q, status: \"Reset Q=0\" };\n    node.status({ fill: \"blue\", shape: \"dot\", text: result.status });\n}\n\n// Save Q if valid\nif (result.Q !== \"Invalid\") {\n    flow.set(\"Q\", Q);\n}\n\n// Only output if Q changed or state is Invalid\nlet lastQ = flow.get(\"lastQ\");\nif (result.Q === \"Invalid\" || result.Q !== lastQ) {\n    if (result.Q !== \"Invalid\") {\n        flow.set(\"lastQ\", result.Q);\n    }\n    msg.payload = result;\n    msg.topic = \"SR_Latch\";\n    return msg;\n} else {\n    return null;\n}","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":660,"y":660,"wires":[["8c7a1a257ced701a"]],"outputLabels":["Q"]}]

Thank you very much "dynamicdave'
a "fudged" body shape for the S-R Latch work perfectly.