SANPO USB to RS485

The SANPO USB to RS485 protocol controls RS485 devices from Windows or Linux and forwards RS485 data without requiring an additional driver. The raw RS485 data is wrapped with a SANPO header and trailer over the USB management serial port. These extra bytes are used only by the board; the RS485 device receives the raw data without a SANPO header or trailer.

Connection and Communication Settings

After connecting the board over USB, six serial ports appear: two management ports and four dedicated RS485 passthrough ports. In this protocol mode, send RS485 data through the two management ports, not the four dedicated passthrough ports; see RS485 Passthrough Mode for the latter. One management port accesses RS485-1/2 and the other accesses RS485-3/4. On first use, connect only one device to confirm the USB-port-to-physical-interface mapping.

On Linux, you can run the Python serial-port identification example to identify the four RS485 serial ports.

The factory RS485 settings are 4 Mbps, one stop bit, no parity, and eight data bits. However, some Linux serial enumeration may change the live communication settings. Therefore, in protocol mode, explicitly send AT+SETRS485 before sending application data to reapply the RS485 settings. See Communication Settings for details.

Send AT+ commands in text mode with the line ending set to CRLF. Do not send the characters \r\n as ordinary text.

AT+SETRS485=<baudrate>,<stop_bits>,<parity>,<data_bits>

For example, configure the common Unitree motor setting of 4 Mbps, 8-N-1:

AT+SETRS485=4000000,1,0,8

Frame Format

Send and receive use the same outer format:

Field

Length

Description

Header

2 bytes

Fixed 52 54, or RT

Channel

1 byte

RS485 interface number

Data length

1 byte

Raw RS485 data length, up to 64 bytes

Data

0-64 bytes

Raw command or reply defined by the device vendor

Trailer

2 bytes

Fixed 0D 0A

When sending to the RS485 bus, the board removes RT, Channel, length, and the trailer and sends only the raw data. On a device reply, it adds the RT wrapper and Channel identifies the first or second local interface.

Unitree GO-M8010 Example

Raw Unitree command:

FE EE 11 00 00 00 00 00 00 00 00 00 00 00 00 18 7C

Send these 17 bytes to Channel 2:

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 interface and 11 is decimal 17 in hexadecimal. The RS485 bus receives only the 17-byte Unitree command beginning with FE EE.

A motor reply may look like:

52 54 02 10 FD EE ...16 bytes of motor feedback... 0D 0A

Complete example: USB to RS485 Unitree motor example

Every time it opens the management port, the example explicitly sends AT+SETRS485=4000000,1,0,8 before sending motor frames. This restores the protocol-mode UART to the 4 Mbps, 8-N-1 setting required by the Unitree GM8010 even if a dedicated RS485 passthrough port was previously opened with another baud rate. The identical setting is reapplied to both RS485 interfaces on the current MCU without writing another Flash record.

Windows example:

python usb2rs485_unitree_demo_v8.py --port COM9 --motors 1 --channel 2

Linux example:

sudo python3 usb2rs485_unitree_demo_v8.py --port /dev/ttyACM0 --motors 1 --channel 2

Reply Handling

One RS485 receive event represents one continuous block of received data and is not guaranteed to be one complete motor-protocol frame. Channel identifies the interface, but the host must reassemble complete replies using the motor protocol’s header, length, and checksum.

USB is also a byte stream. A single read may contain a partial frame or multiple frames. Find 52 54, read the length field, and wait for the complete 6 + data_length bytes.

Troubleshooting

Symptom

Action

The command is sent to both RS485 interfaces

Channel is 0x00; select a specific channel

No reply after sending

Check USB port, Channel, RS485 settings, device ID, command checksum, A/B wiring, and power

AT+SETRS485? reports 4 Mbps but protocol mode still receives no reply

The saved value may be correct while a passthrough port changed the live UART setting. Send AT+SETRS485=4000000,1,0,8 again; the GM8010 example on this page does this automatically

Reply Channel is 1/2 instead of 3/4

Replies use local numbering on the current MCU; this is normal

Reply is split into multiple blocks

Reassemble the outer frame using its RT length field, then parse the device-protocol Data