You wire a vision camera into a robot controller over Modbus TCP, and the link looks healthy: the digital and register inputs come alive, the node shows green, the camera's values read back cleanly. Then the first register write fails. The same register accepts a write from a desktop master tool, which makes it look like a robot problem. It is neither an address problem nor a wiring problem: the robot's register output leaves as function 06, write single register, and the camera's register map accepts only function 10, write multiple registers. This guide is for the engineer who owns that link. You will learn to read the exception for what it is, compare the two functions in bytes, and pick one of three fixes, each matched to a case.
The symptom, read correctly
The green node already tells you three things. The TCP session to the camera on port 502 is up, so IP address, subnet and cabling are right. Reads work, so function 03, read holding registers, is implemented and your unit ID matches the device. And the write came back as a Modbus exception — which is an answer, not a timeout: the server processed the request and refused it.
Exception code 01 is Illegal Function: the server does not permit the action the function code requests. The reply names the refused function by echoing it with its high bit set, so 0x86 means function 06 was refused and 0x90 would mean function 10 was. When the teach pendant reports the failure as a short code beside the register output, that 1 is this exception. Nothing is wrong with your register number or your value yet; you have used a verb the device does not implement.
The server side can be any device holding a register map — one of our smart cameras, a controller, a PLC. The MV-SC3050XC-16M-ATN-H, a 5 MP color vision sensor with a Fast Ethernet interface, is a typical example of the camera end of this failure.
- Interface
- Fast Ethernet
- Resolution
- 5 MP
- Sensor format
- 1/1.45"
- Shutter
- Global
Function 06 and function 10 are different verbs
Function 06 writes exactly one holding register: function code, register address, one 16-bit value. Function 10 writes a run of 1 to 123 registers in one request, bounded by the 253-byte PDU limit. The Modbus conformance classes put 03 and 10 in the baseline set and 06 in the extended set, so a server that ships without 06 stays within the specification — the client that can only send 06 is the one out of line. Support really is device by device: drive families exist where one model accepts both 06 and 10 and its sibling accepts only 06, and camera register maps have shipped that accept only 10. Some robot controllers specify their register outputs as write-single-register, so every value you enter leaves the controller as one 06 request.
| Function 06, write single | Function 10, write multiple | |
|---|---|---|
| What it writes | exactly one holding register | 1 to 123 consecutive registers |
| Request PDU | 5 bytes | 6 + 2 × N bytes |
| Value carried as | one 16-bit word | a byte count, then N words |
| Normal reply | echo of the request | start address and quantity |
| Conformance class | extended set | baseline set |
The mismatch is not a camera quirk: any Modbus server in the cell — a PLC, a drive, light controllers on a Modbus network — implements its own subset of write functions, and the register map is the authority on which. For the full frame layout, a byte-level tutorial on Modbus TCP function code 06 goes a level deeper; for the opposite move, an HMI configuration walkthrough for a function 10h multiple-register write shows the client-side switch on another class of device.
Worked example: one register write, robot to camera, in bytes
Inputs, each chosen or copied from the map: unit ID 1, register address 100 decimal, which is 0x0064 in the frame, value 7, and a transaction ID of 0x0001 the client picks freely and the answer echoes. Every Modbus TCP frame is a 7-byte MBAP header followed by the PDU, and the length field counts the unit ID plus the PDU:
The failing write. Length = 1 + 5 = 6, frame = 12 bytes:
00 01 00 00 00 06 01 06 00 64 00 07
The refusal. The exception PDU is the refused function with its high bit set, then code 01: 2 bytes, length = 1 + 2 = 3, frame = 9 bytes:
00 01 00 00 00 03 01 86 01
The working write. Function 10 with a quantity of 1: PDU = 1 + 2 + 2 + 1 + 2 × 1 = 8 bytes, byte count = 2 × 1 = 2, length = 1 + 8 = 9, frame = 15 bytes:
00 01 00 00 00 09 01 10 00 64 00 01 02 00 07
The acceptance. The reply echoes address and quantity, PDU = 5 bytes, frame = 12 bytes:
00 01 00 00 00 06 01 10 00 64 00 01
The decision rule this buys you: a 9-byte reply reading 86 01 to a 12-byte request containing 06 is the complete diagnosis. The server has no function 06 — address, value and timing are all innocent. Move to the fix.
Prove it from a master tool before touching the cell
- From a PC on the camera's subnet, open a Modbus TCP master session to the camera's address on port 502, with the map's unit ID.
- Read the target register with function 03 at the map's address, and check the value against what the camera's own interface shows.
- Write that register with function 06. The 0x86 01 reply is your failure reproduced on the bench, with the robot out of the loop.
- Write the same register with function 10 and a quantity of 1. The address-and-quantity echo is the pass.
- Write the whole block at the map's stated quantity. Some maps accept writes only at block granularity, and this step tells you the grouping the client must reproduce.
If steps 3 and 4 both fail with exception 02, illegal data address, your problem is the address base, not function support — read why the 40xxx register offset returns no data before going further.
The fix, case by case
Case 1 — the client can choose its write function. Group the values into consecutive registers and declare the write as a block. Clients that support block writes stop sending 06 the moment a signal spans more than one register. Where only one word must change and the map is block-oriented, use read-modify-write: read the block with 03, patch your word, write the block back with 10 at the stated quantity. Layout guidance for grouping many values is in sizing the vision coordinate array over Modbus TCP.
Function 22, mask write, would let you set chosen bits of one register without the read first — how the mask write register algorithm works shows the mechanics — but it is the least-implemented write in the field, and a server with no 06 almost never has 0x16 either.
Case 2 — the client is locked to 06. Some robot firmwares give register outputs no function choice at all. Put a Modbus-capable middle device in the path: a vision controller or a small PLC accepts the robot's 06 writes into its own register table and re-issues them to the camera as 10. The vision controller Modbus integration guide covers that role end to end. Keep safety functions out of this path entirely — an interlock or E-stop stays hardwired, because a refused or lost register write must never be the link that fails unsafe. If the camera also speaks raw TCP, trigger and pass/fail messaging over TCP is a simpler road with no function codes at all.
For the middle device, the MV-VC3301H-128G66 brings 4 built-in light channels and 5+ LAN ports, and the MV-VC5525-256G70-NN brings 8 built-in light channels, PoE camera ports and 32 GB of memory.
- LAN ports
- 5+ LAN ports
- USB 3 ports
- 3-4 USB 3 ports
- LAN ports
- 5+ LAN ports
- USB 3 ports
- 3-4 USB 3 ports
Case 3 — the server's maker can change it. When the register map states that writes use function 10, that is the design, not a defect; a firmware change is the maker's call and arrives on their schedule. Ship case 1 or case 2 now and treat a future firmware with 06 as a bonus.
Checks before you commit
- Unit ID in every frame matches the map; a foreign unit ID is dropped by many servers, which looks like a timeout.
- Address base agreed in writing: 0-based wire addresses on the line, 4xxxx display numbers on the schematic.
- Write quantity equals the map's block size, and block writes start where the map says they must.
- Exactly one master writes each block, with polls and writes on a single scheduler — one poll loop for many cameras on one PLC CPU shows the pattern.
- The commissioning record names, per device, the read function, the write function and the block size, so the next integration starts from facts.
- One captured frame pair — the 86 01 refusal and the 10 acceptance — filed with that record.
When it is not the function code
Exception 02, illegal data address. The address base or the quantity. The 4xxxx offset is the usual culprit, and the master-tool read in step 2 catches it before you blame the robot.
Exception 03, illegal data value. The value sits outside the map's allowed range. A holding register carries 0 to 65535, and many maps cap a command word far below that.
No reply at all — node grey, timeouts. Unit ID, subnet or cabling, before any protocol question; fixing IP and subnet mismatches on a smart camera is the shorter path.
Writes pass on the bench, fail in production. A second master is writing the same block during running hours. Back to one writer, as in the checks above.
Decide from the failure you captured: client flexible — group the registers and send 10; client fixed — put a vision controller in the middle; server promised a firmware change — ship one of the first two anyway. To size the middle route, start from the camera finder and bring the captured refusal to our contact page — an 86 01 frame and the register map are the whole brief.
Vision computers and fanless industrial PCs
190 models · from $1,119.00Questions
What does Modbus exception code 01 on a camera write mean?
Illegal Function: the server refuses the function code itself. Remember the triad when a write bounces — 01 means the function, 02 means the address, 03 means the value. Only 01 is cleared by changing which function you send; fixing the register number or the data leaves it untouched. The reply echoes your function with its high bit set, so the refused verb is named in the response.
Why do reads work while register writes fail on the same node?
Because the register-input and register-output nodes look identical in the client UI, the working read feels like proof the whole path is fine. It only proves function 03 and the unit ID. Writes are separate functions — 06 or 10 — and a server may implement either, both, or 10 alone. Treat the read as wiring proof and the write as an untested function until you probe it.
How do I write one register with function 10?
Read the block with 03, patch the single word in your buffer, and write the whole block back with 10 at the map's quantity. The request is only 3 bytes longer than the equivalent 06 frame. Keep one writer: a second master updating the block between your read and your write loses its change when your frame lands.
Can the camera be configured to accept function 06?
Only through its firmware or register-map options, and the answer is usually no: a one-register function 10 frame performs the same write, so makers see little reason to add 06. Ask, but in parallel ship the client-side fix — grouped block writes, or a middle device that accepts 06 and sends 10 — because the integration should not wait on a firmware roadmap.
Is mask write, function 0x16, a way around a block-oriented map?
In theory yes — mask write sets and clears chosen bits of one register without reading the block first. In practice it is the least-implemented write function in the field, and a server that never coded 06 has almost certainly not coded 0x16. Probe it with a master tool if you like; expect the same exception 01.
Does a green register-output node prove the write path works?
No. Green means the TCP session to port 502 opened and the client accepted the signal configuration. It says nothing about which function the client sends or which the server implements — a link can stay green all day while every write returns an exception. Only a deliberate test write or a captured frame pair proves the path.


