Modbus tools
Build and read Modbus RTU, ASCII and TCP frames, check CRC-16 and LRC, and look up exception codes. In Chrome or Edge it can also talk to a device on a serial port (RS-485 / RS-232 adapter) through Web Serial: request and reply, polling and a log. Reading is the default; every write is confirmed first.
Request
Numbers in decimal or as 0x hex. Quantities follow the specification: 1 … 2000 coils or inputs and 1 … 125 registers per read, 1 … 1968 coils and 1 … 123 registers per write. Requests outside these limits are not built.
Runs in this browser. Data is not uploaded or stored.
Frame
—
Serial link (Web Serial)
The serial link needs JavaScript and Web Serial: Chrome, Edge or Opera on a computer. Building, reading and checking frames work without it.
RS-485 direction switching (driver enable) is done by the adapter, not by the browser: use an adapter with automatic direction control. The port settings must match the device: the specification’s default is 19200 baud, 8 data bits, even parity, 1 stop bit.
Reading is the default. A write request is sent only after you confirm it in a dialog, every time; writes are never polled and nothing is retried. Polling stops at the count or at Stop.
Log
No traffic yet.
Frame
A reply does not repeat the address it answers: type the request’s start address (0-based) to list the registers with their addresses. Auto framing: “:” … CR LF is ASCII; protocol id 0 with a matching length is TCP; otherwise RTU (checked by its CRC).
Runs in this browser. Data is not uploaded or stored.
Decoded
Bytes
Runs in this browser. Data is not uploaded or stored.
Checksums
How the frames are built and read
A Modbus request is a protocol data unit (PDU: function code and data, at most 253 bytes) wrapped in an application data unit for the line it travels on. The tool follows the Modbus Application Protocol Specification V1.1b3, Modbus over Serial Line V1.02 and Modbus Messaging on TCP/IP, as recalled; the points that could not be checked against the documents here are listed at the end.
Framing
- RTU: unit id (1 byte), PDU, CRC-16 (2 bytes, low byte first); at most 256 bytes. Frames are separated by at least 3.5 character times of silence (t3.5); one character is 11 bits (start, 8 data, parity, stop — or 2 stop bits without parity). Above 19200 baud t3.5 is fixed at 1.75 ms (t1.5 at 0.75 ms).
- CRC-16/MODBUS: initial value 0xFFFF; each byte is XORed into the low byte, then 8 times: shift right, and XOR 0xA001 when the bit shifted out was 1 (the polynomial 0x8005 reflected); no final XOR. Check value: “123456789” → 0x4B37.
- ASCII: “:” (0x3A), then the unit id, the PDU and the LRC as two upper-case hex characters per byte, then CR LF; at most 513 characters; 7 data bits by default; up to 1 s between characters. LRC = two’s complement of the 8-bit sum of the bytes (unit id and PDU), so all bytes plus the LRC sum to 0 modulo 256.
- TCP: MBAP header of 7 bytes — transaction id (2, chosen by the client and echoed), protocol id (2, always 0), length (2, the bytes that follow: unit id + PDU), unit id (1) — then the PDU; at most 260 bytes; no checksum (TCP has its own). Port 502.
- All 16-bit fields (addresses, quantities, register values) are sent high byte first. How a 32- or 64-bit value spans several registers is not defined by the protocol: choose the order under “Show registers also as” (see the PLC data converter).
Functions
- 01 Read Coils, 02 Read Discrete Inputs: start, quantity 1 … 2000. Reply: byte count = ⌈quantity / 8⌉, the first coil in the lowest bit of the first byte, unused bits 0.
- 03 Read Holding Registers, 04 Read Input Registers: start, quantity 1 … 125. Reply: byte count = 2 × quantity, then the registers.
- 05 Write Single Coil: value FF00 = ON, 0000 = OFF (anything else is answered with exception 03); the reply echoes the request. 06 Write Single Register: the reply echoes the request.
- 15 Write Multiple Coils (1 … 1968, packed like 01), 16 Write Multiple Registers (1 … 123): the reply repeats start and quantity.
- 22 Mask Write Register: result = (current AND and-mask) OR (or-mask AND NOT and-mask); the reply echoes the request. 23 Read/Write Multiple Registers: writes 1 … 121 registers, then reads 1 … 125 (the write is done first).
- 08 Diagnostics, sub-function 00 Return Query Data: the device echoes the data (serial line only). Other sub-functions (restart, counters, listen-only mode) are named when read but not built: some change the device’s state.
- 43 / 14 Read Device Identification: code 01 basic, 02 regular, 03 extended (stream), 04 one object; the reply lists objects (0 VendorName, 1 ProductCode, 2 MajorMinorRevision, 3 VendorUrl, 4 ProductName, 5 ModelName, 6 UserApplicationName; 0x80 … 0xFF private), with “more follows” and the next object id.
- Address + quantity may not pass 65535. The builder refuses requests outside these limits; the reader decodes them and warns which exception a device would send.
Exception responses
A device that cannot carry out a request answers with the function code + 0x80 (0x83 for 03) and one exception code.
- 01 Illegal Function
- The device does not support this function code, or not in its current state.
- 02 Illegal Data Address
- An address of the request is not available in the device: the start address, or start + quantity, is outside what it has. Check 0-based addresses against register numbers (40001 = address 0).
- 03 Illegal Data Value
- A value of the request is not allowed: for example a quantity outside the limits, a byte count that does not match, or a coil value other than FF00 / 0000.
- 04 Server Device Failure
- An unrecoverable error occurred in the device while it was performing the requested action.
- 05 Acknowledge
- The device has accepted a request that takes a long time and is processing it; poll it later for completion.
- 06 Server Device Busy
- The device is busy with a long command; send the request again later.
- 07 Negative Acknowledge (not in V1.1b3)
- Not in the exception table of V1.1b3; older Modicon documentation (unverified here) used 07 for a program function the device cannot perform.
- 08 Memory Parity Error
- Used with function codes 20 and 21 (file records): the device found a parity error in its memory.
- 0A Gateway Path Unavailable
- A gateway could not set up a path to the target device; it may be misconfigured or overloaded.
- 0B Gateway Target Device Failed To Respond
- A gateway got no response from the target device; the device may be absent or not answering.
Addresses and register numbers
- The request carries a 0-based address 0 … 65535 for each of the four tables (coils, discrete inputs, input registers, holding registers).
- Manuals often give 1-based register numbers with the table as the first digit: 00001 coils, 10001 discrete inputs, 30001 input registers, 40001 holding registers (= address 0); the six-digit form (400001 … 465536) reaches every address. This is a convention (Modicon), not part of the protocol, and some manuals use plain 1-based numbers or even the address itself: check one register you know.
Serial link (Web Serial)
- Web Serial works in Chromium browsers (Chrome, Edge, Opera) on a computer, also in the offline file opened from disk (checked in Chromium 141: the API is present on file:// pages). The page can open only the port you choose in the browser’s window; it remembers nothing between visits.
- Safety: nothing is sent without a button press. Reading is the default; a request of a write function (05, 06, 15, 16, 22, 23) opens a dialog that lists the unit, the addresses, the values and the frame, and is sent only after “Write to the device”, every time. Writes are never polled, nothing is retried automatically, and polling stops at its count or at Stop.
- Timing: before a request the line must have been quiet for t3.5. The reply ends when it has the length its function code and byte count give; a reply that stops short ends after t3.5 of silence plus the USB allowance (default 20 ms: USB adapters deliver bytes in packets, often every 16 ms, so the browser cannot see t1.5 / t3.5 gaps reliably). ASCII replies end with CR LF. The response timeout (default 1000 ms) runs from the end of the request on the wire.
- Every reply is checked: CRC or LRC, unit id, function code (or exception), byte count against the quantity, and the echo of a write. Bytes that arrive outside a request are logged and discarded before the next one. After a broadcast (unit 0, writes only) the link waits 200 ms and expects no reply.
- RS-485: switching the driver between sending and receiving is done by the adapter; use one with automatic direction control. Some 2-wire adapters receive their own transmission: tick the echo option to drop that copy. Termination and biasing of the bus are outside the browser’s reach.
- Modbus TCP cannot be sent from a web page (no sockets); its frames can be built and read.
Worked examples (the tool’s examples)
- Read 10 holding registers from unit 1 at address 0 (registers 40001 … 40010): PDU 03 00 00 00 0A; RTU 01 03 00 00 00 0A C5 CD (CRC 0xCDC5, low byte first); ASCII :01030000000AF2 CR LF (1 + 3 + 0 + 0 + 0 + 10 = 14 = 0x0E, LRC = 0x100 − 0x0E = 0xF2); TCP with transaction id 1 00 01 00 00 00 06 01 03 00 00 00 0A.
- The reply has 3 + 20 + 2 = 25 bytes: 01 03 14 (byte count 20) then the registers 00E1 0190 41C8 0000 FFFE 1DC0 0001 0000 1234 0007 and the CRC 99 8A. Register 40001 = 0x00E1 = 225; registers 40003 – 40004 = 0x41C8 0x0000 = 25.0 as FLOAT32 (ABCD); 40005 – 40006 = −123456 as INT32 (illustrative values).
- The exception reply 01 83 02 C0 F1: function 0x83 = 03 + 0x80, exception 02 Illegal Data Address.
- Writing 25.0 as FLOAT32 (ABCD) to address 100 with function 16: 01 10 00 64 00 02 04 41 C8 00 00 61 B6.
- The check value: the CRC-16/MODBUS of the nine characters “123456789” is 0x4B37.
Common mistakes
- Off by one: register 40001 is address 0. A device that answers exception 02, or values shifted by one register, usually means this.
- CRC bytes swapped: the CRC is the only field sent low byte first.
- Port settings that differ from the device: 8E1 is the default of the specification, but many devices are set to 8N1 or 8N2.
- Polling too fast for the device or the bus: leave time for the reply and the inter-frame silence; at 9600 baud a reply of 25 bytes alone takes 29 ms.
- Two masters on one RS-485 bus: Modbus serial has exactly one client; a second one (an HMI, a PLC) collides with this page.
Input and files
- Hex bytes with or without spaces, commas or dashes, 0x prefixes allowed; an ASCII frame as its characters starting with “:”. Register values in decimal (−32768 … 65535), hex (0x41C8) or binary (0b…); typed values through the PLC data converter’s conversion (exact float rounding).
- Results CSV for each part, the log as CSV (time, direction, bytes, decoded text, status, reply time) and one settings JSON for every field; nothing is stored by this file, and no port is remembered.
Not verified against the documents
- The specifications could not be opened here; the function layouts, limits, exception names, the 1.75 ms / 0.75 ms timing above 19200 baud and the CRC are written from memory. Frames and CRCs agree with the independent reference script and with pymodbus, and the well-known published frames (01 03 00 00 00 0A C5 CD; the CRC check value 0x4B37) are reproduced.
- Exception 07 (Negative Acknowledge) is from older Modicon documentation; the turnaround delay after a broadcast (200 ms, within the 100 … 200 ms recalled from the serial line specification); the explanations of the exception codes are this tool’s own words.
- The serial link was tested with a simulated device, not with real hardware.
Questions
- Is register 40001 address 0 or 1?
- Address 0. On the wire a Modbus request carries a 0-based address. The numbers 40001, 30001, 10001 and 00001 are a convention of manuals and SCADA tools (from the Modicon days, not part of the protocol): the first digit names the table and the rest counts from 1. So holding register 40001 is address 0, 40108 is address 107, and the six-digit form 400001 … 465536 reaches every address. The builder shows both side by side.
- Why does my device answer with exception 02?
- Exception 02 (Illegal Data Address) means that the start address, or the start plus the quantity, is outside what the device has. The most common cause is an off-by-one between register numbers and addresses (40001 is address 0), or reading a block that crosses a gap in the device’s map. Exception 03 (Illegal Data Value) usually means a quantity outside 1 … 125 registers, and 01 a function the device does not support.
- How is the Modbus RTU CRC calculated?
- CRC-16/MODBUS: start with 0xFFFF; for each byte XOR it into the low byte, then eight times shift right and, when the bit shifted out was 1, XOR 0xA001 (the polynomial 0x8005 reflected). There is no final XOR. The result is sent low byte first: the CRC 0xCDC5 of 01 03 00 00 00 0A goes on the wire as C5 CD. The check value of the ASCII text “123456789” is 0x4B37.
- Can a web page talk to my Modbus device?
- Over a serial port, yes, in Chrome, Edge or Opera on a computer: Web Serial lets the page open a USB serial adapter after you choose it in the browser’s own window. The page sends a request only when you press Send or Poll, asks for a confirmation before every write and never writes in a loop. Modbus TCP needs a network socket, which a web page cannot open, so TCP frames can be built and read here but not sent.
- Why do I get no reply (timeout)?
- Most often the port settings differ from the device (baud, parity, stop bits), the unit id is wrong, the A and B wires of the RS-485 pair are swapped, or the bus lacks termination and biasing. A wrong framing (RTU against an ASCII device) also gives no reply. A device answers nothing at all to a broadcast (unit 0) and to a request with a CRC error.