I’m using 4 pcs of ODrive v3.6 in order to command a robot. The system voltage is 24V, and the ODrives are of the 24V variant.
A small PC (Jetson Nano, but we also tried others) command the four ODrives over USB. Due to lack of ports, we use a USB hub. The USB cables are 1.8m long, new, from a reputable source.
The problem is that even without doing anything, the ODrives disconnect and reconnect randomly as seen in ODrivetool:
ODrive control utility v0.6.5.post1
Connected to unknown device 2068346E5748 (firmware v0.5.4) as odrv0
Connected to unknown device 208835873056 (firmware v0.5.4) as odrv1
Connected to unknown device 207A34765748 (firmware v0.5.4) as odrv2
Website: https://odriverobotics.com/
Docs: https://docs.odriverobotics.com/
Forums: https://discourse.odriverobotics.com/
Discord: https://discord.gg/k3ZZ3mS
Github: https://github.com/odriverobotics/ODrive/
Please connect your ODrive.
You can also type help() or quit().
In [1]: xz = odrv0
In [2]: xz.axis0.requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL
Oh no odrv1 disappeared
Reconnected to unknown device 208835873056 (firmware v0.5.4) as odrv1
Oh no odrv1 disappeared
Oh no odrv2 disappeared
Reconnected to unknown device 208835873056 (firmware v0.5.4) as odrv1
Oh no odrv1 disappeared
Task exception was never retrieved
future: <Task finished name='Task-3' coro=<_Domain.run_discovery.<locals>.loop() done, defined at /usr/local/lib/python3.11/dist-packages/odrive/pyfibre/fibre/libfibre.py:977> exception=TypeError("Expected value of type RemoteObject or None but got 'EmptyInterface'. An example for a RemoteObject is this expression: odrv0.axis0.controller._input_pos_property")>
Traceback (most recent call last):
File "/usr/local/lib/python3.11/dist-packages/odrive/pyfibre/fibre/libfibre.py", line 980, in loop
await callback(obj)
File "/usr/local/lib/python3.11/dist-packages/odrive/pyfibre/fibre/shell.py", line 15, in discovered_device
mount_result = await mount(device)
^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/odrive/shell.py", line 127, in mount
serial_number_str = await odrive.utils.get_serial_number_str(obj)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/odrive/utils.py", line 52, in get_serial_number_str
return format(await device._serial_number_property.read(), 'x').upper()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/odrive/pyfibre/fibre/libfibre.py", line 535, in async_call
tx_buf += arg[2].serialize(self._libfibre, args[i])
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/odrive/pyfibre/fibre/libfibre.py", line 247, in serialize
raise TypeError("Expected value of type RemoteObject or None but got '{}'. An example for a RemoteObject is this expression: odrv0.axis0.controller._input_pos_property".format(type(value).__name__))
TypeError: Expected value of type RemoteObject or None but got 'EmptyInterface'. An example for a RemoteObject is this expression: odrv0.axis0.controller._input_pos_property
In [3]:
The problem is less pronounced if I only have 1 ODrive connected at a time (I’ve used this successfully to configure them), but for the end application I will need all 4. The problem doesn’t always appear when I enable closed loop control. Sometimes it holds on and I can move the motors, but eventually it would randomly disconnect and reconnect. It seems random, not much related to what I’m doing.
I’m testing on Linux and dmesg
shows that the ODrive USB devices disconnect/reconnect, or have read errors.
I’ve read that people use USB isolators to improve USB reliability, but I’m confused how to test it in my scenario. E.g., one isolator per ODrive, or it would be sufficient to use one isolator, and then spawn the 4 through an unpowered USB hub.
BTW, we’ve tried with both powered and unpowered USB hubs, that doesn’t make any difference.
Please, give some advice how to rectify the issue?