问题
I would like to extract the actual images captured by a single chip optical mouse sensor, specifically the ADNS-2700. As apposed to the various other tutorials on the internet that use a micro controller to talk to the SPI interface of the imaging chip (like this), the chip I am trying to work with has a USB interface integrated.
ADNS-2700 Datasheet
System: Windows 7, Python2.7, PyUSB 1.0
I have successfully extracted the button presses, velocity, and scroll wheel following this example:
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
Which extracts data like:
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])
I need help extracting the raw image data!
I am a USB noob which is probably causing most of the problem.
On page 18 of the datasheet, there is a list of USB commands. The one that looks promising is:
Mnemonic Command Notes
---------------------------------------------------------------
Get_Vendor_Test C0 01 00 00 xx 00 01 00 Read register xx
Then on page 28, there is a list of registers of which this looks promising:
Address Register Name Register Type Access Reset Value
----------------------------------------------------------------------
0x0D PIX_GRAB Device Read only 0x00
However, I have tried:
device.write(endpoint.bEndpointAddress,'C0:01:00:00:0A:00:01:00',0)
which results in a:
usb.core.USBError: [Errno None] libusb0-dll:err [_usb_setup_async] invalid endpoint 0x81
as well as:
device.read(endpoint.bEndpointAddress, 0x0D)
which simply times out.
Complete Solution:
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()
回答1:
You probably need to do ctrl_transfer() as shown in pyUSB tutorial.
You will also need to convert hex bytes from the datasheet into individual parameters to ctrl_transfer. See this page for the format.
Get_Vendor_Test
C0 01 00 00 xx 00 01 00
can be issued with ctrl_transfer() call like this:
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]
回答2:
I just tried this code out myself, and there was a rather large bug in it. The datasheet for the ADNS-2700 states that response values that do not have the most-significant bit set are invalid. So the loop should not do exactly 361 reads, but should read until it gets 361 valid pixels, discarding any byte that does not have the "valid" bit set.
I made a couple other small changes, like unpacking the returned array before adding it to the list, and removing the MSb from the return values, since it doesn't represent actual pixel data.
I have tested this code using an Amazon Basics USB mouse, and it outputs a valid image.
import usb.core
import usb.util
import matplotlib.pyplot as plt
import numpy as np
VENDOR_ID = 0x04F2
PRODUCT_ID = 0x0939
# 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 = 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 = []
while len(pixList) < 361:
temp = 0
response = device.ctrl_transfer(bmRequestType = 0xC0, #Read
bRequest = 0x01,
wValue = 0x0000,
wIndex = 0x0D, #PIX_GRAB register value
data_or_wLength = 1
)
if response[0] >= 0x80:
temp = response[0] & 0x7F
pixList.append(temp)
pixelArray = np.asarray(pixList)
pixelArray = pixelArray.reshape((19,19))
plt.imshow(pixelArray)
plt.show()
来源:https://stackoverflow.com/questions/23229083/acquiring-images-from-a-usb-mouse-single-chip-adns-2700-via-pyusb