Configure serial ports
This guide collects the settings and environment you need to open serial ports with the PDComm Modbus SDK. For the concepts see Serial line: RTU and ASCII; for hands-on practice see RTU and ASCII communication.
Configuration members
Section titled “Configuration members”| Member | Values | Description |
|---|---|---|
transport |
rtu, ascii |
Data bits are automatic: 8 for RTU, 7 for ASCII. |
role |
client, server, gateway |
A gateway also uses the TCP address. |
port |
Device path | When empty, connect fails with InvalidConfig. |
baud |
1 or more | Match the device. The specification’s default is 19200. |
parity |
even, odd, none |
Default even. With none, stop_bits must be 2. |
stop_bits |
1, 2 | |
unit |
1–247 | A server’s own address; a client’s default target |
timeout_ms |
1–60000 | How long a client waits for the whole response |
ascii_timeout_ms |
1–60000, default 1000 | Longest gap between ASCII characters |
turnaround_ms |
0–60000, default 100 | Wait after a broadcast before the next request |
The allowed character formats are 8E1, 8O1 and 8N2 for RTU and 7E1, 7O1 and 7N2 for ASCII. No parity with one stop bit fails with Invalid endpoint configuration. Flow control isn’t used.
Port names
Section titled “Port names”| OS | Example | Notes |
|---|---|---|
| Windows | COM3 |
The name under “Ports (COM & LPT)” in Device Manager |
| macOS | /dev/cu.usbserial-FT1234 |
Each device has a tty. and a cu. name; use the cu. (calling unit) name. |
| Linux | /dev/ttyUSB0, /dev/ttyACM0, /dev/ttyS0 |
Your user needs dialout group access. |
{"action":"serial_ports"} returns the serial devices the operating system knows. Compare the list before and after plugging in an adapter to find its name.
{"ok":true,"result":{"ports":["/dev/cu.Bluetooth-Incoming-Port","/dev/tty.Bluetooth-Incoming-Port","/dev/cu.usbserial-FTAJM0FK","/dev/tty.usbserial-FTAJM0FK"]}}Ports are opened exclusively. If another program, including another PDComm process, already has the port open, connect fails with Io(Other, "Unable to acquire exclusive lock on serial port"). A server and a client can’t share one port.
PDComm virtual serial ports
Section titled “PDComm virtual serial ports”To test serial communication without a cable, use the PDComm virtual serial tool. Tools covers installing and configuring it.
- Quick pair:
pdcomm-vserial pair --link-a <path> --link-b <path>creates two pseudo terminals joined by a null modem and places links at the given paths. Use it on macOS and Linux, and put a link path intoport. - Driver ports: ports created by the virtual serial driver show up in
serial_portslike real ports. - Fault injection: send
{"command":"inject","node":"a","fault":{"xor":1}}to a running virtual link to corrupt a character and reproduce a CRC error.
Keep in mind:
- A pseudo terminal has no UART. On macOS, PDComm opens a pseudo terminal without setting a speed, so the speed configured on the virtual link applies. Parity and stop bits are applied.
- The virtual link applies the format set in
connectfrom the first data after it, so you can send the first request right afterconnect. - Run equipment acceptance tests with the real wiring and device.
USB serial adapters
Section titled “USB serial adapters”- Latency timer: USB adapters hand received bytes over in batches. An FTDI adapter’s default latency timer is 16 ms, and measured response times include it. A PDComm client completes a response by its function-defined length and CRC, so batching doesn’t make it drop responses.
- Timestamps: serial
tracetimes are when the PC finished a read (host_io_batch). They don’t prove UART character gaps (t1.5, t3.5). - macOS FTDI driver: the macOS built-in FTDI driver doesn’t report parity errors to the operating system. Bytes with wrong parity arrive as they are, and the CRC check drops corrupted frames.
- RS-485 direction: two-wire RS-485 enables its driver only while transmitting. Most USB-RS485 adapters switch automatically; PDComm never toggles RTS itself.
Wiring
Section titled “Wiring”| Link | What to check |
|---|---|
| RS-232 | Transmit and receive must cross exactly once along the whole path: 2↔3, 3↔2, 5↔5 null modem between two 9-pin DTE connectors. No crossing, or two, means no response at all. |
| RS-485 two-wire | Connect D0/D1 (A/B) polarity, termination at both ends of the bus, biasing at one point and the common line as the device instructions say. Vendors sometimes label A and B the opposite way. |
| RS-232 to RS-485 | Can’t connect directly; use a converter. |
Choose timeouts
Section titled “Choose timeouts”timeout_ms must cover sending the request, the device’s processing and receiving the response. Make it larger for long responses.
| Example | Estimate |
|---|---|
| 9600 bit/s, 8E1, read 125 holding registers | 255 response bytes × 11 bits ÷ 9600 ≈ 292 ms, plus the request, device processing and USB latency |
| 19200 bit/s, 8E1, one register | 7 response bytes ≈ 4 ms; the device’s processing time usually dominates |
- Start from the response time in the device manual and add margin, typically a few hundred milliseconds to one second.
- Behind a gateway, give the TCP client a longer
timeout_msthan the gateway’s serial wait. - With broadcasts, make
turnaround_mslonger than the slowest device on the bus needs to process a write. The specification gives 100–200 ms as typical.
Next steps
Section titled “Next steps”- If nothing answers or you see CRC errors, follow Serial communication problems.
- JSON command reference lists every configuration member.