通过 pyusb 从 USB 鼠标(单芯片,ADNS-2700)获取图像

Onl*_*jus 5 python usb libusb pyusb

我想提取单芯片光学鼠标传感器(特别是 ADNS-2700)捕获的实际图像。与互联网上使用微控制器与成像芯片的 SPI 接口通信的各种其他教程(如下所示)不同,我尝试使用的芯片集成了 USB 接口。

ADNS-2700 数据表

系统:Windows 7、Python2.7、PyUSB 1.0

我已经成功提取了以下示例中的按钮按下、速度和滚轮:

import usb.core
import usb.util

VENDOR_ID = 6447
PRODUCT_ID = 2326

# find the USB device
device = usb.core.find(idVendor=VENDOR_ID,
                       idProduct=PRODUCT_ID)

# use the first/default configuration
device.set_configuration()

# first endpoint
endpoint = device[0][(0,0)][0]

# read a data packet
attempts = 10
data = None
while attempts > 0:
    try:
        data = device.read(endpoint.bEndpointAddress,
                           endpoint.wMaxPacketSize)
        print data

    except usb.core.USBError as e:
        data = None
        if e.args == ('Operation timed out',):
            attempts -= 1
            continue
Run Code Online (Sandbox Code Playgroud)

它提取如下数据:

array('B', [0, 0, 16, 0, 0])
array('B', [0, 0, 240, 255, 0])
array('B', [0, 0, 16, 0, 0])
array('B', [0, 0, 240, 255, 0])
Run Code Online (Sandbox Code Playgroud)

我需要帮助提取原始图像数据!

我是一个USB菜鸟,这可能是造成大部分问题的原因。

在数据表的第 18 页上,有一个 USB 命令列表。看起来有希望的一个是:

Mnemonic            Command                    Notes
---------------------------------------------------------------
Get_Vendor_Test     C0 01 00 00 xx 00 01 00    Read register xx
Run Code Online (Sandbox Code Playgroud)

然后在第 28 页,有一个看起来很有前途的寄存器列表:

Address     Register Name    Register Type    Access       Reset Value
----------------------------------------------------------------------
0x0D        PIX_GRAB         Device           Read only    0x00
Run Code Online (Sandbox Code Playgroud)

不过,我尝试过:

device.write(endpoint.bEndpointAddress,'C0:01:00:00:0A:00:01:00',0)
Run Code Online (Sandbox Code Playgroud)

这导致:

usb.core.USBError: [Errno None] libusb0-dll:err [_usb_setup_async] invalid endpoint 0x81
Run Code Online (Sandbox Code Playgroud)

也:

device.read(endpoint.bEndpointAddress, 0x0D)
Run Code Online (Sandbox Code Playgroud)

这只是超时。


完整的解决方案:

import usb.core
import usb.util
import matplotlib.pyplot as plt
import numpy as np

VENDOR_ID = 6447
PRODUCT_ID = 2326

# find the USB device
device = usb.core.find(idVendor=VENDOR_ID,
                       idProduct=PRODUCT_ID)

# use the first/default configuration
device.set_configuration()


# In order to read the pixel bytes, reset PIX_GRAB by sending a write command
response = self.device.ctrl_transfer(bmRequestType = 0x40, #Write
                                     bRequest = 0x01,
                                     wValue = 0x0000,
                                     wIndex = 0x0D, #PIX_GRAB register value
                                     data_or_wLength = None
                                     )

# Read all the pixels (360 in this chip)
pixList = []
for i in range(361):
    response = self.device.ctrl_transfer(bmRequestType = 0xC0, #Read
                                         bRequest = 0x01,
                                         wValue = 0x0000,
                                         wIndex = 0x0D, #PIX_GRAB register value
                                         data_or_wLength = 1
                                         )
    pixList.append(response)

pixelArray = np.asarray(pixList)
pixelArray = pixelArray.reshape((19,19))

plt.imshow(pixelArray)
plt.show()
Run Code Online (Sandbox Code Playgroud)

Art*_*emB 5

您可能需要执行 ctrl_transfer() ,如pyUSB 教程中所示。

您还需要将数据表中的十六进制字节转换为 ctrl_transfer 的单独参数。请参阅此页了解格式。

Get_Vendor_Test C0 01 00 00 xx 00 01 00可以通过 ctrl_transfer() 调用发出,如下所示:

ret = dev.ctrl_transfer(bmRequestType=0xc0, # byte[0]
                        bRequest=0x01,      # byte[1]
                        wValue=0x0000,      # byte[2,3]
                        wIndex=register,    # byte[4,5]
                        data_or_wLength = 1)# byte[6,7]
Run Code Online (Sandbox Code Playgroud)