为什么我无法重复调用PyUSB函数dev.read()而不出现超时错误?

3 投票
5 回答
13079 浏览
提问于 2025-04-29 05:36

我有一个USB连接,连接着一台Macbook Air和一个微控制器传感器,这个传感器会不断地发送十六进制数据。我想用Python中的PyUSB来获取这些数据。我用PyUSB连接微控制器,代码是这样的:

import usb 
dev = usb.core.find(idVendor=0xXXXX, idProduct=0xXXXX)
dev.set_configuration()
cfg = dev.get_active_configuration()
intf = cfg[(0,0)]
ep = usb.util.find_descriptor(intf,custom_match = lambda e: usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_OUT)

然后我尝试使用dev.read()方法从设备中读取数据到一个数组里,第一次这样做是成功的:

dev.read(0x1,100,100)

这次读取得到了一个长度为100的数组,但在我多次调用dev.read(0x1,100,100)之后(并且得到了几个不同的数组),我开始收到这个错误:

dev.read(0x1,100,100)

Traceback (most recent call last):

File "stdin", line 1, in <module>

File "/Users/dimachy/anaconda/lib/python2.7/site-packages/usb/core.py", line 918, in read
self.__get_timeout(timeout))

File "/Users/dimachy/anaconda/lib/python2.7/site-packages/usb/backend/libusb1.py", line 777, in bulk_read
timeout)

File "/Users/dimachy/anaconda/lib/python2.7/site-packages/usb/backend/libusb1.py", line 880, in __read
_check(retval)

File "/Users/dimachy/anaconda/lib/python2.7/site-packages/usb/backend/libusb1.py", line 560, in _check
raise USBError(_str_error[ret], ret, _libusb_errno[ret])

usb.core.USBError: [Errno 60] Operation timed out

为什么会发生这种情况呢?我怀疑我对数据传输过程中缓冲区是如何存储数据的理解有问题,但我找不到一个清晰的解释来说明发生了什么。

暂无标签

5 个回答

0

你可以这样做。

while True:
try:
    r = dev.read(eddr, 1024)
    print(r)
except Exception as e:
    continue
0

发送数据的设备可能在等待某种回复,它就在那里等着,这样会导致你其他的读取操作超时。如果可以的话,试着用一些工具监控它正常工作时的数据流量,然后确保你没有漏掉任何数据包。

0

在你完成读取后,记得使用 usb.util.dispose_resources(dev) 来释放资源。你可以在我的项目中看到一个例子:https://github.com/JosepEscobar/inverterApi/blob/main/app/data_source.py

1

如果你不确定的话,尽量不要固定接收到的数据包大小。如果可以的话,找一下你这个端点的最大数据包大小,然后把它作为你读取方法的第二个参数:

endpoint.wMaxPacketSize

通常,你可以通过在终端输入这个命令来查看描述符、端点和接口:

lsusb -d vendorId:productId -v

这样你就能直接得到最大数据包大小了。希望这能帮助你解决问题。

2

你收到的响应长度是多少呢?你现在设置的dev.read是告诉PyUSB,期望的响应长度是100字节。如果在100毫秒内没有收到100字节的数据,就会抛出一个超时错误。如果你的设备返回的消息长度小于100字节,那么在100毫秒到达时,你会收到一个错误,尽管这个消息的长度是正确的。所以,你可以选择以下两种方法:

1) 去掉超时变量。在这种情况下,PyUSB会等待一个默认的时间,然后返回响应而不会报错。如果你需要比默认时间更快的超时,这样做就不管用了。

2) 更好的方法是,如果你知道你收到的响应长度(听起来你已经有一些数据了,所以这可能是情况),就用这个实际的长度来替代100字节。这样可以在没有错误的情况下获取数据,同时还可以设置超时变量。

撰写回答