I have an USB devices that use FTDI chip that I can identify in Linux:
user@user:~/src/libftdi/build$ lsusb
Bus 009 Device 008: ID 0403:faf0 Future Technology Devices International, Ltd
or:
user@user:~$ lsusb -v -d 0403:faf0
Bus 009 Device 008: ID 0403:faf0 Future Technology Devices International, Ltd
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 8
idVendor 0x0403 Future Technology Devices International, Ltd
idProduct 0xfaf0
bcdDevice 6.00
iManufacturer 1 Thorlabs
iProduct 2 APT DC Motor Controller
iSerial 3 83836244
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 32
bNumInterfaces 1
bConfigurationValue 1
iConfiguration 0
bmAttributes 0xc0
Self Powered
MaxPower 0mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 255 Vendor Specific Class
bInterfaceSubClass 255 Vendor Specific Subclass
bInterfaceProtocol 255 Vendor Specific Protocol
iInterface 2 APT DC Motor Controller
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x02 EP 2 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 0
Device Status: 0x0001
Self Powered
I have installed pylibftdi and figured how to list them
In [26]: dev.driver.list_devices()
Out[26]:
[('Thorlabs', 'APT DC Motor Controller', '83836244'),
('Thorlabs', 'APT DC Motor Controller', '83838416'),
('Thorlabs', 'APT DC Motor Controller', '83837686'),
('Thorlabs', 'APT DC Motor Controller', '83836852'),
('Thorlabs', 'APT DC Motor Controller', '83837812'),
('Thorlabs', 'APT DC Motor Controller', '83825518'),
('Thorlabs', 'APT DC Motor Controller', '83838377'),
('Thorlabs', 'APT DC Motor Controller', '83838379'),
('Thorlabs', 'APT DC Motor Controller', '83836769'),
('Thorlabs', 'APT DC Motor Controller', '83837688'),
('Thorlabs', 'APT DC Motor Controller', '83836926'),
('Thorlabs', 'APT DC Motor Controller', '83837767'),
('Thorlabs', 'APT DC Motor Controller', '83836887'),
('Thorlabs', 'APT DC Motor Controller', '83836737'),
('Thorlabs', 'APT DC Motor Controller', '83838436'),
('Thorlabs', 'APT DC Motor Controller', '83837639'),
('Thorlabs', 'APT DC Motor Controller', '83836040'),
('Thorlabs', 'APT DC Motor Controller', '83837769'),
('Thorlabs', 'Brushed Motor Controller', '27251492'),
('Thorlabs', 'Brushed Motor Controller', '27251539')]
In [1]: from pylibftdi import USB_PID_LIST, USB_VID_LIST, Device
In [2]: USB_PID_LIST.append(0xFAF0)
In [3]: dev = Device()
In [4]: dev.driver.libftdi_version()
Out[4]: libftdi_version(major=0, minor=0, micro=0, version_str='< 1.0 - no ftdi_get_library_version()', snapshot_str='unknown')
The documentation for the pylibusb says that the attribute device_id can be used to specify the device I am trying to connect to:
| __init__(self, device_id=None, mode='b', encoding='latin1', interface_select=None, device_index=0, **kwargs)
| Device([device_id[, mode, [OPTIONS ...]]) -> Device instance
|
| represents a single FTDI device accessible via the libftdi driver.
| Supports a basic file-like interface (open/close/read/write, context
| manager support).
:param device_id: an optional serial number of the device to open.
| if omitted, this refers to the first device found, which is
| convenient if only one device is attached, but otherwise
| fairly useless.
Here is my simple code where I am creating two instances dev1 and dev2. For dev2 i do not specify the device_id (hence no specific serial number) and for dev1 I do. I can succesfully communicate with the dev2 but not dev1:
>>>from pylibftdi import USB_PID_LIST, USB_VID_LIST, Device
>>>from struct import pack, unpack
>>>USB_PID_LIST.append(0xFAF0)
>>>command = pack('BBBBBB',0x05,0x00,0x00,0x00,0x50,0x01)
>>>dev2 = Device();
>>>dev2.baudrate = 115200;
>>>dev2.writelines(command);
>>>dev2.readline()
'\x06\x00T\x00\x81P\xc0z\xf2\x04TDC001\x00\x00\x10\x00\x03\x00\x02\x00TDC001 DC Servo Drive\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00104927Apr\x00\x01\x00\x02\x00\x00\x00\x01\x00'
>>>dev1 = Device(device_id = '83838416');
>>>dev1.baudrate = 115200;
>>>dev1.writelines(command);
>>>dev1.readline()
''
Since, I have dozens of these USB devices connected to one computer, it is essential for me to be able to create an instance and talk to a device with defined serial number.
I am not sure if it is a bug or I am doing something wrong.
Added later:
Somehow it is history dependent. If I run the same code after restarting python, I get an empty string as a response. I don't know what I am doing different now from before.
In [1]: from pylibftdi import USB_PID_LIST, USB_VID_LIST, Device
In [2]: from struct import pack, unpack
In [3]: USB_PID_LIST.append(0xFAF0)
In [4]: command = pack('BBBBBB',0x05,0x00,0x00,0x00,0x50,0x01)
In [5]: dev2 = Device();dev2.baudrate = 115200;dev2.writelines(command);dev2.readline();
In [6]: dev2.__dict__
Out[6]:
{'_baudrate': 115200,
'_opened': True,
'ctx': <ctypes.c_char_Array_1024 at 0x7ff2008a1b00>,
'decoder': <encodings.latin_1.IncrementalDecoder at 0x7ff2006906d0>,
'device_id': None,
'device_index': 0,
'driver': <pylibftdi.driver.Driver at 0x7ff200690610>,
'encoder': <encodings.latin_1.IncrementalEncoder at 0x7ff200681f90>,
'encoding': 'latin1',
'fdll': <CDLL 'libftdi.so.1', handle 5627c1668650 at 7ff2011d08d0>,
'interface_select': None,
'mode': 'b'}
In [8]:
Are you interested in uart (like) modes only? If so you might take a look at pyserial. Especially the serial.tools.list_ports.comports() function:
import serial
import serial.tools.list_ports
print([(x.device,x.hwid,x.description,x.location,x.serial_number) for x in serial.tools.list_ports.comports()])
This way you might be able to get the right description and open then the port via
ports = [x.device for x in serial.tools.list_ports.comports() if search_string in x.hwid]
serial.Serial(ports[0], 115200)
来源:https://stackoverflow.com/questions/56530409/cannot-communicate-with-ftdi-device-via-pylibftdi-with-specified-device-id