How to Use Node-Red with Modbus

Modbus is a de facto standard, truly open and the most widely used network protocol in the industrial manufacturing environment.-ref Modbus Faqs

Because of its popularity there is a growing requirement for reading data and controlling Modbus devices over TCP/IP networks using node-red.



In this tutorial we are going to cover.

Node-red Modbus Nodes

There are a collection of modbus nodes available for node-red which you will need to install.

Go the the menu and select manage Pallete and search for the node-red-contrib-modbus package.

modbus-nodes-install

There are 11 nodes in the package and they are grouped together in the Modbus section.modbus-nodes

The nodes that we are mainly interested in are the read and write nodes.

Modbus Server Configuration

The modus getter and write nodes all require that you configure a server to connect to.

The settings fro this server are store in the server configuration and are available to all nodes in the workspace.

For a TCP/IP server you will need to configure the IP address and the port number. The default modbus server port is 502.

The settings page is shown below:

modbus-server-settings

The important settings are IP address,port, TCP type and unit id.

You can also access this tab from the configuration nodes menu.

configuration-nodes

Node status

The getter and write nodes display the server status under the node as shown below:

node-status

You can see that the green active staus means that we are connected to the modbus server.

As you read or write data you will see the status change.

The status is also available to the status node and you can use the status in your flow to ensure successful read and write. See Using the status node for flow control

Sleeping Nodes

Although the status node can be useful it doesn’t detect what I call sleeping nodes.

When using the getter or write nodes you will notice that if there is long delay between reading or writing (about 2mins) the node appears to go to sleep.

This means that a read or write attempt fails and the node reinitializes. Once it has reinitialized you can then read or write normally.

Unfortunately the node doesn’t send any error messages on any outputs so it isn’t easy to detect.

The solution I’ve used in my flows is the send the read signal in two paths and check which one gets received. To work it relies on the fact that each message has an ID and we can check this id.

Here is the flow

modbus-detect-fail

A normal read/write the function node sees the msg coming first from path1 and so it knows it is ok.

The message should also come in from path 2 and this is used to reset the function node.

However in a failed read/write the function node sees the msg from path 2 but none form path1 and so it knows it has failed and triggers another read.

Modbus Read Nodes

These are the modbus getter and modbus flex getter. Both can be used for reading data using Modbus TCP/IP,TCP RTU and also serial .

The read mode is configured in the server properties shown below:

modbus-server-properties

The modbus getter node has all of the configuration done in the node itself and is used when doing a fixed read.

The modbus flex getter expects you to pass the configuration data in from a preceding node and is recommended when you are doing multiple reads of different values.

modbus-red nodes

The nodes support function codes 1,2,3 and 4 as shown below:

modbus-read-function-codes

Both nodes have two outputs which are essentially the same. I tend to use output 2.

If you pass the output to a debug node and display the complete msg object you will see that you get an output like the one shown below.

modbus-read-output

The node assumes that the register contains a 16 bit integer and if that is the case then you can use the value field to get the data. If the data represents a float or 32 bit integer you will need to use the buffer.

The syntax is msg.values and msg.payload.buffer

The video below gives a quick overview of the nodes and also read examples using both the modbus getter and modbus flex getter nodes.

Modbus Read Register Examples

All of the examples use a flow like that shown below:

modbus-read-flow-1

The function code is used to create the read command and the code will be similar to the code below:

var fc=3;
var sa=0;
var addresses=2;
//var slave_ip=msg.payload.slave_ip;
//msg.slave_ip="192.168.1.31";
msg.payload={value: msg.payload, 'fc': fc, 'unitid': 1, 'address': sa , 'quantity': addresses };
return msg;

The function code, start address(sa) and the number of address will vary.

The inject node is used just to trigger the flow.

The process function node connected to output 2 extracts the data from the modbus server response and the code shown below in the example should be placed there.

As mentioned earlier if you have 16 bit integers in the registers then they are available in the values field and you don’t need to do anything to extract the value.

However if the resisters contain other data types then you will need to work with the buffer object.

Both getter nodes return the data in the msg.payload.buffer field.

The following examples show how to extract a 16 bit integer,a 32 bit integer and a 32bit float from the buffer.

Read 16 Bit Integer

Below is the code from a function code that reads a value of 16 bit Integer buffer. It sends to a modbus server using fc =3 and reads 1 address

 

const buf= Buffer.from(msg.payload.buffer)
//const buf = Buffer.from(msg.payload.buffer);
const value = buf.readUInt16BE();
msg.value = value;
return msg;

Read 32 Bit Integer

Below is the code from a function code that reads a value of 32 bit Integer buffer. It sends to a modbus server using using fc =3 and reads 2 addresses.

const buf = Buffer.from(msg.payload.buffer);
const value = buf.readUInt32BE();
msg.value = value;
return msg;

Read 32 Bit Float

Below is the code from a function code that reads a value of 32 bit Integer buffer. It sends to a modbus server using using fc =3 and reads 2 addresses.

const buf = Buffer.from(msg.payload.buffer);
const value = buf.readFloatBE();
msg.value = value;
return msg;

You should note that BE (big Endian) is the normal but if your data is in Little Endian format use LE instead of BE.

This is covered in the first three minutes of Node-red Modbus video2

Reading Coil Example

To read coils we change the function code to 1. The number to read should be divisible by 8. If you ask it to read 6 it will actually show you 8.

The return value contains the coil data as true and false. The command fc=1 sa=0 and addresses= 6 returns the following:

modbus-read-coils

To extract the first coil reading I would use msg.values[0].

Signed and Unsigned

All of the examples given above use signed integers. If you need to write signed use readUInt16BE() and readUInt32BE().

BE and LE

All of the examples above use BE format. If you need LE format replace BE with LE.

I.e readUInt16BE() becomes readUInt16LE() etc

See Working with Buffers in Node-red for more details.

Writing data ———>

Resources

Flow for video1

download

Related Tutorials

Click to rate this post!
[Total: 1 Average: 5]