[Announce] node-red-contrib-discrete-fsm

This is a set of Node-RED nodes that implements Finite State Machines (FSM).

In contrast to existing monolithic fsm nodes, each Input, Output, Condition, and State of the FSM is modeled as a discrete node in a Node-RED flow.

1 Like

That is a very interesting concept.

Are you protecting the nodes using semaphores or equivalent to make sure that race conditions do not occur?
For example, suppose two different state change input events occur consecutively, very close together, then, unless the code is protected to prevent it happening, the second input will be flowing through the nodes before the first one has completed its passage and generated an output. Perhaps that is not an issue, I am not sure.

Thanks for the question.

Typically, nodejs seems to exhibit event loop behavior and complete each message chain without pre-emption, but I don't try to exploit that behavior.

There be an issue, in some designs, with multiple inputs changing (especially feedback inputs) and possibly introducing intermediate states.

For this, there is a synchronous option where the condition nodes retain input state as inputs change, but only evaluate the expression when a "sync" topic message is received. Only one condition at a time is true, so there would be no race condition.

You use an inject node to send periodic timestamps with a "sync" topic, leaving enough time for the state machine inputs to all propagate between sync messages. This is analogous to a synchronous state machine in hardware logic design.

I still need to do more work and make an example using this feature.

Best regards

OK, I will see if I can come up with an example where race conditions could be a problem, to see if your solution fixes it.
I will have to play with it a bit more first though in order to understand the mechanism.

Great! Looking forward to anything interesting you find.

I'm also building nodes for relay ladder logic; in this case I'm looking at using timestamps in the sync messages to align the logic processing of the flow on each "frame" in order. There would be a 2 stage pipeline, where all of the inputs in one frame (same timestamp) are marshalled in the first stage, then processed on the next sync message, etc.

This might also be applicable to the fsm nodes and the setpoint (pid, etc.) controller, which can have more than one input.

I am concerned with suppressing intermediate states (logic hazards) as well as race conditions. I am thinking about actual relay ladder logic, where the logic must be designed hazard-free to begin with.

Which node is that?

I'm developing a setpoint controller node that will use the same input and output nodes (maybe with more options) and design pattern as the FSM, but much simpler to wire up, there being only one processing node.

The goal is a set of Node-RED flavored PLC functions:

  • FSM Finite State Machine (v0.0.1)
  • SPC Setpoint Controller with remote setpoint, bumpless transfer, etc.and output modes
  • RLL Relay Ladder Logic, coils and contacts (prototyping now using function nodes)
  • TDR Time Delay Relay, a set of industrial timers (subflow prototypes available now)

With consistent message semantics, it should be possible to combine elements, for example to embed timers, controllers, and state machines in ladder logic.

The high level goal is a framework for embedded industrial control systems, using microcontrollers for the wire-level interface (GPIO and serial bus) and embedded Linux for the application logic, with LWM2M over pub-sub between them.

If you are writing a PID algorithm you might like to look at my node-red-contrib-pid.

Nice, thanks. I have been researching the existing nodes for these functions and the only reason for me to do something different for PID is compatibility with the message semantics of the other components in the framework. Maybe I can just adapt your node.

The one thing missing from it is bumpless transfer, I have been meaning to add that.

The methods use to set and pass in parameters is clunky. I didn't know much about node-red when I wrote it, and features such as typed input were not available then.

The node-red-contrib-timeprop is also useful.

Bumpless transfer brings up some questions. Would you call it auto/manual instead of enable/disable, and change disabled_op to manual_op? How does the external part of the flow work.

Similar question for multiple setpoint selection. Sometimes you want to switch between a local GUI/HMI setting (still external to the node config) and a cascade mode.

It reminds me that we need a good dashboard UI control for setpoint controllers...

I realised too late that I had got the naming wrong. For backwards compatibility that will have to be considered carefully.

Sorry, not sure what you mean by that.

I had not imagined that being handled within the node, but open to suggestions.

Sorry, not sure what you mean by that.

What do I need to do to get data in and out of the custom node? Do I need to wrap the data in an object with a pre-defined key, or use a change node to add a topic, or set a message property? Do I need to filter the output to get the value to downstream nodes in the application? How many "support" nodes are needed, and what does the flow around the custom node look like?

For example, many hardware PID controllers had an external setpoint input and a local/remote switch. Should that be part of the node function, or should the user use some set of standard nodes like switch and change to accomplish it?

On my phone at the moment. The help text describes the various ways of passing in parameters.