Programming FTDI devices in Python: Part 2

Using pylibftdi on Linux

Linux and pylibftdi

In the first part, I used the FTDI Windows D2XX driver and Python ftd2xx library to do some simple I/O testing on an FTDI module. However, when attempting to run the same code on Linux, I had problems getting the d2xx driver to cooperate with the ftd2xx library, so switched to using the pylibftdi library, which uses the open-source libftdi driver in place of d2xx.

Installation is as you’d expect: use sudo apt-get (or equivalent) to install libftdi 1.x, then sudo pip (or pip3) to install pylibftdi. There are then a couple of Linux-specific issues:

  • If you want to avoid running all your code as root, you need to give permission for user-space applications to access the USB device. FTDI devices usually have a PID of 0403, so to allow user access to all FTDI devices, create a file /etc/udev/rules.d/99-libftdi.rules with the contents:
    SUBSYSTEMS=="usb", ATTRS{idVendor}=="0403", GROUP="dialout", MODE="0660"

    Then re-plug the device for the new rule to take effect. This rule will apply to all devices with the FTDI vendor ID, for security reasons you may need to restrict it to devices that match a specific product ID as well.

  •  By default, Linux will load ftdi_sio and usbserial kernel modules when the device is plugged in. Various ways of preventing this have been posted on the Internet, but fortunately libftdi works fine without having to unload the modules.

To see if the library is working, try listing all the FTDI devices:

import sys, pylibftdi as ftdi
print(ftdi.Driver().list_devices())

This should return a list of devices, each with manufacturer, description and serial number, e.g.

[('FTDI', 'FT2232H MiniModule', 'FT2FNDAR')]

Device I/O

Enabling bitbang mode is similar to the D2XX function calls used in part 1:

d = ftdi.Device()                  # Open first device
OP = 1                             # Bit 0 will be an output
d.ftdi_fn.ftdi_set_bitmode(OP, 1)  # Return 0 if bitbang mode set OK

A baud rate of 9600 is set by default, so the O/P bit clock rate should be 16 times that, as discussed in the previous post.

The differences in Python 2.7 and 3.x byte string handling are still a potential problem, though the pylibftdi library goes some way towards addressing this by using a ‘Latin 1’ encoder to translate between unicode and binary strings. However, to simplify the manipulation and storage of transmit & receive data, I am retaining the list-of-integers storage method used in the first part;

def ft_write(d, data):
    s = str(bytearray(data)) if sys.version_info<(3,) else bytes(data)
    return d.write(s)
ft_write(d, (OP, 0))

def ft_read(d, nbytes):
    s = d.read(nbytes)
    return [ord(c) for c in s] if type(s) is str else list(s)
ft_read(d, 1)

As before, the read cycle returns [254], since the unused pins are floating high, and we have set bit 0 low.

See the next post for an example of code that runs on Linux and Windows.

Copyright (c) Jeremy P Bentham 2018. Please credit this blog if you use the information or software in it.

Caterpillar pic chip small

2 thoughts on “Programming FTDI devices in Python: Part 2”

Leave a comment