USB moves data in scheduled batches. A USB-serial adapter therefore does not pass every received byte to the PC immediately; it sends a batch when its buffer fills or a timer expires. FTDI chips call this the «Latency Timer», 16 ms by default.
What goes wrong
- Frames split: at 9600 bps a 17-byte request takes about 19 ms on the wire. If the adapter hands data over every 16 ms, the PC gets two chunks with a gap longer than 3.5 characters (4 ms), so the RTU frame splits in two and both halves fail the CRC.
- Frames merge: several short replies can arrive in one chunk and look like one frame.
- Replies arrive late: a request-response round trip can take tens of milliseconds longer. A master with a tight timeout reports «no response».
What to do
- FTDI: Device Manager → Ports (COM) → port Properties → Port Settings → Advanced → lower Latency Timer from 16 to 1–4 ms. Other chips (CH340, CP210x …) differ by driver.
- Frame by length, not time: Modbus requests reveal their length from the function code (reads and single writes 8 bytes, multiple writes 7 + byte count + 2). PortDock Modbus Slave reassembles requests this way and uses a 20 ms minimum gap on USB ports.
- Give time-based framing more room: with USB adapters set the idle gap to about 20 ms. PortDock Serial points this out on USB ports.
- Give the master's timeout headroom: device response time + adapter latency (up to 2 × latency timer per round trip).
How to recognise it
If one request appears as two lines in the log and both show «CRC FAIL», it was split. Line timestamps clustering at roughly 16 ms steps point to the latency timer.
Published 2026-10-17