04. RS-232 Serial Communication
RS-232 is the oldest serial link, connecting the robot and a host (PC·PLC) 1:1 with one cable. Lesson 3's CWRITE/CREAD and {}·, packet format carry over unchanged — only the physical layer and COPEN's first argument (ETH→SER) change. We verify the packet framing with pure Python (no port), and practice real serial transfer with com0com virtual COM ports.
What you'll learn
- 1Explain RS-232 physical traits (1:1 point-to-point, TX↔RX cross + common GND, matched baud)
- 2Know COPEN(SER)'s first argument means serial, vs TCP/IP's ETH
- 3Encode/decode {}·, packets and compare with non-format (ASCII decimal)
- 4Run pyserial echo over a com0com virtual COM pair (COM5↔COM6)
Introduction
Unlike Ethernet where many nodes share a wire, only two devices connect directly with one cable. The command flow and packet format are identical to lesson 3's TCP/IP — only COPEN's first argument changes ETH→SER.
Key concepts
1) 1:1 point-to-point + TX↔RX cross
Robot controller Host (PC/PLC)
TX ─────────────────► RX
RX ◄───────────────── TX ← cross
GND ───────────────── GND ← common groundBoth sides must use the same baud rate. There's no auto-negotiation like Ethernet — if one is 9600 and the other 19200, characters corrupt. Set it manually.
2) TCP/IP vs RS-232
| Aspect | TCP/IP | RS-232 |
|---|---|---|
| COPEN 1st arg | ETH | SER |
| Topology | many-to-many·network | 1:1 point-to-point |
| Wiring key | hub/switch | TX↔RX cross + common GND |
| Speed negotiation | automatic | manual (matched baud) |
| Packet format | { }·,·non-format | same |
Key: the commands and packet format are the same; only the physical layer and COPEN's first argument differ. Non-format mode drops the start/end·separators and reads each byte as ASCII CODE (decimal): "AB"→[65,66].
Core example
Implement the RS-232 packet encode/decode in pure Python and round-trip-verify it (no port needed).
def encode_packet(values):
return "{" + ",".join(str(v) for v in values) + "}" # [123,456] -> "{123,456}"
def decode_packet(packet):
return [int(t) for t in packet.strip().strip("{}").split(",")]
encode_nonformat = lambda text: [ord(ch) for ch in text] # "AB" -> [65, 66]# After making a com0com virtual COM pair (COM5↔COM6) (optional)
python ../../_shared/serial_echo.py --port COM6 --baud 9600 # Terminal A echo
python ../../_shared/serial_client.py --port COM5 --baud 9600 --value 123 # Terminal B
# Both --baud must match. One at 19200 → corrupt or b'' replyReal-hardware mapping: serial.Serial('COM5',9600)↔COPEN(SER), ser.write↔CWRITE, ser.read↔CREAD, ser.close↔CCLOSE. com0com is a virtual port pair where writing one side is read on the other — a software stand-in for a cross cable.
Common mistakes
Q. The reply comes back as b'' (empty) / characters corrupt.
A. The echo server isn't up, or baud mismatch. Start the echo server first and set both --baud the same (9600), keeping the default 8N1. RS-232 has no auto-negotiation.
Q. SerialException: could not open port 'COM6'.
A. The com0com pair isn't made, a port typo, or another program holds the port. Check COM5/COM6 in Device Manager and close other serial programs.
Q. Nothing shows on the HRSS comm screen.
A. "Show message" is unchecked in the RS-232 settings (off by default). Check it before testing.
Summary
- RS-232 is 1:1 point-to-point; wiring key is TX↔RX cross + common GND, and matched baud on both sides
- The command flow (COPEN→CWRITE→CREAD) and packet format ({ }·,·non-format) are identical to TCP/IP
- Only the physical layer and COPEN's first argument (ETH→SER) change
- com0com reproduces real serial transfer on a PC
Exercises
- Round-trip-verify [123,456] and [90000,-45100,30]
- Change one side's baud to 19200 to reproduce corruption, and explain why
- Convert "AB" to [65,66] and back with non-format
All lecture materials and example code (with simulators, homework, and answers) are openly available on GitHub.
View on GitHub ↗