ModbusTCP - Can you give me an example of a Modbus/TCP to BACnet/IP configuration

This sample FieldServer configuration illustrates a config which reads data from a Modbus/TCP device and makes the data available as BACnet data. A remote BACnet client can read and write points.

Relationship between a connection, node and Map Descriptor for a client

The name of the connection/adapter is used to form the relationship between the connection and the node. Here the name ‘N1’ is used in common. This means that when messages are sent to the node called PLC_01 (Node Address=1) they will be sent using connection N1.

As the FieldServer processes each task (Map Descriptor) it needs to know which device or node to send the message to. The name of the Node is used to form the relationship. For example, the task to read address 40001 is defined for Node=’PLC_01’. Now the FieldServer looks for a node with the same name. When it finds it, it then known which connection to send the message on. In this example, it also finds the IP address of the node. So now it knows to send a read holding register message to the device with device address = 1 at IP Adrdess using Network connection N1.


Relationship between a connection, node and Map Descriptor for a Server

For a server, it is not necessary to form a relationship between the connection and the node. What does it mean when a node is not related to a connection? Let's say you define the same protocol on two connections (eg N1 and N2 – not all FieldServer’s have both) but you want to use the same server node to respond to messages that arrive on connection N1 or N2. By leaving the relationship between a connection and a node undefined (like this example), this becomes possible.

For a server, Map Descriptors may be thought of as server data object definitions. They must be related to a node. When a request for data from node 11 (like this example) is received, the driver must find a matching server node in the config. Once a matching node is found, the FieldServer must find a data object definition that matches the request. Thus, a relationship between the node and the Map Descriptor must be established. This is done by using a common Node_Name as illustrated by the green line.


What connects two protocols together?

The Data Arrays connect protocols. The client reads data and stores it in a data array. The server serves data, extracting it from the Data Array and serving the data using a different protocol. Some data scaling or rearrangement may be required. FieldServer provides tools to move, reorganize, do arithmetic and scale Data Array data. In this example the relationship is direct.

In this diagram the pink and purple lines show how client side data read using Modbus is served as BACnet Data.


The Client read 20 data items from register 30001 and stores the data in DA_Ana_Inputs starting at offset zero.

This means DA_Ana_Inputs[0] contains the value of register 30001.  DA_Ana_Inputs[1] contains the value of register 30002.  DA_Ana_Inputs[2] contains the value of register 30003.

The server Map Descriptor named ‘AnaInput01’ serves data extracted from the Data Array named ‘DA_Ana_Inputs’ offset 0. Thus the data it serves correlates to register 30001.

The server Map Descriptor named ‘AnaInput02’ serves data extracted from the Data Array named ‘DA_Ana_Inputs’ offset 1. Thus the data it serves correlates to register 30002.

The server Map Descriptor named ‘AnaInput03’ serves data extracted from the Data Array named ‘DA_Ana_Inputs’ offset 2. Thus the data it serves correlates to register 30003

A similar discussion applies to the other data.

If the client goes offline or the data cannot be read because of some error then the age of the data increases. At some point the data becomes too old to serve, in which case the FieldServer marks the data as unreliable.

Data Arrays

Data Arrays are used to store data. Select Data_Formats that are suitable for the data. FieldServers can store 1,8,16 and 32 bit data, signed and unsigned as well as floating point data. A few other formats such as packed_bits and packed_bytes allow binary data to be easily packed/unpacked. In addition, using special functions, data can be moved from one location to another. During the move, data formats can be changed and arithmetic can be performed.

Data arrays use FieldServer memory but the length does not affect the point count.



A value can be scaled before it is served. In this example, the value served will be 100 times smaller than the value found in the Data Array. Read the config as follows; When a value of 0-10,000 is extracted from the Data Array it will be served to the remote node as a value between 0-100.


Modbus Client

No more than once per second (Scan_Interval) read (Function=RDBC which means read continuously) 20 (Length) input registers starting at address 30001 (Address) and store the returned data in DA_Ana_Inputs[0..19]. For this protocol the Map_Descriptor_Name serves only a descriptive purpose – it is not used by the protocol.

There are three other similar tasks. Each reads a different data type and stores it in a different location.


BACnet Server

The BACnet device instance has been set to 11. (Node_ID).

12 Data objects have been defined. Each is defined by a single map descriptor. The unstated length of each map descriptor is 1 (default value for this protocol.). That means each map descriptor defines a single BACnet data object. The object type and instance numbers are defined by Data_Type and Object_ID. They do not have to be sequential.

The MapDescriptor name is used as the BACnet Object Name. When a remote client reads from this server it will find objects named ‘AnaInput01’, ‘AnaInput02’, etc...

The Virtual BACNet device will be allocated to the Local Network. (Network zero). There are methods to change this default allocation.

A parameter called ‘Relinqush_Default’ tells the driver what value to set the object to if it is not being commanded by a remote device and if it is not being read from a remote device. It is required for output types and the typical value is zero.

The function is set to server meaning that these map descriptors are capabilities as opposed to tasks. The FieldServer does no active work based on these Map Descriptors. The server side waits passively until it receives a message from a remote BACnet device. When a message is received, the Fieldserver matches it against a server side node and then against the server side map descriptors. If there is a match data can be extracted and served. If there is no match then an error response is sent.


Engineering Units are a property of a BACnet data object. You can set them to any supported unit using the ‘Units’ parameter. The manual provides a full list of units. You can see the analog data is scaled before it is served.

How to Write/Command Data

When you send a BACnet command to change the value of an object (typically an output object) then a message is sent to the FieldServer with the new value. If a matching device and object are found the Data Array is updated. Normally the data is read by the client side and shared with the server side. These two operations seem to contradict each other. Here is how it works:

1. Normally client side (Modbus) reads the data and server side serves that data.

2. BACnet Scada System sends a command to write a data object.

3. This causes the FieldServer to store the data in the Data Array location being used by the corresponding Server Map Descriptor.

4. This in turn triggers a one-off operation. Instead of reading the data from the Modbus Device, a single write to the Modbus device is performed with the new data. FieldServers call this a ‘write-though-read’. That is why we get away with having no ‘write’ map descriptors to the Modbus device but we are still able to send commands to the Modbus Device.

Lets say a remote controller sends a new setpoint to Analog Output #2. In this case the new setpoint is stored in DA_Ana_Outputs[1] (offset 1).


You can deduce that DA_Ana_Outputs[1] corresponds to Modbus register 40002. ( Basis for deduction – follow the data array name from the server map descriptor – find which client Map Descriptor uses the same Data Array. In this case it is the one called ‘Read_Holding_Regs’. Now you can see that 40001 corresponds to DA_Ana_Outputs[0] and hence 40002 corresponds DA_Ana_Outputs[1].


Now the FieldServer knows where to send the new setpoint and hence a message to set 40002 in device #1 using Modbus/TCP is sent.

Modbus and Floating Point Numbers

Modbus does not naturally have a way of transporting floating point numbers. Commonly, two 16bit integers are used to store a representation of a floating point number. Commonly the representation method is IEEE754. FieldServer has a method of doing the conversion.

The following table shows the FieldServer function moves that copy two adjacent 16-bit registers to a 32-bit floating point value:


In these examples, 32 16-bit values are combined to form 16 floating point numbers.

In the 1st example DA_SYN_REG[502] and DA_SYN_REG[503] are combined and stored in DA_SYN_ FLOAT500[0]. This is repeated 15 more times. Eg DA_SYN_REG[504] and DA_SYN_REG[505] are combined and stored in DA_SYN_FLOAT500[1].


Complete Configuration File



  1. Carlo says:

    This article seems very helpful, but I can’t read any of the images because they are too small.

  2. cpascu says:

    Sorry about that, I’ve edited the article so the pictures are now clickable. Click them to view the fullsized image. They should be a bit more readable…

Contact Us

Contact us via phone (+1 866-383-1657) or leave a detailed message below for sales, support, or any other needs

*Required Field
*Required Field
I'd like to receive the newsletter. *Check email for confirmation.
*Required Field
8:00am - 12:00pm 12:00pm - 5:00pm