UUID based addressing and python multiple device support
I’m excited to announce a significant usability improvement for all moteus controllers, command line tools and the python library! If your moteus controllers are on firmware version 2025-09-20 or newer and your moteus client tools are at 0.3.91 or newer, (and if you are using a pi3hat, it is on firmware 2025-09-20 or newer) there are some big improvements that you transparently get:
- You no longer need to assign unique CAN IDs before daisy chaining controllers
- The python transport lets client programs transparently operate across multiple CAN-FD interfaces simultaneously
- tview will automatically open all controllers attached to all CAN-FD interfaces on the computer
Let’s dig into what this looks like from the command line, tview and what the practical constraints are.
UUID based addressing
Historically, each moteus device has a integer CAN ID that is between
1 and 126. In order to communicate on the CAN-FD bus, each device had
to have a unique ID assigned. Since every moteus controller ships
from the factory with ID 1, this meant that they had to be connected
one by one on the CAN-FD bus in order to assign IDs. Further, because
changing the CAN ID takes effect immediately, it is easy to not
correctly save the configuration afterward. If you change the ID in
tview, it renders further communication inoperative, so unless you
remember to restart tview with the new ID, any conf write
you issue
will go into the void.
Now, there are two mechanisms for selecting which moteus to communicate with. The CAN ID method remains functional and is preferred for deployed systems. Additionally now though, the unique UUID embedded into the OTP of each moteus controller can also be used to select which device is communicated with. As a technical matter, the broadcast CAN ID is used, then the first part of the CAN frame is a write to a special UUID mask register. If a controller sees a write to this register with a UUID that does not match its own, then it assumes it is not being addressed.
Practically, this means a few things. First, if you do not specify an address to moteus_tool or tview and multiple devices with the same CAN ID are on the bus, the tool will find all of them.

moteus_tool discovering devices with the same CAN ID
Second, when manually specifying a device either on the command line or in the python library, you can use either the CAN ID or a prefix of the UUID. The prefix needs to be an even 4 bytes, so you can use 4, 8, 12 or 16 byte long strings with or without dashes. For example:
python -m moteus.moteus_tool -t 647093ea --info
Will show the information from the controller with a UUID that starts with 647093ea. Usage in the python library looks like:
c = moteus.Controller(moteus.DeviceAddress(uuid=bytes.fromhex('647093ea')))
await c.set_stop()
To make ID assignment even easier, tview will switch to UUID based addressing if it detects that you are attempting to change the CAN-ID and the controller supports it.
Addressing controllers by their UUID imposes a moderate penalty in
terms of CAN frame size, as the UUID must be sent in every frame.
Thus, it is still recommended to set unique CAN IDs for each device.
However, now it is much easier because you can connect everything,
open up tview once, then change all the IDs at once. The old method
required many cable reconnections and restarts of tview. You of
course still need to ensure that you are changing the correct device!
One easy method is to look at the reported position in
motor_position.output
, then wiggle the motor by hand.
Multiple device support
The other big change is that the python library now transparently supports interacting with devices on multiple physical CAN-FD interfaces at the same time. That can be multiple mjcanfd-usb-1x’s, any supported python-can devices like socketcan interfaces or PCAN library based peripherals, or any of the channels on the pi3hat. By default, the library will attempt to use every connected transport so simple usage is really simple. For example, using:
python -m moteus.moteus_tool --info
Would simultaneously find devices attached to multiple
mjcanfd-usb-1x’s and a socketcan, reporting which transport each
device was discovered on. tview
operates the same way, and will show
the transport, if there are multiple possible ones, in the tree view
along with the ID.

moteus_tool discovering devices on multiple transports
When using the python library, the transport you want to use does not need to be specified in advance, only the device address, either CAN ID or UUID. When an interaction is first performed with a device, a short discovery message is sent on all connected CAN-FD interfaces to find which one the device is located on, after which further communication is directed specifically at that CAN-FD bus.
If necessary, there are facilities for manually specifying which CAN-FD interfaces to use, and for manually associating devices with CAN-FD interfaces, although in practice they probably won’t be used all that often. That means that for many cases even with many different transports, your python code can look like:
parser = argparse.ArgumentParser()
moteus.make_transport_args(parser)
args = parser.parse_args()
transport = moteus.get_singleton_transport(args)
controllers = {x: moteus.Controller(id=x, transport=transport)
for x in [1, 2, 3, 4, 5, 6, 7, 8]}
await transport.cycle([c.make_stop() for c in controllers.values()])
results = await transport.cycle(
[c.make_position(position=position[id], query=True)
for id, c in controllers.items()])
Similarly, tview now usually needs no arguments whatsoever, and shows all the devices attached simultaneously.

tview operating on devices across multiple transports
pi3hat operation
Multiple device support changes how usage of the pi3hat happens both in the python library and with the command line tools. Basically, in the new world, no pi3hat specific python or command line interface is required any more. The old Pi3HatRouter
and --pi3hat-cfg
continue to work as before, but if omitted, then all channels of the pi3hat are probed and devices are automatically allocated to the pi3hat ports where they are connected.
How to use
Unfortunately, to get the full benefit of all these features, all controllers in your system need to be at firmware 2025-09-20 or newer, your pi3hat firmware needs to be 2025-09-20 or newer, your mjcanfd-usb-1x or fdcanusbs need to be on version 2025-09-19 and your moteus and moteus-gui python library need to be 0.3.91 or newer. Some capabilities will work in a degraded manner with mixed versions, but enough fixes were required across the board that a full upgrade is required to get the full experience.
To upgrade the moteus firmware, follow these instructions: https://github.com/mjbots/moteus/blob/main/docs/reference.md#flashing-over-can
To upgrade the python library:
python -m pip install --upgrade moteus moteus-gui
To upgrade the pi3hat firmware, see this blog post: https://blog.mjbots.com/2025/10/02/pi3hat-firmware-release-2025-09-20/
To upgrade the mjcanfd-usb-1x or fdcanusb firmware, see this blog post: Improved performance for mjcanfd-usb-1x
To upgrade the pi3hat python library:
./venv/bin/python -m pip install --upgrade moteus-pi3hat