3.1 Modbus Map [T-Series Datasheet]
Modbus Map Tool
The filter and search tool above displays information about the Modbus registers of T-series devices.
Name: The string name that can be used with the LJM library to access each register.
Address: The starting address of each register, which can be used through LJM or with direct Modbus.
Details: A quick description of the register.
Type: Specifies the datatype, which specifies how many registers each value uses.
Access: Each register is readable, writable, or both.
Tags: Used to associate registers with particular functionality. Useful for filtering.
For the U3, U6 and UE9, see the deprecated Modbus system called UD Modbus.
For a printer-friendly version, see the printable Modbus map.
Usage
T-series devices are controlled by reading or writing Modbus registers as described on the Communication page.
Protocol
Modbus TCP is described further on the Protocol Details page.
Address Mapping
T-series devices have a single map of addresses from 0 to 65535. Any type of register can be located anywhere in that address range, regardless of the data type or whether it is read-only, write-only, or read-write.
Some addresses point to buffers that can access more data than what would normally fit within the Modbus address range. See Buffer Registers.
Sequential Addresses
Many registers are sequentially addressed. The Modbus Map gives you the starting address for the first register, and then—depending on whether the data type is 16-bits or 32-bits—you increment the address by 1 or 2 to get the next value:
Address = StartingAddress + 1*Channel#
(UINT16)
Address = StartingAddress + 2*Channel#
(UINT32, INT32, FLOAT32)
Note that the term "register" is used 2 different ways throughout documentation:
A "register" is a location that has a value you might want to read or write (e.g. AIN0 or DAC0).
The term "Modbus register" generally refers to the Modbus use of the term, which is a 16-bit value pointed to by an address of 0-65535.
Therefore, most "registers" consist of 1 or 2 "Modbus registers".
For example, the first entry (starting address of 0) in the Modbus Map has the name AIN#(0:254), which is shorthand notation for 255 registers named AIN0, AIN1, AIN2, ..., AIN254. The AIN# data type is FLOAT32, so each value needs 2 Modbus registers, thus the address for a given analog input is channel*2
.
Zero-Based Addressing
Zero-Based Addressing means that the addresses defined in the Modbus Map are the addresses that should be used in the actual Modbus TCP packets.
If you want to read an address documented to be at address 2000, then 2000 should be the address in in the Modbus TCP packet. Some Modbus TCP client software subtracts 1 from all addresses. For example, you tell the client software you want to read address 2000, but it puts 1999 in the actual Modbus TCP packet. That means if you want to read Modbus address 2000 you have to pass 2001 to the client software.
Some Modbus TCP client programs use addresses written as 4xxxx, which can refer to the "Holding Register" address block in some Modbus addressing schemes. However, this addressing scheme is not defined as a part of the Modbus specification and LabJack devices do not use this form for addressing. If 4xxxx addressing is encountered in a client program, the xxxx will often refer to the address used in the Modbus packet, or it might also have 1 subtracted before being put into the Modbus packet. For example, address 2000 on the LabJack may be accessible by passing 42000 or 42001 to the client software.
Big-Endian
Modbus is specified as big-endian, which means the most significant value is at the lowest address. With a read of a 16-bit (single register) value, the 1st byte returned is the MSB (most significant byte) and the 2nd byte returned is the LSB (least significant byte). With a read of a 32-bit (2 register) value, the value is returned MSW then LSW, where each word is returned MSB then LSB, so the 4 bytes come in order from most significant to least significant.
Some Modbus TCP clients expect Modbus to be implemented with big-endian bytes but with the least significant word before the most significant word. In other words, the client software flips the order of the words within a 32-bit value. For example, a read of TEST (address 55100) should return 0x00112233, but the client returns 0x22330011. Most client programs provide options to change the data interpretation.
Data Type Constants
Each entry in the map has an associated data type. The data type tells us know to format data being sent to the device and how to interpret data from the device. The raw data in the map contains the integer values below. The Map above displays the type name instead of the integer value.
Type | Integer Value |
---|---|
UINT16 | 0 |
UINT32 | 1 |
INT32 | 2 |
FLOAT32 | 3 |
BYTE | 99 |
STRING | 98 |
ljm_constants.json
LabJack distributes a constants file called ljm_constants.json
that defines information about the Modbus register map. The filter and search tool above pulls data from that JSON file.
The ljm_constants GitHub repository contains up-to-date text versions of the Modbus register map:
JSON - ljm_constants.json
C/C++ header - LabJackMModbusMap.h
Most device registers are written and/or read by address. Buffer registers are special registers that are used when multiple values must be written or read, but the number of values are able to change. Buffer Registers produce multiple values when being read and consume all values being written, and they allow users to write a sequence of values to a single Modbus address. Buffer registers typically have a companion "_SIZE" register that defines how many sequential values should be sent to or read from a buffer register.
Buffer Registers
Buffer registers could also be called array registers; the array size is defined using a "_SIZE" register, then the array data is accessed or modified using a single specific (Modbus) address.
For example, consider the difference between AIN0 and FILE_IO_PATH_READ:
Normal register:
AIN0 is at address 0 and is followed by AIN1 at address 2
AIN0 is a normal register
Reading an array of 4 registers starting at address 0 would read 2 registers from AIN0 and 2 registers AIN1 (AIN values are FLOAT32, which each consist of 2 registers)
Buffer register:
FILE_IO_PATH_READ is at address 60652 and is followed by FILE_IO_WRITE at address 60654
FILE_IO_PATH_READ is a Buffer Register
Reading an array of 4 registers starting at address 60652 would read 4 registers from FILE_IO_PATH_READ. FILE_IO_WRITE would not be read.
Note that users would first designate that 8 bytes are about to be read by writing a value of 8 to FILE_IO_PATH_READ_LEN_BYTES.
In practice, the important differences are:
You don't need to know what registers follow a Buffer Register, you can simply write / read without worrying about colliding with other registers
You can only write / read values sequentially. E.g. you cannot modify previously written values.
Define how much data to send/receive to/from the buffer register using the associated _NUM_BYTES, or _SIZE, or _LEN register.
Often it is necessary to complete the transaction with an action register, such as _GO, or _OPEN, or _ENABLE.
Buffer Registers, and their size definitions:
Serial Comm Systems
ASYNCH_DATA_RX
ASYNCH_DATA_TX
ASYNCH_NUM_BYTES_RX
ASYNCH_NUM_BYTES_TX
I2C_DATA_RX
I2C_DATA_TX
I2C_NUM_BYTES_RX
I2C_NUM_BYTES_TX
ONEWIRE_DATA_RX
ONEWIRE_DATA_TX
ONEWIRE_NUM_BYTES_RX
ONEWIRE_NUM_BYTES_TX
SPI_DATA_RX
SPI_DATA_TX
SPI_NUM_BYTES
File IO System
FILE_IO_PATH_READ
FILE_IO_PATH_WRITE
FILE_IO_PATH_READ_LEN_BYTES
FILE_IO_PATH_WRITE_LEN_BYTES
FILE_IO_READ
FILE_IO_WRITE
FILE_IO_SIZE_BYTES
Lua Scripts/Debug Info
LUA_SOURCE_WRITE
LUA_SOURCE_SIZE
LUA_DEBUG_DATA
LUA_DEBUG_NUM_BYTES
Stream Out System
STREAM_OUT#(0:3)_BUFFER_F32
STREAM_OUT#(0:3)_BUFFER_U16
STREAM_OUT#(0:3)_BUFFER_U32
STREAM_OUT#(0:3)_BUFFER_ALLOCATE_NUM_BYTES
User RAM FIFOs
USER_RAM_FIFO#(0:3)_DATA_F32
USER_RAM_FIFO#(0:3)_DATA_I32
USER_RAM_FIFO#(0:3)_DATA_U16
USER_RAM_FIFO#(0:3)_DATA_U32
USER_RAM_FIFO#(0:3)_ALLOCATE_NUM_BYTES
WIFI
WIFI_SCAN_DATA
WIFI_SCAN_NUM_BYTES
Internal Flash
INTERNAL_FLASH_READ
INTERNAL_FLASH_WRITE
Buffer registers can be identified using the Modbus Map tool. Expand the details button to see whether a register is a buffer register, and other details.
LJM
When using the LJM library, the ByteArray or Array functions should be used to read or write buffer buffer registers:
Non-BYTE registers: LJM_eReadAddressArray, LJM_eReadNameArray, LJM_eWriteAddressArray, or LJM_eWriteNameArray
BYTE-type registers: LJM_eReadAddressByteArray, LJM_eReadNameByteArray, LJM_eWriteAddressByteArray, or LJM_eWriteNameByteArray
Reading buffer registers with the wrong LJM function can result in error LJME_FUNCTION_DOES_NOT_SUPPORT_THIS_TYPE
.