What is a Modbus RTU CRC Error?
In the Modbus RTU protocol, every frame transmitted across an RS-485, RS-232, or RS-422 serial line ends with a two-byte Cyclic Redundancy Check (CRC-16). The transmitting node calculates this checksum over the entire message (Slave Address, Function Code, and Data bytes).
When the receiving node picks up the frame, it recalculates the CRC across the received payload and compares its calculated value against the two CRC bytes sent at the end of the packet:
- Match: The frame is intact. The slave processes the command or the master records the telemetry.
- Mismatch (CRC Error): The frame suffered bit corruption, noise interference, or timing deformation. Per Section 4.2 of the Modbus Serial Line Specification, the receiving device must silently discard corrupted frames without sending an error reply, resulting in a master timeout.
The Modbus CRC-16 Algorithm Explained
The standard Modbus RTU CRC calculation uses the CRC-16-IBM (also known as CRC-16-Modbus) specification:
- Initial Preload Value:
0xFFFF(all 16 bits set to 1) - Generator Polynomial:
0xA001(the bit-reversed representation of the algebraic polynomialx^16 + x^15 + x^2 + 1/0x8005) - Shift Direction: Right shift (Least Significant Bit shifted first)
- Byte Order on the Wire: Low Byte First (LSB), followed by High Byte (MSB)
def calculate_modbus_crc(data: bytes) -> bytes:
crc = 0xFFFF
for byte in data:
crc ^= byte
for _ in range(8):
if crc & 1:
crc = (crc >> 1) ^ 0xA001
else:
crc >>= 1
# Modbus RTU transmits Low Byte first, then High Byte
low_byte = crc & 0xFF
high_byte = (crc >> 8) & 0xFF
return bytes([low_byte, high_byte])
# Example: Read 2 Holding Registers from Slave 1 starting at address 0
# Request frame: [Slave: 0x01, Function: 0x03, Addr Hi: 0x00, Addr Lo: 0x00, Qty Hi: 0x00, Qty Lo: 0x02]
frame = bytes([0x01, 0x03, 0x00, 0x00, 0x00, 0x02])
crc = calculate_modbus_crc(frame)
print(f"Frame with CRC: {list(frame + crc)}")
# Output: [1, 3, 0, 0, 0, 2, 196, 11] -> CRC bytes: 0xC4, 0x0B
Top 6 Causes of Modbus CRC Errors (and Solutions)
1. Byte Order Inversion (Endianness Bug in Software)
This is the single most common software cause of CRC errors in custom microcontrollers, Node.js scripts, and Python gateways. The Modbus specification dictates that the 16-bit CRC must be sent Low Byte first, then High Byte.
If your code calculates 0xC40B and transmits [0x0B, 0xC4] instead of [0xC4, 0x0B], every single packet will be rejected by standard industrial PLCs as a CRC error.
Solution: Swap the two CRC bytes in your serialization routine and verify using a known packet analyzer.
2. Missing 120-Ohm RS-485 Line Termination
In an RS-485 daisy-chain network, electrical pulses travel along the twisted pair at approximately two-thirds the speed of light. When the signal hits an open (unterminated) wire end, it reflects back into the cable, creating destructive interference that mangles digital square waves.
This signal reflection causes jitter on byte edges, causing the receiver's UART to read a 0 as a 1 or vice-versa, which instantly invalidates the CRC checksum.
Solution: Install a 120-Ohm, 1/4-Watt metal film resistor across the A (+) and B (-) lines at the two physical ends of the bus (the first device and the last device). Never place termination resistors on middle drops.
3. Electrical Noise & Electromagnetic Interference (EMI)
In factory environments, unshielded RS-485 cables routed parallel to high-voltage AC lines, Variable Frequency Drives (VFDs), or welding equipment pick up severe inductive spikes. A transient 50V spike across the differential pair will flip serial bits mid-packet.
Solution:
- Always use shielded twisted-pair (STP) cabling (such as Belden 9841 or 3105A).
- Ground the cable shield at one end only (typically at the PLC/Master) to prevent ground loop currents.
- Maintain a minimum physical separation of 30 cm (12 inches) between RS-485 communication cables and high-power AC motor leads.
4. Baud Rate, Parity, or Stop Bit Mismatches
If your Master is configured for 19200, 8-E-1 (Even Parity) and the Slave is set to 19200, 8-N-1 (No Parity) or 9600 bps, the receiver's UART will misinterpret byte boundaries.
The receiver might assemble 7 out of 8 bits correctly, but the resulting bytes will be completely garbled, guaranteeing a CRC failure and framing error.
Solution: Audit all devices on the RS-485 loop. Every single slave must share the identical baud rate (e.g., 9600, 19200, 38400, 115200), parity (None, Even, Odd), and stop bits (1 or 2).
5. Inter-Character Timing Violations (3.5 Character Rule)
The Modbus RTU standard specifies strict timing constraints:
- Inter-character silence: No more than 1.5 character times (
t1.5) of silence between consecutive bytes within a frame. - Frame demarcation: At least 3.5 character times (
t3.5) of complete silence before and after a frame.
If a non-real-time operating system (such as standard Windows or Linux without RT-PREEMPT) pauses thread execution mid-transmission, a 2 millisecond delay will cause the slave's hardware UART to believe the frame has ended prematurely. When the remaining bytes arrive, the slave treats them as a brand-new malformed frame, generating a CRC error.
6. Ground Loops & Common-Mode Voltage Exceeding Limits
Standard RS-485 transceivers can only tolerate a common-mode ground voltage between -7V and +12V. If two buildings or distant electrical cabinets have separate earth grounds, potential differences of 20V to 50V can develop across the communication line, saturating the differential receiver and corrupting bits.
Solution: Run an isolated 3-wire RS-485 network (A, B, and common reference ground) and install galvanic isolation repeaters between different ground planes.
Step-by-Step Diagnostic Workflow
Step 1: Isolate Hardware vs Software with ModbusSimulator
Connect your polling software or PLC to ModbusSimulator running on a local PC using a virtual COM port pair (such as com0com or tty0tty). If the simulator processes requests with zero CRC errors, your software and CRC calculation algorithms are 100% correct—the problem is purely electrical wiring, noise, or baud rate settings on the factory floor.
Step 2: Sniff Raw Hex Frames with a Serial Monitor
Use a USB-to-RS485 adapter and a serial monitor (such as RealTerm or Wireshark with USBPcap) to log the raw hexadecimal bytes on the wire. Extract the data bytes and run them through our Python CRC script above. If the software calculation matches the received bytes, the master software has a buggy validation routine; if it differs, the wire corrupted the bytes.
Step 3: Check Waveform Integrity on an Oscilloscope
Connect an oscilloscope across lines A and B. A clean RS-485 signal should show sharp square waves with differential amplitude between 1.5V and 5V. If you see ringing, rounded corners, or distorted spikes, you have missing termination resistors or severe cable capacitance.
Troubleshooting Matrix: Error Symptoms & Root Causes
| Observed Symptom | Primary Root Cause | Corrective Action |
|---|---|---|
| 100% of packets fail CRC check | Inverted CRC byte order (MSB/LSB swapped) or wrong polynomial | Verify LSB is transmitted first; verify 0xA001 polynomial |
| Occasional CRC errors during motor start | EMI noise from VFDs / heavy inductive loads | Use shielded twisted pair (STP), ground shield at one end, separate conduit |
| Errors increase at higher baud rates (38400+) | Missing 120-Ohm termination resistors | Add 120Ω resistor at both physical ends of RS-485 bus |
| Slave never responds to polls | CRC error on incoming poll (silent discard by slave) | Check slave baud rate, unit ID, and test with Free Modbus Simulator |
| Errors increase with cable distance | Cable reflection or common-mode ground voltage offset | Install RS-485 optical isolator and verify 120Ω termination |
Eliminate Modbus Errors Fast with ModbusSimulator
Simulate up to 247 Modbus RTU & TCP slave devices simultaneously. Test register maps, verify CRC checksums, and debug PLC communications before field deployment.
Frequently Asked Questions
What is a Modbus CRC Error?
A Modbus CRC error occurs when the receiving device calculates a 16-bit checksum on an incoming Modbus RTU frame and the result does not match the 2-byte CRC checksum transmitted at the end of the packet. Mismatched frames are discarded immediately to protect industrial systems from corrupted data.
Why do Modbus RTU frames require a CRC while Modbus TCP does not?
Modbus RTU operates on raw serial physical layers (RS-485/RS-232) without underlying network error correction. Modbus TCP relies on standard Ethernet (32-bit CRC) and TCP (16-bit checksum) to guarantee packet integrity, making an application-level CRC redundant.
What is the standard byte order for Modbus CRC-16?
In standard Modbus RTU, the 16-bit CRC is transmitted Low Byte (LSB) first, followed by High Byte (MSB). Inverting this byte order is one of the most common firmware programming mistakes.
How does electrical noise on RS-485 cause Modbus CRC errors?
Electromagnetic interference from motors, VFDs, or unshielded cables induces voltage spikes that flip binary bits in transit. Flipping even a single bit completely changes the calculated CRC-16 value, causing the receiver to reject the frame.
How do 120-Ohm termination resistors eliminate CRC errors?
At high baud rates or over long cable runs, electrical signals reflect back from unterminated line ends like an acoustic echo, distorting digital square waves. Installing 120-ohm resistors at the two physical ends of the RS-485 bus absorbs signal reflections.
How can I test if a Modbus CRC error is caused by hardware or software?
Use ModbusSimulator on a local PC over virtual COM ports. This completely eliminates physical wiring and noise. If the CRC error disappears in simulation, your code is fine and the issue is hardware; if it persists, your software CRC calculation or endianness is faulty.