Modbus-TCP Read Analog IO Tutorial

This is a Node-Red example of reading Temperature from a Temco T3-8o Expansion i/o using Raspberry Pi Compute Module 3+.

In order to create or use this flow node-red-contrib-modbus must be installed.

The flow looks like this;

In order to change the values for any of the Nodes just double-click on the node.

The Inject node can be configured to retrieve the Temperature on an interval by setting the Repeat Value to ‘Interval’ and setting the duration between checks. To enable it to retrieve the value only when the Inject button (on the left) is selected - set interval to none and select either Timestamp, String or Number and leave the value empty.

The code for the first Function node is as follows;

msg.payload = {
‘fc’: 3,
‘unitid’: 254,
‘address’: 116 ,
‘quantity’: 2
return msg;

The first value is for the ModBus Flex Getter Function Code - currently supported Codes are;

  • FC 1: Read Coil Status
  • FC 2: Read Input Status
  • FC 3: Read Holding Registers
  • FC 4: Read Input Registers

The ‘unitid’ is the Address ID of the Expansion I/O - this can currently only be changed using T3000 software.

The ‘address’ is the ‘RegAddress’ of the Register that you want to retrieve. In order to view the list of Register Addresses for your device use T3000 software Tools>Register Viewer.

The ‘quantity’ is the number of values to retrieve - Also seen in the Register Viewer ‘Reg_Length’.

The next Node is the ‘Modbus Flex Getter’ - this is where the connection to the device is configured.

In order to configure the connection for your device Click on the edit icon to the right of the Server name.

  • Name is optional
  • Type can be set to TCP or Serial (I will do another tutorial on Serial)
  • Host is IP address of device
  • Port - must be set to same value as Device - can be viewed/set using T3000>Configuration
  • TCP Type - in this example Default works fine
  • Unit-ID - should be left to 1, the actually value used is set in the Function Node code
  • Timeout - default setting is 1000 (ms) - I changed this to 2000ms and deselected 'Reconnect on timeout which worked better.

The rest of the values are set to their defaults.

Next is another Function Node - the value retrieved from the device is the temperature in a 4 digit string, in order to convert it to the value with decimal point the Function simply takes that value and divides by 100.

msg.payload = (msg.values[1] / 100)
return msg;

The msg.values[1] - selects the second value in the array retrieves, this particular register has 2 values so we need to select the second value (first value would be msg.values[0].

Then finally the final debug node outputs the temperature value to the debug window of the Node-red GUI.

This flow can be downloaded from the included attachment.

modbus_read_temp.json (1.7 KB)

Hi Brent,

I’m a newbie with Node-Red but managed to read modbus values from various plc’s and a T3-BB

Do you think it’s better (speed, stability, anything else ?) to poll T3-XX through Node-Red/Bacnet or keep my present Node-Red/Modbus connection ?

Thank you

Not clear what you mean Mike but keeping things simple is always the first choice. Brent is reading an expansion IO using node-red which is running on a Pi in order to use them in the node-red environment. This will give him some interesting features but there’s a long way to go before node-red is useful in a production environment.

Hi Maurice !

I’m using Node-Red to poll registers, using the modbus contrib. I have the other option to use the bacnet contrib to obtain the same result. My question is to know which one (modbus or bacnet contrib) is more stable/faster, or just simply no differences.

Hi Mike,

To be honest I am also a newbie with Node-Red, also with both Modbus and Bacnet. I have tried both and for me I find that there seems to be more functionality in the Modbus nodes than the Bacnet nodes. Unfortunately the Bacnet nodes haven’t been updated in a while and I found there were less examples available in my searches on figuring out how to use it. I have done just one quick ‘Who-is’ example for it. That said I do plan on exploring it more - I understand Bacnet is object oriented making it easier to integrate rather than dealing with a Modbus Register List. As far as either one being stable/faster - since I haven’t done much with Bacnet I can’t really say which is faster - they seem to be similar - and I didn’t notice any stability problems with either of them. If you do try Bacnet please let me know how it goes. I will be having another try at it over the next few days and will be posting any examples I am able to get working.

1 Like

Hello Mike & Brent

I am even newer… no experience at all with these, only watched a bunch of videos and read doc and files.
My understanding is the following:
Bacnet is à object oriented building automation protocol that put the focus on high quality service.
It is thus more restrictive but more explicit because the object names reflect their class…
Modbus is a very old protocol that was is still used a lot nowadays because it is quite simple

Regarding temco controller and Module
All io and parameter can be read or write but you have to refer to a documentation to know which address can be read in which format
The numbering is not easy to remember.
Example reading VAR25 from a controller will be done with AV25 in bacnet but with MB_REGxxx in where the relationship between xxx and 25 is not so clear…
modbus numbering was developed in 16bit times… so reading 32 or 64 bit values is changing the numbering too…

From what I have read from T3000 Modbus address excel file, all parameter have a modbus address while only DI, DO, AI, AO,VAR have a bacnet address in the Temco world

bacnet also manage more complex objects like schedule,alarms, trends but I don’t think that T3 controller follow the Bacnet standard for theses objects
@maurice could you please confirm that my understanding is good?

Well put Pierre, anyone contemplating integration work will do well to consider going with Bacnet rather than Modbus. There’s about 1500 Modbus registers to keep track of with the T3-BB series for example. The lowly Tstat8 zone controller has some 500 Modbus registers.

In the Bacnet world its much easier to refer to AI1 and BO2, etc. which are all well supported in our controllers. There are a few Bacnet objects we’re missing like you say: trendlogs and alarms, but we do support Bacnet schedules and calendars.

Please note that the msg.values[1] technique value will only work if msg.values[0]=0 . Which might be fine if your numbers are in centigrade.

I am not an expert, but for higher values, you will need to handle both register and value from Modbus, especially if you are dealing with Fahrenheit values. I googled around and found this, which seems to work.

// Create new Buffer based on array bytes
const buf = Buffer.from(msg.responseBuffer.buffer);
// Represent these bytes as 32-bit unsigned int
const value = buf.readUInt32BE();
// save the value
msg.payload = value/1000;
return msg;

I’ve been messing with Node-Red for a few weeks or so to mainly get around the absence of email functionality in the T3’s.
Here is a snap of one of my flows;
Starting on the left, what this is doing is querying a T3 controller for the value of 25 inputs at once, parsing that data, splitting it back into single values. Then I can run some logic on the Alarm values. I.E, Temp is Too Warm or Too Cold, Sensor is Open or Sensor is Shorted. Then on the far right after a delay it will Email Whomever the Alarm Info I.E. “Case Temperature for A1a is Too Warm at 45 °F”.
This flow does not have it but I’ve also got all these value being written to an SQL DB, that I have displayed on the User Interface.

The email alarm todo item is way past overdue Mike, Chelsea willbe putting some time into it this week. NonSSL is working so we’ll push that out quickly. It’s the SSL encryption that has been holding us up. it chews up a lot of resources.

Not sure if node-red can do block reads & writes but you can consider using those to speed up the communications.

1 Like