Modbus
Modbus is a widely adopted, open serial communication protocol originally developed in 1979 by Modicon (now part of Schneider Electric) to facilitate data exchange between programmable logic controllers (PLCs) and other industrial automation devices.[1] Operating at the application layer (Layer 7) of the OSI model, it defines a simple, request-response messaging structure for reading and writing data such as discrete inputs, coils, input registers, and holding registers, typically in 16-bit word formats representing statuses, counters, or analog values.[1] The protocol employs a master-slave architecture, where a master device (e.g., an HMI or SCADA system) initiates transactions and slaves (e.g., sensors or actuators) respond, ensuring reliable communication across diverse physical media like serial lines or Ethernet.[2] The core of Modbus is its Protocol Data Unit (PDU), a compact structure consisting of a 1-byte function code (e.g., 03 for reading holding registers or 16 for writing multiple registers) followed by up to 252 bytes of data, with a maximum PDU size of 253 bytes to support efficient, low-overhead transactions.[2] Addressing in Modbus uses four distinct data banks—coils and discrete inputs for boolean values, and holding and input registers for 16-bit words—each supporting up to 65,536 elements addressed from 0 to 65,535, often prefixed in documentation (e.g., 4xxxx for holding registers).[2] Error handling includes exception responses for issues like invalid addresses or unsupported functions, using codes such as 01 (illegal function) or 02 (illegal data address).[2] Modbus has evolved into several variants to accommodate different network types, including Modbus RTU (binary format over serial lines like RS-485 with CRC error checking and silent inter-frame periods), Modbus ASCII (human-readable hexadecimal over serial with LRC checks), and Modbus TCP/IP (adapted for Ethernet using TCP for reliable delivery and a Modbus Application Protocol header).[3] The protocol's serial line specifications date back to 1996, with ongoing updates like the Modbus Security Protocol, which integrates Transport Layer Security (TLS) and X.509v3 certificates for authentication and integrity on port 802.[3] Despite its simplicity and lack of native support for advanced features like large data types or built-in security in base variants, Modbus remains a de facto standard due to its royalty-free openness, broad device compatibility, and ease of implementation in industrial environments.[2] In practice, Modbus powers critical applications in manufacturing, energy management, and process control, enabling seamless integration between PLCs, sensors, drives, and supervisory systems while serving as a foundational protocol in the transition to Industrial IoT (IIoT).[1] Its enduring popularity stems from over four decades of widespread adoption, with conformance classes (0 for basic public functions, 1 for diagnostics, and 2 for vendor-specific extensions) ensuring interoperability across thousands of compliant devices globally.[4]Overview
History and Development
The Modbus protocol was developed in 1979 by Modicon, a pioneering company in programmable logic controllers (PLCs) that is now part of Schneider Electric, to enable reliable communication between PLCs and other devices in industrial automation systems.[5] Initially designed as a simple, master-slave protocol for reading and writing data over serial lines such as RS-232 and RS-485, it addressed the need for standardized data exchange in manufacturing environments dominated by Modicon's proprietary hardware.[6] This foundational version, often referred to as Modbus RTU or ASCII, quickly gained traction within Modicon ecosystems for its robustness and ease of implementation in multidrop networks.[7] Originally proprietary to Modicon, the protocol was released as an open, royalty-free standard in the 1990s, allowing broader adoption across vendors and reducing barriers to interoperability in industrial settings.[8] A significant milestone came in 1999 with the introduction of Modbus TCP/IP by Modicon, which extended the protocol over Ethernet networks using TCP/IP as the transport layer, facilitating higher-speed integration with modern IT infrastructure while preserving the core messaging structure.[9] This adaptation marked Modbus's transition from serial-based systems to networked environments, enhancing its applicability in distributed control architectures.[7] In 2004, Schneider Electric transferred stewardship of the Modbus specification to the newly formed Modbus Organization, a nonprofit trade association comprising users, suppliers, and developers dedicated to maintaining, evolving, and certifying the protocol.[10] This shift ensured ongoing support and conformance testing, solidifying Modbus's status as a de facto standard. Evolution continued with proprietary variants like Modbus Plus, introduced by Modicon in the late 1980s as a high-speed, token-passing network for demanding applications, though it diverged from the open standard in implementation. Additionally, integrations such as gateways for Ethernet/IP have enabled Modbus to coexist with other industrial protocols, extending its utility in hybrid networks.[7]General Protocol Characteristics
Modbus operates as a client-server, request-response protocol, originally designed as a master-slave architecture, facilitating communication between automation devices in industrial environments. In this model, a single client (master) initiates requests to one or more servers (slaves), which respond with the requested data or actions, enabling efficient control and monitoring without constant polling from all devices simultaneously. This structure positions Modbus at the application layer of the OSI model, independent of the underlying physical and data link layers, allowing it to run over serial lines, Ethernet, or other networks.[11] Key characteristics of Modbus include its simplicity, openness, and royalty-free nature, which have contributed to its widespread adoption since its inception. The protocol features a minimalistic messaging structure with low overhead, making it easy to implement on resource-constrained devices such as programmable logic controllers (PLCs), sensors, and actuators. It supports up to 247 devices on a single network, addressed via 8-bit identifiers ranging from 1 to 247, allowing for scalable deployments in multi-device systems. As an open standard maintained by the Modbus Organization, it is freely available for use without licensing fees, promoting interoperability across vendors in industrial control systems (ICS), supervisory control and data acquisition (SCADA), and automation applications.[11][12][2] Modbus finds primary applications in industries such as manufacturing, energy production, and water treatment, where it enables the reading and writing of discrete inputs/outputs, analog values, and diagnostic information between field devices and control systems. For instance, it allows PLCs to query sensors for process variables like temperature or pressure and command actuators to adjust valves or motors accordingly, supporting real-time automation tasks. Its ease of implementation and low protocol overhead make it suitable for legacy and modern systems alike, though it lacks built-in security mechanisms such as authentication or encryption, necessitating additional safeguards in sensitive deployments.[11][13][14]Protocol Fundamentals
PDU and ADU Structure
In the Modbus protocol, the Protocol Data Unit (PDU) represents the core, application-layer message that is independent of the underlying physical and data link layers. It consists of a single-byte function code followed by variable-length data bytes specific to the requested operation or response. The function code, ranging from 0x01 to 0xFF (with values 0x80 to 0xFF indicating exceptions), specifies the action to be performed, such as reading or writing data, while the data field carries parameters like register addresses or values. The maximum PDU size is 253 bytes to accommodate transport-layer constraints, ensuring compatibility across different implementations.[11] The Application Data Unit (ADU) encapsulates the PDU with transport-specific headers and integrity checks to form a complete frame suitable for transmission over a particular medium. In serial line implementations, the ADU prepends a one-byte slave address (ranging from 0x01 to 0xF7 for individual devices or 0x00 for broadcast) to the PDU and appends an error-checking field: either a two-byte CRC-16 for binary RTU mode or a one-byte LRC for ASCII mode. This results in a maximum ADU length of 256 bytes for RTU, comprising the address, up to 252 bytes of PDU data, and the CRC. For ASCII mode, the ADU uses printable characters, with the address and LRC each represented as two hexadecimal characters, leading to a maximum of 513 characters including delimiters.[15][11] For Modbus TCP, the ADU replaces serial-specific elements with a seven-byte Modbus Application Protocol (MBAP) header prefixed to the PDU, yielding a maximum length of 260 bytes. The MBAP includes a two-byte transaction identifier for matching requests and responses, a two-byte protocol identifier (fixed at 0x0000 for Modbus), a two-byte length field indicating the bytes following it (always at least 1 for the unit identifier), and a one-byte unit identifier serving as the logical slave address. Unlike serial ADUs, TCP variants omit explicit CRC or LRC, relying instead on the TCP/IP stack's checksum mechanisms for error detection.[11] Error-checking fields ensure data integrity in serial ADUs. The CRC-16 used in RTU mode employs the polynomial $0xA001 (equivalent to x^{16} + x^{15} + x^2 + 1) with an initial register value of $0xFFFF. The calculation processes each byte of the message (address through PDU data) by XORing it with the low byte of the register, right-shifting 16 times while XORing the polynomial into the high byte whenever the outgoing bit is 1, and appending the low byte followed by the high byte. For ASCII mode, the LRC is computed as the two's complement negation of the sum of all message bytes (address through PDU data) modulo 256, represented in two hexadecimal characters with the high-order nibble first. These mechanisms provide robust frame validation without impacting the protocol-independent PDU.[15]| Component | RTU ADU (Serial) | ASCII ADU (Serial) | TCP ADU |
|---|---|---|---|
| Prefix/Header | Slave Address (1 byte) | Start (:) + Address (2 chars) + Function (2 chars) | MBAP (7 bytes: Transaction ID [16], Protocol ID [16], Length [16], Unit ID [17]) |
| Core | PDU (up to 253 bytes: Function Code [17] + Data [0-252]) | Data (up to 2×252 chars) | PDU (up to 253 bytes: Function Code [17] + Data [0-252]) |
| Suffix/Check | CRC-16 (2 bytes) | LRC (2 chars) + End (CR LF) | None (TCP checksum) |
| Max Length | 256 bytes | 513 characters | 260 bytes |
Data Model and Addressing
Modbus employs a straightforward data model organized into four distinct tables, each representing a different type of data accessible within a device. These tables are: coils (discrete outputs), discrete inputs, holding registers, and input registers. Coils and discrete inputs store single-bit values, while holding and input registers hold 16-bit words. This model allows for the logical separation of read-write and read-only data, as well as bit-level and word-level information, facilitating efficient access in industrial control systems.[11] The following table summarizes the four data tables, including their characteristics and associated primary function codes for access:| Data Table | Description | Access Type | Size | Primary Function Codes |
|---|---|---|---|---|
| Coils | Discrete outputs (bits) | Read-Write | 1 bit | 01 (Read), 05/15 (Write) |
| Discrete Inputs | Discrete inputs (bits) | Read-Only | 1 bit | 02 (Read) |
| Holding Registers | Analog values/output (words) | Read-Write | 16 bits | 03 (Read), 06/16 (Write) |
| Input Registers | Analog input values (words) | Read-Only | 16 bits | 04 (Read) |
Communication Mechanisms
Modbus Transactions
Modbus transactions operate on a client/server model, where the master (client) initiates all communications in a polling manner by transmitting a request Application Data Unit (ADU) to one or more slave devices (servers). The targeted slave processes the request and returns a response ADU containing the results or an indication of success; unicast requests to specific slaves expect a reply, while the master implements a timeout mechanism—typically 1 to several seconds at 9600 baud—to detect non-responses and handle errors accordingly.[15][19] In broadcast transactions, the master addresses the request to all slaves using device address 0, limiting it to write operations since no responses are generated or expected from the slaves; this allows efficient multi-device updates without reply overhead. The master-slave polling ensures orderly access to shared media, preventing collisions in multi-drop networks.[19][15] Timing constraints are essential for reliable transaction framing, particularly in serial line implementations. In Modbus RTU mode, a message frame begins and ends with a silent interval of at least 3.5 character times, while the interval between consecutive characters must not exceed 1.5 character times to avoid the receiver declaring the frame incomplete and discarding it. For ASCII mode, inter-character timeouts allow up to 1 second of silence. Turnaround delays after broadcasts range from 100 to 200 ms to permit slave processing before the next master transmission, and these must be shorter than the overall response timeout.[15] A representative example of a simple read transaction involves the master sending an ADU with the slave's address, a read function identifier, and references to specific data locations such as coils or holding registers. Upon receipt, the slave validates the request, retrieves the data, and transmits a response ADU mirroring the structure but populated with the read values; the entire exchange completes within the configured timeout if successful. These transactions reference the Modbus data model of discrete inputs, coils, input registers, and holding registers.[19]Function Codes Overview
Modbus function codes define the specific operations requested by a client device in a Modbus transaction, forming a critical part of the Protocol Data Unit (PDU) to specify actions such as reading or writing data from server devices.[11] These codes are standardized to ensure interoperability across devices, with the function code occupying the first byte of the PDU following the transaction identifier and protocol ID fields.[11] Some functions include an optional subfunction code byte for additional specificity, such as in diagnostic operations, while multi-bit or multi-register functions employ bitmasks or byte arrays to efficiently handle batches of data without individual addressing.[11] Function codes are categorized into public, user-defined, and reserved groups to balance standardization with flexibility for custom implementations. Public codes, ranging from 1 to 127 (0x01 to 0x7F), are officially defined and validated by the Modbus Organization for broad use in reading and writing coils (discrete outputs) and registers (analog values).[11] User-defined codes, in the ranges 65-72 (0x41-0x48) and 100-110 (0x64-0x6E), allow vendors to implement device-specific commands without conflicting with public standards, though they lack uniqueness guarantees and are intended for proprietary extensions.[11] Reserved function codes are those currently used by some companies for legacy products and are not available for public use (as listed in Annex A of the specification).[11] The public function codes are grouped by data type and operation, primarily targeting coils (single-bit values representing on/off states) and registers (16-bit words for holding or input data). For coils, code 01 reads the status of multiple coils, code 02 reads discrete inputs (read-only coil equivalents), code 05 writes a single coil to on or off, and code 15 writes multiple coils using a bitmask-packed byte array for efficiency.[11] For registers, code 03 reads multiple holding registers (writable), code 04 reads input registers (read-only), code 06 writes a single holding register, code 16 writes multiple holding registers with a sequence of 16-bit values, code 22 performs a mask write on a single register using AND/OR bitmasks to modify specific bits without affecting others, and code 23 combines reading and writing multiple holding registers in one transaction to reduce communication overhead.[11] These groupings enable targeted access to the Modbus data model, where coils address up to 2000 bits and registers up to 125 words per function call, promoting scalable industrial automation.[11]| Category | Code (Hex) | Purpose | Data Type |
|---|---|---|---|
| Public (Coils/Discrete) | 01 | Read multiple coils | Bits (outputs) |
| Public (Coils/Discrete) | 02 | Read discrete inputs | Bits (inputs) |
| Public (Coils/Discrete) | 05 | Write single coil | Bit (output) |
| Public (Coils/Discrete) | 15 (0F) | Write multiple coils | Bits (outputs, bitmask) |
| Public (Registers) | 03 | Read holding registers | 16-bit words (holding) |
| Public (Registers) | 04 | Read input registers | 16-bit words (input) |
| Public (Registers) | 06 | Write single register | 16-bit word (holding) |
| Public (Registers) | 16 (10) | Write multiple registers | 16-bit words (holding) |
| Public (Registers) | 22 (16) | Mask write register | 16-bit word (holding, bitmask) |
| Public (Registers) | 23 (17) | Read/write multiple registers | 16-bit words (holding) |
Error Handling
Exception Responses
In Modbus, when a server (slave) encounters an error while processing a client (master) request, it generates an exception response to indicate the issue rather than a normal response. The server detects errors such as unsupported functions, invalid addresses, or invalid data values in the request. To signal an exception, the server modifies the function code in the response by setting its most significant bit to 1, which is equivalent to adding 0x80 (in hexadecimal) to the original function code; for example, a request with function code 0x01 would result in an exception response with function code 0x81. This modified function code allows the client to immediately recognize the response as an exception without parsing further data.[11] The structure of an exception response follows the same application data unit (PDU) format as a normal response but includes the modified function code followed by a single-byte exception code in the data field, with no additional payload. In the full application data unit (ADU), which encompasses the PDU plus transport-layer elements (such as address fields in serial implementations or transaction identifiers in TCP), the exception response maintains the overall frame structure of the original request type but flags the error via the function code and exception code. This concise format ensures minimal overhead while providing essential diagnostic information about the failure.[11] Modbus defines a set of standard exception codes to specify the nature of the error, each represented as a single byte value. These codes are universally applicable across Modbus variants and are returned only when a specific condition is met during request validation or execution. The following table summarizes the standard exception codes:| Code (Hex) | Name | Description |
|---|---|---|
| 01 | Illegal Function | The function code received is not supported by the server or the server is in an improper state to execute it. |
| 02 | Illegal Data Address | The data address referenced in the request is not accessible or does not exist in the server's data model. |
| 03 | Illegal Data Value | A value contained in the request data is invalid, such as a quantity exceeding supported limits. |
| 04 | Server Device Failure | An unrecoverable error occurred while the server attempted to perform the requested action. |
| 05 | Acknowledge | The server has accepted the request but requires significant processing time; the client should perform a polling operation to monitor completion, such as using Read Exception Status (function code 0x07). |
| 06 | Server Device Busy | The server is engaged in processing another request and cannot handle the current one; the client should retry later. |
| 07 | Negative Acknowledge | The data value received in the query is not an allowable value for the server (e.g., a parameter that is ignored or an unsupported operation). |
| 08 | Memory Parity Error | A parity error was detected in the memory during file record read or write operations (specific to functions 20 and 21). |
| 0A | Gateway Path Unavailable | In a gateway configuration, the path to the target device cannot be established due to configuration or overload issues. |
| 0B | Gateway Target Device Failed to Respond | The gateway was unable to receive a valid response from the target device within the timeout period. |
Diagnostic and Error Codes
Modbus provides diagnostic capabilities primarily through Function Code 08 (Diagnostics), which enables masters to query slaves for communication status and internal error conditions, particularly in serial line implementations. This function is essential for troubleshooting network issues, such as verifying message integrity or resetting communication counters, without disrupting normal data access operations. It operates by specifying a subfunction code in the request PDU to select the diagnostic test, with the slave echoing or providing relevant data in the response. The subfunctions for Diagnostics (Function Code 08) include a range of tests, as defined in the Modbus Application Protocol Specification. For example, subfunction 00 (Return Query Data) simply echoes the request data back to confirm basic communication, while subfunction 01 (Restart Communications Option) restarts the slave's communication port and clears diagnostic counters, though it generates no response if the slave is in Listen Only Mode. Other key subfunctions provide counters for error tracking: subfunction 0C (Return Bus Communication Error Count) reports the number of messages discarded due to CRC errors since the last restart, and subfunction 0D (Return Bus Exception Error Count) counts exception responses sent by the slave. The complete set of subfunctions includes the following:| Subfunction (Hex) | Decimal | Name | Description |
|---|---|---|---|
| 00 | 0 | Return Query Data | Echoes request data for communication verification. |
| 01 | 1 | Restart Communications Option | Restarts port and clears counters; no response in Listen Only Mode. |
| 02 | 2 | Return Diagnostic Register | Returns 16-bit diagnostic register contents. |
| 03 | 3 | Change ASCII Input Delimiter | Sets new end-of-message delimiter (replaces default colon and line feed). |
| 04 | 4 | Force Listen Only Mode | Puts device in Listen Only Mode; no response returned. |
| 0A | 10 | Clear Counters and Diagnostic Register | Clears all counters and diagnostic register. |
| 0B | 11 | Return Bus Message Count | Returns total messages processed or detected since last restart. |
| 0C | 12 | Return Bus Communication Error Count | Counts CRC errors since restart. |
| 0D | 13 | Return Bus Exception Error Count | Counts exception responses since restart. |
| 0E | 14 | Return Server Message Count | Counts processed messages since restart. |
| 0F | 15 | Return Server No Response Count | Counts messages addressed to server but no response sent since restart. |
| 10 | 16 | Return Server NAK Count | Counts Negative Acknowledge exception responses since restart. |
| 11 | 17 | Return Server Busy Count | Counts Server Device Busy exception responses since restart. |
| 12 | 18 | Return Bus Character Overrun Count | Counts messages lost due to character overrun since restart. |
| 14 | 20 | Clear Overrun Counter and Flag | Clears overrun error counter and resets overrun flag. |
Serial Line Implementations
Modbus RTU
Modbus RTU is a binary implementation of the Modbus protocol designed for serial communication, utilizing compact 8-bit byte encoding to maximize efficiency on low-bandwidth lines.[15] Each byte in an RTU frame consists of 1 start bit, 8 data bits transmitted least significant bit first, an optional parity bit, and 1 or 2 stop bits, resulting in a total of 11 bits per character.[15] Even parity is typically required, though odd parity or no parity (with 2 stop bits) may be used depending on the implementation.[15] This binary format allows for higher data throughput compared to text-based alternatives due to its greater character density.[15] RTU frames are delimited by periods of silence on the communication line, with a minimum of 3.5 character times of idle space before the start of a frame and after its end to separate messages.[15] The frame structure begins with a 1-byte slave address field (ranging from 1 to 247, or 0 for broadcast), followed by a 1-byte function code, a variable-length data field (0 to 252 bytes), and ends with a 2-byte CRC-16 checksum appended in low-byte-first order.[15] The total frame length is limited to a maximum of 256 bytes to ensure compatibility across devices.[15] Strict timing is essential for RTU operation to detect frame boundaries and errors; between consecutive characters within a frame, the inter-character timeout must not exceed 1.5 character times, or the receiver discards the frame.[15] For baud rates of 19,200 bits per second or lower, these timings are calculated directly in character times (e.g., 3.5 character times equates to approximately 1.75 ms at 19.2 kbps), while higher baud rates use fixed values of 1.750 ms for the frame delimiter and 750 µs for inter-character gaps to account for hardware variations.[15] Modbus RTU is particularly suited for resource-constrained serial interfaces such as RS-232 and RS-485, where its compact binary nature optimizes bandwidth usage in master-slave or multi-drop network configurations.[15] It supports up to 247 addressable slave devices in a network, though practical limits without repeaters typically allow for 32 devices due to electrical constraints on RS-485 bus loading.[15]Modbus ASCII
Modbus ASCII is a human-readable variant of the Modbus protocol designed for transmission over serial lines, where each binary byte is represented by two hexadecimal characters in the ASCII character set. This mode encodes the protocol data unit (PDU) into a text-based frame that begins with a colon (:) character (ASCII 3A hex) and ends with a carriage return-line feed (CRLF) pair (ASCII 0D 0A hex), making it suitable for environments where visual inspection of messages is beneficial. Unlike binary formats, Modbus ASCII allows for easier debugging and logging since the transmitted data can be directly interpreted by humans using standard text tools. The frame structure in Modbus ASCII consists of the start delimiter (1 character), slave address (2 hexadecimal characters), function code (2 characters), data field (an even number of characters, up to 504 for a maximum PDU size of 252 bytes), longitudinal redundancy check (LRC) (2 characters), and end delimiter (2 characters), resulting in a total frame length of up to 513 characters. Each byte from the binary message is converted to two ASCII hexadecimal digits (0-9, A-F), ensuring the data portion has an even character count. The LRC, an 8-bit checksum, is computed by summing all bytes in the address, function, and data fields (excluding delimiters), taking the two's complement of the result, and appending it as two hexadecimal characters before the CRLF; this provides basic error detection for the frame. Timing requirements in Modbus ASCII are more lenient than in binary modes, with inter-character intervals permitted up to 1 second (or up to 4-5 seconds in wide-area network scenarios) before the frame is considered invalid, eliminating the need for precise millisecond-level synchronization. This flexibility arises because the explicit start and end delimiters (: and CRLF) clearly bound the message, allowing receivers to tolerate delays without ambiguity. However, the encoding doubles the transmission size compared to binary equivalents, leading to higher bandwidth consumption and reduced throughput at the same baud rate, which can slow parsing and increase latency in high-volume applications. Modbus ASCII is particularly employed in legacy systems or scenarios where the strict timing constraints of binary modes cannot be reliably met, such as over noisy or low-speed serial connections, and its readable format supports troubleshooting and integration with text-based monitoring tools. Despite these benefits, its inefficiencies make it less common in modern, high-performance industrial networks, where compact binary alternatives are preferred for better resource utilization.TCP/IP Implementations
Modbus TCP
Modbus TCP is an adaptation of the Modbus protocol designed for communication over Ethernet networks using the Transmission Control Protocol (TCP) as the transport layer. It encapsulates the Modbus Protocol Data Unit (PDU) within an Application Data Unit (ADU) that includes a Modbus Application Protocol (MBAP) header, eliminating the need for slave address fields and cyclic redundancy checks (CRC) present in serial variants. This implementation enables direct integration with standard TCP/IP infrastructure, allowing Modbus devices to operate within intranet or internet environments without requiring specialized serial hardware. The MBAP header consists of four fields: a 2-byte transaction identifier for matching requests and responses, a 2-byte protocol identifier set to 0 to denote Modbus TCP, a 2-byte length field indicating the size of the subsequent data, and a 1-byte unit identifier for routing to specific devices on the network. Modbus TCP operates on TCP port 502, facilitating client-server interactions where clients initiate connections to servers. These connections are typically persistent, supporting multiple concurrent transactions over a single socket; the transaction identifier ensures proper pairing of requests and responses, preventing mismatches in high-traffic scenarios. Unlike serial Modbus, there is no inherent addressing or error-checking overhead in the ADU, as TCP handles reliability and ordering. To illustrate, consider a request to read two holding registers starting from address 0 using function code 03. The ADU in hexadecimal format is00 01 00 00 00 06 01 03 00 00 00 02, broken down as follows:
00 01: Transaction identifier00 00: Protocol identifier (0)00 06: Length (6 bytes following)01: Unit identifier03: Function code (read holding registers)00 00: Starting register address00 02: Number of registers
00 01 00 00 00 07 01 03 04 02 2B 00 64:
00 01: Transaction identifier00 00: Protocol identifier (0)00 07: Length (7 bytes following)01: Unit identifier03: Function code04: Byte count (4 bytes of data)02 2B 00 64: Register values (big-endian: 555 and 100 decimal)
Modbus over UDP and Other IP Variants
Modbus over UDP represents a connectionless adaptation of the Modbus protocol, leveraging the User Datagram Protocol (UDP) for IP-based communication, typically on port 502. This variant retains the core Modbus application layer while eliminating the connection overhead of TCP, enabling faster transmission with reduced bandwidth usage. It supports stateless, transaction-oriented exchanges where requests and responses are paired using a transaction identifier in the MBAP header, similar to Modbus TCP but without persistent sessions.[21][7] Key advantages include support for multicast and broadcast messaging, which facilitates efficient data dissemination in multi-device environments such as low-latency sensor networks in industrial IoT setups. For instance, in real-time monitoring applications, UDP's lightweight nature allows quicker polling of multiple slaves without the retransmission delays inherent in TCP. However, the lack of built-in reliability means no guaranteed delivery, ordering, or error correction at the transport layer, necessitating application-level acknowledgments and retry logic to handle packet loss.[21][7] This makes Modbus UDP particularly suited for scenarios where occasional data loss is tolerable, but it sees limited adoption due to the prevalence of more robust alternatives and the absence of an official specification from the Modbus Organization.[22] Beyond UDP, other IP variants extend Modbus TCP with security enhancements, such as the Modbus Security Protocol, which integrates Transport Layer Security (TLS) to encapsulate messages, ensuring authentication via X.509v3 certificates, data integrity, and confidentiality. Operating on port 802, this wrapper addresses Modbus's inherent vulnerabilities in open networks by providing encrypted channels without altering the underlying protocol structure. Additionally, protocol gateways enable Modbus integration with contemporary IP-based systems, mapping device registers to MQTT publish/subscribe topics for cloud connectivity or to OPC UA information models for secure, semantic data exchange in enterprise environments. These mappings support IIoT scalability but require careful configuration to maintain timing and data fidelity.[23][24] Overall, such variants enhance Modbus's versatility on IP networks while mitigating its traditional limitations in reliability and security.Protocol Extensions and Variants
User-Defined and Reserved Codes
In the Modbus protocol, user-defined function codes provide a mechanism for implementers to extend the standard set of operations without conflicting with publicly defined codes. These codes allow for the creation of custom services tailored to specific applications, such as proprietary device interactions or specialized data exchanges. The ranges designated for user-defined codes are 65 to 72 (hexadecimal 0x41 to 0x48) for simple extensions and 100 to 110 (hexadecimal 0x64 to 0x6E) for more complex encapsulated interfaces.[11][2] Implementers selecting these codes must ensure no overlap with public function codes (1 to 64), and there is no guarantee of uniqueness unless a Request for Comments (RFC) is submitted to the Modbus Organization for potential reclassification as public.[11] Reserved function codes, spanning 73 to 99 (hexadecimal 0x49 to 0x63) and 111 to 127 (hexadecimal 0x6F to 0x7F), are held exclusively for future allocation by the Modbus Organization and are not available for public or user-defined implementations. These ranges support legacy uses by specific companies but prohibit new public developments to maintain protocol integrity. No known public implementations exist within these reserved spaces, ensuring they remain protected for standardized extensions.[11][2] Implementation guidelines emphasize compatibility and non-interference; user-defined codes must adhere to the general Modbus Protocol Data Unit (PDU) structure, with responses including the same function code unless an exception occurs (indicated by setting the high-order bit). These codes are often employed for proprietary features, such as advanced file transfer operations that build on public codes like 20 (Read File Record) and 21 (Write File Record) for subfunction-based record access, or function code 23 (Read/Write Multiple Registers) for atomic read-write combinations in specialized contexts.[11] A key application of the higher user-defined range involves encapsulation, where function code 43 (Encapsulated Interface Transport) uses Modbus Encapsulated Interface (MEI) types—such as type 13 for tunneling CANopen commands—to wrap non-Modbus protocols within a Modbus frame for interoperability in hybrid networks.[2][25]| Category | Decimal Range | Hexadecimal Range | Purpose |
|---|---|---|---|
| User-Defined (Simple) | 65–72 | 0x41–0x48 | Basic custom extensions without encapsulation |
| User-Defined (Encapsulated) | 100–110 | 0x64–0x6E | Complex interfaces, e.g., protocol tunneling |
| Reserved | 73–99 | 0x49–0x63 | Future public use by Modbus Organization |
| Reserved | 111–127 | 0x6F–0x7F | Legacy and future allocations, no new public use |