Skip to content

Conversation

@perara
Copy link

@perara perara commented Nov 15, 2025

As previously discussed. Some are in need of UART support. Since it was not natively supported, we thought it nice to add. Feel free to adopt for the main repo if interesting.

Summary

This PR adds support for using the moteus firmware over UART with the fdcanusb ASCII protocol, enabling communication via serial adapters (e.g., USB-UART, RS485) as an alternative to CAN-FD. Its guarded behind compile macro.

Motivation

  • Enables development and testing without CAN-FD hardware
  • Provides a fallback communication method for debugging
  • Allows use of low-cost USB-UART adapters for prototyping
  • Simplifies integration with systems that have limited CAN-FD support and generally do not need CAN

Changes

Firmware (fw/)

  • fw/uart_fdcanusb_micro_server.h (new): Complete implementation of fdcanusb ASCII protocol over UART
    • Handles can send commands and rcv/OK responses
    • Full protocol compliance including ID mapping, DLC rounding, and flags (E/B/F)
    • Efficient single-buffer design with minimal RAM overhead
  • fw/moteus.cc: Conditional UART initialization and multiplex routing
    • Dual transport support (CAN-FD + UART) with proper stream routing
    • UART configured at 460800 baud on PC10 (TX) / PC11 (RX)
  • fw/moteus_hw.cc: Pin configuration for USART3 (PC10/PC11)
  • fw/moteus_controller.cc: Disable debug UART when protocol enabled to prevent pin contention
  • fw/BUILD: Fixed macro name from MOTEUS_ENABLE_UART_FDCANUSB to MOTEUS_ENABLE_UART_PROTOCOL

Python Library (lib/python/moteus/)

  • fdcanusb_device.py: Add baudrate parameter support
    • Uses explicit baudrate if provided, otherwise defaults to 9600
    • Opens serial port with exclusive=True to prevent multi-access issues
  • transport_factory.py: Add --fdcanusb-baud command-line argument
    • Allows specifying custom baud rates for serial adapters
    • Example: --fdcanusb /dev/ttyUSB0 --fdcanusb-baud 460800

Other

  • .gitignore: Added .history/ for VS Code local history files

Testing

Tested with:

# moteus_tool
python3 -m moteus.moteus_tool --target 1 --fdcanusb /dev/ttyUSB0 --fdcanusb-baud 460800 --info
python3 -m moteus.moteus_tool --target 1 --fdcanusb /dev/ttyUSB0 --fdcanusb-baud 460800 --calibrate
# tview GUI
python3 -m moteus_gui.tview --fdcanusb /dev/ttyUSB0 --fdcanusb-baud 460800 --target 1

Technical Details

  • Protocol: Implements the fdcanusb text protocol (can send XXXX PAYLOAD FLAGS\nOK\n / rcv ...)
  • Baud Rate: Default 460800 baud (configurable via --fdcanusb-baud)
  • Pins: PC10 (TX), PC11 (RX) - USART3 on STM32G4
  • Compatibility: Maintains full backward compatibility with existing CAN-FD communication

Breaking Changes

None. UART support is opt-in and does not affect existing CAN-FD functionality.

Code Size Impact

  • Firmware: +268 lines (uart_fdcanusb_micro_server.h)
  • Python: +11 lines (minimal changes for baudrate support)
  • Total: Clean, minimal implementation focused on core functionality
- Introduced `uart_fdcanusb_micro_server.h` to handle UART communication using the FDCAN USB protocol.
- Updated `BUILD` file to enable UART FDCAN USB configuration.
- Modified `moteus_controller.cc` and `moteus.cc` to integrate UART protocol handling and server polling.
- Adjusted hardware pin definitions in `moteus_hw.cc` for UART functionality.
- Updated the constructor of `FdcanusbDevice` to include an optional `baudrate` parameter, defaulting to 9600 if not provided.
- Modified the `FdcanusbFactory` to accept a command-line argument for specifying the baudrate for the serial adapter, improving flexibility for different hardware configurations.
- Changed the compilation flag from `-DMOTEUS_ENABLE_UART_FDCANUSB` to `-DMOTEUS_ENABLE_UART_PROTOCOL` to reflect the new UART protocol implementation.
- Added '.history/' to the .gitignore to prevent tracking of history files in the repository.
@jpieper
Copy link
Member

jpieper commented Nov 16, 2025

Thanks for sharing! I can't commit to merging this, but I have questions/requests:

  1. It looks like this is either/or, i.e. if you have the UART compiled in, then CAN-FD doesn't work. Is that correct? I see at least the diagnostic channel is associated with only one or the other.
  2. If it were to be merged, I'd want to have the pins used by configurable, in the same manner as the kDebug uart mechanism. I'd probably want it to be enabled by default on the aux2/abs UART pins for whatever those are for the board in question.

I admit to using the fdcanusb protocol is quite ingenious and solves a lot of problems, like maintaining interoperability with all existing tools and the python and C++ library for desktops. It was not a design alternative I had considered and makes it much more feasible. It could even be used in an RS485 multiplex bus using either a direction pin, or ignoring self sends like if the n1/x1 RS422 wires are connected together. Some downsides:

  1. It is not very simple to use on say an Arduino with limited flash space. I'm not sure that this is a problem, as the other logical alternative, the existing diagnostic protocol, does not work very well as it doesn't make it very easy to query the current state.
  2. There is no checksum or consistency check. With a UART alone, and a motor control system, bit errors are very likely as people have all kinds of electrical and EMI issues in their systems. Maybe adding a NMEA style *XX checksum at the end, which the device requires as mandatory as soon as it sees it at least once?

As mentioned, I can't commit to merging this even if every request was addressed, so take them for what you will!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants