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.


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:


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

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


Node status

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


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


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:


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:


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.


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:


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.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:


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 ———>


Flow for video1


Related Tutorials

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


  1. Hey Steve,

    I am getting a puzzling result when trying to read a 32 bit floating register which I know exists (I have successfully read it with other hosts). Node-Red posts the error “Modbus exception 2: Illegal data address (register not supported by device)”. If I am 100% certain that the register exists, what else could be causing this? I am subtracting 1 from the address as I had done to successfully read unsigned 16 bit integers (base 0 vs base 1), but that has not helped. Any ideas?

    1. Not really except that the error implies a faulty address so I would just try reading a slightly different address . It is not important at that stage what data you get as long as you don’t get the error.
      If you still have problems send me the relevant bit of the flow and I’ll take a look

      1. I’m sorry, I wasn’t very clear on my question. I managed to make the correct communication between the software I’m using, OpenPLC, and Node-red. But I can’t read the data correctly. I have a value that changes from 0 to 100, float, to simulate a temperature sensor. However, when reading node-red presents values ​​between 16500 and 17100. I thought it was something related to the amount of bytes, however when I use the example here on the site for float cases or for integers with 32bytes the program shows the error: “RangeError [ ERR_BUFFER_OUT_OF_BOUNDS]: Attempt to access memory outside buffer bounds”. Thanks a lot for the help!

  2. Thanks !
    Do you think it’s possible to change ip adress and port without edition of node ?
    I have à php local website with an input form wich transmit the ip and port into mysql. I want yo use thoses into the node’s configuration.

      1. Thanks for reply but getter and setter need a “serveur” wich need an IP adress.
        By using : var slave_ip=msg.payload.slave_ip; msg.slave_ip=”″; what to i have to complete into the adress and port of Server’s getter node parameter ?
        I need to read multiple 32bit double intergers and put them into a mysql database.
        In this database, there is the IP and port of Modbus TCP slaves i need to communicate with.

        Thanks for your help.

        1. Hi
          Have you seen the videos I did on reading 32bit floats and integers. They also come with a flow which you might find useful.

          1. Yes, i’ve seen the video and tried to use your “modbus-video2-flow” but when i modify the “32bit INT function” replacing the ip adress by one of my slave modbus device (Schneider M221) msg.slave_ip=”″ -> msg.slave_ip=”″; it dosn’t change anything. Local getter is not connected. I need to change also the adress into Modbus-Getter-node -> Server -> host / what I would like not to have to do because the address can change (coming from mysql)
            And when the Server is in manually, it’s OK, but the Value is not good.
            In my Schneider PLC, i have %MD0 = 111111 but 2986803201 in node-red. Thanks a lot

          2. So changing the ip address has no effect? You want a different ip address in the getter node is that correct. How many addresses are you looking at?

          3. Yes it’s correct, i want to change IP address because it’ not fixed, the target is defined by the user of the system, by a formular in PHP stored in MySQL database.
            To begin i tried to change it into the function node : msg.slave_ip=”″
            The host parameter into Server into the Getter node was configured in
            It doesn’t work, then i change the host parameter into and it’s OK. If i change the IP address in your function code, it’s doesn’t change anything.
            I don’t understand how can the msg.slave_ip can replace the host ip address of the server.

            var function_code=3;
            var start_address=0;
            var register_qty=2;
            var slave_ip=msg.payload.slave_ip;
            msg.payload={value: msg.payload, ‘fc’: function_code, ‘unitid’: 1, ‘address’: start_address , ‘quantity’: register_qty};
            return msg;

          4. I think that the slave ip address is when the modbus server you are connected to has slave nodes.
            How many modbus servers are you connecting to?

          5. I use Modbus getter to read 2 slaves devices with ip adresses controlled by a web server and mysql. The server is a Raspberry pi with node red, Apache, PHP, MySQL, the slaves are PLC and Wireless gareway in Modbus TCP with modifiable IP address

          6. Each user have its own network architecture and don’t want to install a router

          7. Can you use the ask steve page and contact me and then send me a diagram of your setup as I’m not quite sure I understand it.

  3. Hi Steve,
    I am trying to read 208 addresses but the mobus node only allows me to read 125 address quantity. How I can to read the 208 addresses with node red? Thanks and regards.

    1. You will need to do two reads and hold the first read and add the second read to it if you app needs the 208 reads in one go. Does that make sense?

      1. Hi Steve,
        thanks for the answer. Why is the address quantity limited to 125? Is it possible change it or is it by protocol? Thanks and regards.

    1. Hi
      This is what I got back
      In the settings, you can choose Serial Expert, then set the port you are communicating with. Set the Serial type to RTU, with the correct baud rate etc. Each device will get its own Unit ID. Set timeout around 2 seconds.

  4. Hi Steve,

    I’m trying to read a register from a CAT (EMCP 3.2) via serial. I can read many registers just fine, but i’m trying to figure out how read certain bits of a particular register. As shown in the manual, the register is defined as:

    335 – 1 REGISTER (2 BYTES) LONG – READ
    Bits 15:4 UNUSED
    Bits 3:2 Amber Lamp Status: Bits 00 = off, 01 = on
    Bits 1:0 Red Lamp Status: Bits 00 = off, 01 = on

    I’m not sure how to extract the relevant bits?

    1. I will take a look and send you the function code via email. Go to the ask steve page and contact me so I can send the email.

  5. Steve can you point me in the right direction on this. The use of big endian and word swapping has me prepelxed as to how to decode this.

    Reading these registers requires that the address be in the range of 16 to 22 (0x10 and 0x16).
    Also, the address must be evenly divisible by 2. In other words, only address 0x10, 0x12, 0x14
    and 0x16 are valid. Each value is returned as two registers in IEEE 754 floating point format. The
    four data bytes are treated as two individual big endian 16-bit words with the least significant word
    being sent first. In other words, the 32 bit floating point number represented as ABCD is sent as

  6. Thanks for this blog, information is pretty thin on the ground.
    Do you have an example of config for a modbus rtu connction please?
    I have python code that works, but I do not know how to convert that into something that works in node red.
    I can always use the code as a fall back, but I’d prefer not to.
    Any help would be much appreciated.

    1. Hi
      No never done it. However if you let me know a bit more about it I will run it past someone who does that a lot and see if they can help.

  7. halo steve
    ‘ve learned over time, that the more modbus data I read, the more RAM memory it uses, and it’s very systemic. is there anything I can do with the problem?

      1. I use 2Gb Ram, every time I observe, there is always an increase in memory when I add a modbus node. and can exceed up to 80%, resulting in slow performance. I am using armbian Linux.
        Is it possible that the nodes are always read and never deleted, thus making the memory full?

  8. Hi Steve,

    Do you experience working with TCP clients for a longer period of time? I have an example where I am reading a TCP modbus client (not on my local network) with 3 modbus read nodes. It works great for a few hours, and after that it just stops working. The Modbus Queue Info node shows that it has thousands of messages in the queue, and the client does not get queries. I am trying to send in a resetQueue, but nothing happens. Nothing works other than re-deploying the flow.

    1. Hi
      Do you have a long delay between reads as I’ve noticed that it seems to loose the connection after a few minutes of inactivity. Sending a read request resets it.

Leave a Reply

Your email address will not be published. Required fields are marked *