Skip to main content

Transports

Overview

The SDK exposes four transport constructors:
ConstructorProtocolUse Case
Controller(channel)SocketCANStandard CAN 2.0, most common
Controller.from_socketcanfd(channel)CAN-FDHigh-bandwidth, Hexfellow motors
Controller.from_dm_serial(port, baud)SerialDamiao serial bridge adapter
Controller.from_dm_device(device_type, channel)DM_Device SDKDamiao USB2CANFD / USB2CANFD_DUAL / LINKX4C adapters

SocketCAN (Standard CAN)

The default transport for most motor vendors. Linux uses SocketCAN directly, and Windows/macOS use the PCAN backend with canX channel aliases.

Usage

from motorbridge import Controller

# Open standard CAN interface
with Controller("can0") as ctrl:
    motor = ctrl.add_damiao_motor(0x01, 0x11, "4340P")
    # ... control motor

Supported Vendors

  • Damiao (all models)
  • RobStride
  • MyActuator
  • HighTorque

System Setup (3 Platforms)

Linux (SocketCAN):
# Configure CAN interface at 1M bitrate
sudo ip link set can0 type can bitrate 1000000
sudo ip link set can0 up

# Increase TX queue to prevent buffer overflow
sudo ifconfig can0 txqueuelen 1000
macOS (PCAN via PCBUSB):
# Verify PCBUSB runtime is available
python3 -c "import ctypes; ctypes.CDLL('libPCBUSB.dylib'); print('PCBUSB load OK')"

# Run a scan check on can0
motorbridge-cli scan --vendor damiao --transport auto --channel can0 --start-id 1 --end-id 16
Windows (PCAN):
# Verify PCAN runtime is available
python -c "import ctypes; ctypes.CDLL('PCANBasic.dll'); print('PCANBasic load OK')"

# can0@1000000 maps to PCAN_USBBUS1
motorbridge-cli scan --vendor damiao --transport auto --channel can0@1000000 --start-id 1 --end-id 16

Multiple CAN Interfaces

# Control motors on different CAN buses
with Controller("can0") as ctrl0:
    motor0 = ctrl0.add_damiao_motor(0x01, 0x11, "4340P")

with Controller("can1") as ctrl1:
    motor1 = ctrl1.add_robstride_motor(127, 0xFD, "rs-06")

CAN-FD (SocketCAN-FD)

Extended CAN with larger payload and higher bandwidth. Required for some vendors.

Usage

from motorbridge import Controller

# Open CAN-FD interface
with Controller.from_socketcanfd("can0") as ctrl:
    motor = ctrl.add_hexfellow_motor(0x01, 0x00, "hexfellow")
    # ... control motor

Supported Vendors

  • Hexfellow (required)
  • Damiao (optional, for higher bandwidth)

System Setup

# Configure CAN-FD interface
sudo ip link set can0 type can bitrate 1000000 dbitrate 5000000 fd on
sudo ip link set can0 up
CAN-FD examples above are Linux-first. On Windows/macOS, prefer standard CAN (Controller(channel)) unless your adapter stack explicitly supports FD.

DM Serial Bridge

Serial-to-CAN bridge for Damiao motors using the official Damiao serial adapter.

Usage

from motorbridge import Controller

# Open serial bridge
with Controller.from_dm_serial("/dev/ttyACM0", baud=921600) as ctrl:
    motor = ctrl.add_damiao_motor(0x01, 0x11, "4340P")
    # ... control motor

Parameters

ParameterTypeDefaultDescription
serial_portstr”/dev/ttyACM0”Serial device path
baudint921600Baud rate (use 921600 for Damiao)

Supported Vendors

  • Damiao only

DM_Device SDK

DaMiao DM_Device_SDK controls CAN/CAN FD adapter hardware. In motorbridge, this transport is wired to the Damiao motor protocol only, and the adapter must be in USB mode.

Supported Adapter Types

AdapterSDK enumChannelsdm_device_typedm_channel
USB2CANFDUSB2CANFD1usb2canfd0
USB2CANFD_DUALUSB2CANFD_DUAL2usb2canfd-dual0 / 1
LINKX4CLINKX4C4linkx4c0 / 1 / 2 / 3

Python Usage

from motorbridge import Controller

# USB2CANFD_DUAL channel 0
with Controller.from_dm_device("usb2canfd-dual", "0") as ctrl:
    motor = ctrl.add_damiao_motor(0x04, 0x14, "4310")

# LINKX4C channel 0
with Controller.from_dm_device("linkx4c", "0") as ctrl:
    motor = ctrl.add_damiao_motor(0x04, 0x14, "4310")

CLI Usage

# Scan all channels on USB2CANFD_DUAL: 0 and 1
motorbridge-cli scan \
  --vendor damiao \
  --transport dm-device \
  --dm-device-type usb2canfd-dual \
  --model 4310 \
  --start-id 1 \
  --end-id 16

# Scan all channels on LINKX4C: 0, 1, 2, 3
motorbridge-cli scan \
  --vendor damiao \
  --transport dm-device \
  --dm-device-type linkx4c \
  --model 4310 \
  --start-id 1 \
  --end-id 8

# Control one physical channel
motorbridge-cli run \
  --vendor damiao \
  --transport dm-device \
  --dm-device-type linkx4c \
  --dm-channel 0 \
  --model 4310 \
  --motor-id 0x04 \
  --feedback-id 0x14 \
  --mode enable \
  --loop 1
In scan mode, omit --dm-channel to scan every channel for the selected adapter. Pass --dm-channel only when you want one physical channel.

Serial Port Setup (3 Platforms)

Linux:
# Check available serial ports
ls -la /dev/ttyACM* /dev/ttyUSB*

# Add user to dialout group for permission
sudo usermod -a -G dialout $USER
# Log out and back in
macOS:
# Typical serial devices
ls -la /dev/cu.usbmodem* /dev/cu.usbserial*
Windows (PowerShell):
# List COM ports
[System.IO.Ports.SerialPort]::GetPortNames()

Common Serial Devices

DevicePathNotes
Damiao USB-CAN/dev/ttyACM0Default
USB-Serial Adapter/dev/ttyUSB0Check with dmesg

Transport Selection Guide

Decision Tree

What motor vendor are you using?

├── Hexfellow ──→ from_socketcanfd (required)

├── Damiao with DM_Device USB2CANFD/DUAL/LINKX4C ──→ from_dm_device

├── Damiao with USB-CAN adapter ──→ from_dm_serial

├── Damiao with CAN card ──→ Controller (SocketCAN)

├── RobStride ──→ Controller (SocketCAN)

├── MyActuator ──→ Controller (SocketCAN)

└── HighTorque ──→ Controller (SocketCAN)

Mixed Vendor Setup

When using multiple vendors on the same CAN bus, create separate Controller instances:
from motorbridge import Controller

# Each vendor gets its own controller
with Controller("can0") as dm_ctrl:
    dm_motor = dm_ctrl.add_damiao_motor(0x01, 0x11, "4340P")
    dm_ctrl.enable_all()

with Controller("can0") as rs_ctrl:
    rs_motor = rs_ctrl.add_robstride_motor(127, 0xFD, "rs-06")
    rs_ctrl.enable_all()
Do not add motors from different vendors to the same Controller instance. Each controller is optimized for a specific vendor protocol.

Transport Performance

Latency Comparison

TransportTypical LatencyMax Throughput
SocketCAN~1-2 ms~5000 msg/s
CAN-FD~0.5-1 ms~10000 msg/s
DM Serial~2-5 ms~2000 msg/s

Recommendations

  • Real-time control: Use SocketCAN or CAN-FD
  • Development/Debug: DM Serial is convenient for quick testing
  • High-speed loops: Use CAN-FD with dt_ms >= 10

Troubleshooting

SocketCAN: “No buffer space available” (Error 105)

# Stop other CAN senders
# Increase TX queue
sudo ifconfig can0 txqueuelen 1000

# Increase control loop period
# dt_ms = 20 or higher

Serial: Permission Denied

sudo usermod -a -G dialout $USER
# Log out and back in

CAN-FD: “Invalid argument”

# Ensure CAN-FD is enabled on interface
sudo ip link set can0 type can bitrate 1000000 dbitrate 5000000 fd on
sudo ip link set can0 up

Next Steps