# SANPO USB to RS485 SANPO USB to RS485 lets a PC select one of RS485-1/2/3/4. The host places a raw device command inside an `RT` wrapper. The board only selects the interface and forwards the data; it does not change the motor protocol. To send unwrapped data without a Channel field, use [RS485 Raw Passthrough](rs485_passthrough). Raw passthrough requires at least 3 ms of idle time between commands; use the `RT` wrapper on this page for continuous high-rate real-time control. ## Connection and Communication Settings A complete board normally exposes two USB serial ports. One accesses RS485-1/2, and the other accesses RS485-3/4. For first use, connect one device to identify the USB-to-interface mapping. Factory defaults are 4 Mbps, one stop bit, no parity, and eight data bits. Send `AT+SETRS485?` before use and change the settings through [Communication Settings](baudrate_config) when necessary. The bitrate selected in a USB serial application does not change the RS485 bus. ## Select an RS485 Channel | Current USB port | Channel | Target | | --- | --- | --- | | Port for RS485-1/2 | `0x01` | RS485-1 | | Port for RS485-1/2 | `0x02` | RS485-2 | | Port for RS485-3/4 | `0x03` | RS485-3 | | Port for RS485-3/4 | `0x04` | RS485-4 | | Either USB port | `0x00` | Both RS485 interfaces on the current MCU | For transmission, `1/3` select the first local interface and `2/4` select the second. Replies use local Channel: `0x01` for the first and `0x02` for the second. ## RT Frame Format Transmit and receive use the same wrapper: | Field | Length | Description | | --- | ---: | --- | | Header | 2 bytes | Fixed `52 54` (`RT`) | | Channel | 1 byte | RS485 interface number | | Data length | 1 byte | Raw RS485 data length, up to 64 bytes | | Data | 0 to 64 bytes | Raw command or feedback defined by the device manufacturer | | Tail | 2 bytes | Fixed `0D 0A` | When transmitting to RS485, the board removes `RT`, Channel, length, and tail and sends only the raw Data field. When a device replies, the board adds an `RT` wrapper and sets Channel to the first or second local interface. ## Unitree GO-M8010 Example Raw Unitree command: ```text FE EE 11 00 00 00 00 00 00 00 00 00 00 00 00 18 7C ``` Wrap the 17 bytes for Channel 2: ```text 52 54 02 11 FE EE 11 00 00 00 00 00 00 00 00 00 00 00 00 18 7C 0D 0A ``` `02` is the target and `11` is hexadecimal for 17. The RS485 bus still carries only the 17 raw bytes beginning with `FE EE`. A motor reply has a form similar to: ```text 52 54 02 10 FD EE ...16 bytes of motor feedback... 0D 0A ``` Example: [USB to RS485 Unitree motor](https://gitcode.com/sanpo/robot/blob/unified-main/products/spine/v6/demo/rs485/usb2rs485_unitree_demo_v6.py) Windows: ```powershell python usb2rs485_unitree_demo_v6.py --port COM9 --motors 1 --channel 2 ``` Linux: ```bash sudo python3 usb2rs485_unitree_demo_v6.py --port /dev/ttyACM0 --motors 1 --channel 2 ``` ## Reply Handling One RS485 receive event represents one continuous block and is not guaranteed to contain exactly one complete motor-protocol frame. Channel identifies the source interface, but the host must still reassemble complete feedback using the motor protocol's header, length, and checksum. USB is also a byte stream. One read may return part of an `RT` frame or several frames. Find `52 54`, read the length field, and wait for the complete `6 + data-length` bytes. ## Troubleshooting | Symptom | Action | | --- | --- | | Command is sent on both RS485 interfaces | Channel is `0x00`; select a specific channel | | No feedback | Check USB mapping, Channel, RS485 settings, device ID, command checksum, A/B wiring, and power | | Reply Channel shows 1/2 instead of 3/4 | Replies use local numbering; this is normal | | Reply does not begin with `52 54` | RAW replies are enabled; send `AT+RS485RAW=0` | | Need to send raw RS485 data directly | Enable RAW replies as described in [RS485 Raw Passthrough](rs485_passthrough) | | Reply is split into several blocks | Reassemble the `RT` wrapper by its length, then parse Data according to the device protocol |