Handling ChannelbrokenException if USB disconnected

Hi All

I want to handle the exception if the USB is accidentally unplugged. Sometimes the exception occurred without the USB unplugged. I have no way of replicating the issue. That’s why I would like to deal with it

from approxeng.input.selectbinder import ControllerResource
from fibre.protocol import ChannelBrokenException
from usb.core import USBError
from datetime import datetime
import odrive
import threading

Amp_motor = 45
print("Waiting for odrive....")
odrv0 = odrive.find_any() #program stop here unless odrive is found
print("Found odrive!")
lm = odrv0.axis0 
rm = odrv0.axis1
maxSpd = 30
minSpd = 10
pivotthreshold = .5*maxSpd

if( (lm.encoder.is_ready != True) or (rm.encoder.is_ready != True)):
    #right motor
    rm.controller.config.vel_gain = 0.0567
    rm.controller.config.vel_integrator_gain=0.5
    rm.requested_state = AXIS_STATE_ENCODER_OFFSET_CALIBRATION
    rm.controller.config.control_mode = CONTROL_MODE_VELOCITY_CONTROL
    rm.controller.config.vel_limit = maxSpd + 20
    rm.controller.config.vel_ramp_rate = maxSpd
    rm.controller.config.input_mode = INPUT_MODE_VEL_RAMP
    rm.motor.config.current_lim = Amp_motor
    rm.motor.config.direction = -1
    #Left motor
#     time.sleep(10)
lm.controller.config.vel_gain = 0.0567
lm.controller.config.vel_integrator_gain=0.5
lm.requested_state = AXIS_STATE_ENCODER_OFFSET_CALIBRATION
lm.controller.config.control_mode = CONTROL_MODE_VELOCITY_CONTROL
lm.controller.config.vel_limit = maxSpd + 20
lm.controller.config.vel_ramp_rate = maxSpd
lm.controller.config.input_mode = INPUT_MODE_VEL_RAMP
lm.motor.config.current_lim = Amp_motor
lm.motor.config.direction = 1

while True: 
    try:
        with ControllerResource(dead_zone=0.1, hot_zone=0.2) as xbox:
            print("xbox connected")
            while xbox.connected:
                presses = xbox.check_presses() # debug
                lm.controller.input_vel,rm.controller.input_vel = mixer(yaw= -xbox['lx'] ,throttle= -xbox['ly'], max_power=maxSpd)

                if xbox.presses ['dup']:
                    pass

                if xbox.presses ['cross']:
                    rm.requested_state = AXIS_STATE_IDLE
                    lm.requested_state = AXIS_STATE_IDLE
#                     raise robotStopException()
                
                if xbox.presses ['circle']:
                    rm.requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL
                    lm.requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL
                
                if xbox.presses ['square']:
                    pump.set_servo_pulsewidth(OUT_GPIO,500)
                
                if xbox.presses ['triangle']:
                    pump.set_servo_pulsewidth(OUT_GPIO,1500)
#                     print("adqwfqfqfq")

                if xbox.presses ['home']:
                    print(odrv0.vbus_voltage)
                    print("Left [{} , {}]".format(lm.motor.current_control.Iq_measured , lm.motor.current_control.Iq_setpoint))
                    print("Right [{} , {}]".format(rm.motor.current_control.Iq_measured , rm.motor.current_control.Iq_setpoint))
                    
                if xbox.has_presses:
                    print(xbox.presses)
            print("Connection to joystick(s) lost")

    except (ChannelBrokenException, USBError):
        print("channel broken.Retrying...")
        odrv0 = odrive.find_any()
        print("Found odrive!")
        time.sleep(1.0)

After I replug the USB, this what appeared in the shell:

channel broken.Retrying...
USB device init failed (bus 1, device 14). Ignoring this device. More info: Traceback (most recent call last):
  File "/usr/local/lib/python3.7/dist-packages/fibre/usbbulk_transport.py", line 196, in discover_channels
    bulk_device.init()
  File "/usr/local/lib/python3.7/dist-packages/fibre/usbbulk_transport.py", line 50, in init
    self.dev.reset()
  File "/usr/local/lib/python3.7/dist-packages/usb/core.py", line 947, in reset
    self._ctx.managed_open()
  File "/usr/local/lib/python3.7/dist-packages/usb/core.py", line 113, in wrapper
    return f(self, *args, **kwargs)
  File "/usr/local/lib/python3.7/dist-packages/usb/core.py", line 131, in managed_open
    self.handle = self.backend.open_device(self.dev)
  File "/usr/local/lib/python3.7/dist-packages/usb/backend/libusb1.py", line 804, in open_device
    return _DeviceHandle(dev)
  File "/usr/local/lib/python3.7/dist-packages/usb/backend/libusb1.py", line 652, in __init__
    _check(_lib.libusb_open(self.devid, byref(self.handle)))
  File "/usr/local/lib/python3.7/dist-packages/usb/backend/libusb1.py", line 604, in _check
    raise USBError(_strerror(ret), ret, _libusb_errno[ret])
usb.core.USBError: [Errno 5] Input/Output Error

Found odrive!
xbox connected
Traceback (most recent call last):
  File "/home/pi/Desktop/megaBOT_neo.py", line 130, in <module>
    lm.controller.input_vel,rm.controller.input_vel = mixer(yaw= -xbox['lx'] ,throttle= -xbox['ly'], max_power=maxSpd)
  File "/usr/local/lib/python3.7/dist-packages/fibre/remote_object.py", line 245, in __getattribute__
    return object.__getattribute__(self, name)
AttributeError: 'RemoteObject' object has no attribute 'controller'

First, I had my raspberry pi share the same power source as the odrive. Then I tried with separate power source for the pi and odrive. In both cases, the error persist.

Any idea how to handle the exception properly without triggering AttributeError?

Any help would be really appreciated.

I actually got this error while my USB still plugged in but it seldom occurs but critical nonetheless:

Traceback (most recent call last):
  File "/home/pi/Desktop/megaBOT_neo.py", line 137, in <module>
    #vel resets to zero when idle
  File "/usr/local/lib/python3.7/dist-packages/fibre/remote_object.py", line 245, in __getattribute__
    return object.__getattribute__(self, name)
AttributeError: 'RemoteObject' object has no attribute 'controller'

This error here is more critical than when the USB is accidentally unplugged. Please help.

Maybe you have some noise issues? Try the ferrite rings from the shop

You mean use it on the USB? I’ve use them on my motors…

No, using them on the motors. Hmm, curious curious. Have you tried one of the USB isolators?

Well I certainly wouldn’t use USB for anything critical. Use CAN or maybe UART for that.

Yeah, sounds like power spikes going through the ground of your usb line.

Either further reduce the noise source, or isolate your usb connection.

Send us a picture of your setup, then we can suggest improvements.


This is my current setup.

@Wetmelon I’m using a 25m usb 3.0: cosemi aoc

When I resist the motion of my robot, the error surely come up.

Will this make a difference? audio usb 3.0