PySerial
PySerialDocs

RS-485

Configure RS-485 half-duplex communication with PySerial. Set up RS485Settings, RTS toggling, and wiring for multi-drop serial networks.

PySerial supports RS-485 mode through serial.rs485.RS485Settings. This configures the kernel driver to toggle RTS automatically for half-duplex transmit/receive switching.

RS-485 Basics

RS-485 is a differential signaling standard for multi-drop serial networks. Unlike RS-232 (point-to-point, short range), RS-485 supports up to 32 devices on a single bus at distances up to 1200 meters.

FeatureRS-232RS-485
TopologyPoint-to-pointMulti-drop bus
Max devices232 (standard), 256 (high-impedance)
Max distance~15 m~1200 m
SignalingSingle-endedDifferential
DuplexFullHalf (2-wire) or full (4-wire)

Wiring

Two-wire RS-485 (half-duplex) uses three connections:

PinNameFunction
AData- (inverting)Differential pair, negative
BData+ (non-inverting)Differential pair, positive
GNDSignal groundCommon reference

Connect A to A, B to B, and GND to GND between all devices. Add 120-ohm termination resistors at both ends of the bus for runs over a few meters.

Enable RS-485 Mode

import serial
import serial.rs485

ser = serial.Serial("/dev/ttyUSB0", 9600, timeout=1)
ser.rs485_mode = serial.rs485.RS485Settings(
    rts_level_for_tx=True,
    rts_level_for_rx=False,
    delay_before_tx=0.0,
    delay_before_rx=0.0,
)

ser.write(b"\x01\x03\x00\x00\x00\x0A\xC5\xCD")  # Modbus query example
response = ser.read(25)
print(response.hex())
ser.close()

When rs485_mode is set, the driver asserts RTS before transmitting and de-asserts it after. Your code just calls write() and read() normally.

Log RS-485 bus data automatically

TofuPilot records test results from your PySerial scripts, tracks pass/fail rates across RS-485 connected devices, and generates compliance reports. Free to start.

RS485Settings Parameters

ParameterDefaultPurpose
rts_level_for_txTrueRTS state during transmission
rts_level_for_rxFalseRTS state during reception
loopbackFalseEnable RS-485 loopback mode
delay_before_txNoneSeconds to wait after asserting RTS before sending
delay_before_rxNoneSeconds to wait after sending before de-asserting RTS

RTS Timing

Some RS-485 adapters need time to switch direction. If you're dropping the first byte of a response or the last byte of a transmission, adjust the delays:

import serial
import serial.rs485

ser = serial.Serial("/dev/ttyUSB0", 9600, timeout=1)
ser.rs485_mode = serial.rs485.RS485Settings(
    rts_level_for_tx=True,
    rts_level_for_rx=False,
    delay_before_tx=0.002,   # 2 ms before transmitting
    delay_before_rx=0.002,   # 2 ms after transmitting, before receiving
)

Start with 1-2 ms and increase if you still get garbled data. Most USB-to-RS485 adapters work with zero delay.

Platform Support

Linux

Linux has native RS-485 support through ioctl. PySerial uses this when available. You can also configure RS-485 mode system-wide with rs485conf:

# Check current RS-485 settings
rs485conf /dev/ttyS1

# Enable RS-485 with RTS-on-send
rs485conf /dev/ttyS1 --rs485=1 --rts-on-send=1 --rts-after-send=0

Not all UART drivers support rs485conf. Built-in UARTs (e.g. on Raspberry Pi, BeagleBone) usually do. USB adapters rely on PySerial's software RTS toggling.

Windows and macOS

No native RS-485 kernel support. PySerial toggles RTS in software, which works but has higher latency. For time-critical applications on these platforms, use a USB-to-RS485 adapter with built-in direction control (auto-direction adapters with TXE pin).

USB-to-RS485 Adapters

Common adapter chips and their behavior:

ChipAuto-directionNotes
FTDI FT232R + MAX485NoNeeds RTS toggling via PySerial
FTDI FT232HOptionalDepends on breakout board design
CH340 + MAX485NoCheap, works fine with RTS toggling
USB-RS485 (auto)YesBuilt-in direction control, no RTS needed

With auto-direction adapters, you don't need rs485_mode at all. Just open the port and read/write normally. The adapter handles TX/RX switching in hardware.

Multi-Device Polling

RS-485 buses commonly use a master-slave (polling) pattern. The master sends a request with a device address, and only the addressed device responds.

import serial
import serial.rs485
import struct

def poll_device(ser, address, register, count):
    """Send a Modbus-style read request and return raw response bytes."""
    # Build request: address + function(0x03) + register + count
    request = struct.pack(">BBHH", address, 0x03, register, count)
    # Append CRC (simplified, use pymodbus for production)
    crc = 0xFFFF
    for byte in request:
        crc ^= byte
        for _ in range(8):
            if crc & 0x0001:
                crc = (crc >> 1) ^ 0xA001
            else:
                crc >>= 1
    request += struct.pack("<H", crc)

    ser.write(request)
    # Response: address(1) + function(1) + byte_count(1) + data(2*count) + crc(2)
    expected_len = 3 + 2 * count + 2
    return ser.read(expected_len)

ser = serial.Serial("/dev/ttyUSB0", 9600, timeout=0.5)
ser.rs485_mode = serial.rs485.RS485Settings()

for addr in range(1, 5):
    resp = poll_device(ser, addr, 0x0000, 2)
    if resp:
        print(f"Device {addr}: {resp.hex()}")
    else:
        print(f"Device {addr}: no response")

ser.close()

For real Modbus work, use the pymodbus library instead of computing CRCs manually. See the Modbus RTU page.

Troubleshooting

No response from devices. Check A/B wiring (swapped A and B is the most common mistake). Some devices label them differently (D+ vs Data+).

Garbled first/last bytes. Increase delay_before_tx or delay_before_rx. The adapter may not switch direction fast enough.

Works at low baud, fails at high baud. Add termination resistors (120 ohm between A and B) at both ends of the bus. Long cables without termination cause reflections at higher speeds.

Permission denied on Linux. Add your user to the dialout group:

sudo usermod -aG dialout $USER

Log out and back in for the group change to take effect.

On this page

Deploy your PySerial test scripts with TofuPilot

Trusted by Lyft, Cobot, Pacific Defense, and more.

TofuPilot provides dashboards and analytics to track serial device testing at scale.

TofuPilot
Get Started