I am working with an FTDI device that has native software for Windows, but nothing available for Linux. I am trying to read data from the device using pylibftdi
. I would like to translate C# code
that is provided by the device manufacturer and purportedly works (unclear if this is true) but have not been successful. So far I have done the following:
-
Installed the Linux D2XX drivers based on these instructions. Installation was successful.
-
Followed the directions here and here to enable the FTDI device to connect to the Linux system.
-
After plugging the FTDI device into the Linux system USB port:
$ lsusb
Bus 006 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 005 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 003: ID 046d:c52b Logitech, Inc. Unifying Receiver
Bus 001 Device 002: ID 04f2:0833 Chicony Electronics Co., Ltd KU-0833 Keyboard
**Bus 001 Device 006: ID 0403:6001 Future Technology Devices International, Ltd FT232 Serial (UART) IC**
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
The bolded device (Bus 001 Device 006: ID 0403:6001
) is the device from which I would like to read.
- Then installed
pylibftdi
and verified that the device was readable via thepylibftdi
API:
$ python3
Python 3.9.5 (default, Jun 4 2021, 12:28:51)
[GCC 7.5.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys, pylibftdi as ftdi
>>> print(ftdi.Driver().list_devices())
[('FTDI', 'Cognionics Quick-20 20CH 1706Q20N', 'AI2SUN90')]
- As is clear, the device is connected and recognized. However, when I try to read from the device, I receive empty arrays:
>>> d = ftdi.Device()
>>> vars(d)
{'_opened': True, 'driver': <pylibftdi.driver.Driver object at 0x7fd819320910>, 'fdll': <CDLL 'libftdi.so.1', handle 557bc3ca6560 at 0x7fd8190aee80>, 'device_id': None, 'mode': 'b', 'encoding': 'latin1', 'encoder': <encodings.latin_1.IncrementalEncoder object at 0x7fd819320a60>, 'decoder': <encodings.latin_1.IncrementalDecoder object at 0x7fd8190aefd0>, '_baudrate': 9600, 'interface_select': None, 'device_index': 0, 'list_index': None, 'ctx': <ctypes.c_char_Array_1024 object at 0x7fd819342c40>}
>>> d.read(100)
b''
>>> d.read(100)
b''
>>> d.read(100)
b''
- This
C#
code (provided by the manufacturer) purportedly works, but I haven’t been able to test it. It seems like the easiest approach would be to translate this intopython
but even that is challenging as I do not know how to replicate the constants andftdi
function calls that are being used. The providedC#
code is:
UInt32 ftDevCount = 0;
ftStatus = ftDev.GetNumberOfDevices(ref ftDevCount);
ftdiDeviceList = new FTDI.FT_DEVICE_INFO_NODE[ftDevCount];
ftStatus = ftDev.GetDeviceList(ftdiDeviceList);
String[] deviceNames = new String[ftDevCount];
for (int c = 0; c < ftDevCount; c++)
{
deviceNames = ftdiDeviceList.Description.ToString();
}
Connecting to a device and configuring the serial port settings
if (ftDev.OpenBySerialNumber(ftdiDeviceList[devID].SerialNumber) == FTDI.FT_STATUS.FT_OK)
{ ftDev.SetFlowControl(FTDI.FT_FLOW_CONTROL.FT_FLOW_RTS_CTS, 0x11, 0x13);
ftDev.SetDataCharacteristics(FTDI.FT_DATA_BITS.FT_BITS_8, FTDI.FT_STOP_BITS.FT_STOP_BITS_1, FTDI.FT_PARITY.FT_PARITY_NONE);
ftDev.SetLatency(2);
ftDev.SetBaudRate((uint)3000000);
connectedName = ftdiDeviceList[devID].Description.ToString();
return true;
}
else
{
return false; //failed to open!
}
public byte ReadByte()
{
UInt32 bytesRead = 0;
byte[] t_data = new byte[1];
ftDev.Read(t_data, 1, ref bytesRead);
return t_data[0];
}
public void WriteByte(byte dat)
{
UInt32 bytesWritten = 0;
byte[] data = new byte[1];
data[0] = dat;
ftDev.Write(data, 1, ref bytesWritten);
}
//wait for sync byte 0xFF
while (byteInterface.ReadByte() != 255) {};
//read packet counter
int packetCount = byteInterface.ReadByte();
//read the 20 EEG channels
int NumEEG = 20;
for (int c = 0; c < NumEEG; c++)
{
msb = byteInterface.ReadByte();
lsb2 = byteInterface.ReadByte();
lsb1 = byteInterface.ReadByte();
int tempEEG = (msb << 24) | (lsb2 << 17) | (lsb1 << 10);
}
int NumACC = 3;
//read the 3 ACC channels
for (int c = 0; c < NumACC; c++)
{
msb = byteInterface.ReadByte();
lsb2 = byteInterface.ReadByte();
lsb1 = byteInterface.ReadByte();
int tempACC = (msb << 24) | (lsb2 << 17) | (lsb1 << 10);
}
//read packet tail
int impStatus = byteInterface.ReadByte();
//read battery voltage
int batteryByte = byteInterface.ReadByte();
//read trigger
int trigger = (byteInterface.ReadByte()<<8) + byteInterface.ReadByte();
- Based on the documentation in
pylibftdi
github repo, I can find some wrapper function calls as well as a few constants, but I am unaware of how to turn just the setup snippet, for example, :
ftDev.SetFlowControl(FTDI.FT_FLOW_CONTROL.FT_FLOW_RTS_CTS, 0x11, 0x13);
ftDev.SetDataCharacteristics(FTDI.FT_DATA_BITS.FT_BITS_8, FTDI.FT_STOP_BITS.FT_STOP_BITS_1, FTDI.FT_PARITY.FT_PARITY_NONE);
ftDev.SetLatency(2);
ftDev.SetBaudRate((uint)3000000);
into something in python
. I think I can reset the baudrate using d.baudrate = 3000000
, and I can change the latency timer using d.ftdi_fn.ftdi_set_latency_timer(2)
but I do not know how to set the data characteristics, what the constants mean (FTDI.FT_DATA_BITS.FT_BITS_8
, etc.), and how to set the flow control identically to the C#
code.
- Other SO posts have also referred to the D2XX programmers guide found here but didn’t see a way to apply it to this problem
Any suggestions would be appreciated.