Welcome to pylibftdi’s documentation!¶
pylibftdi is a simple library interacting with FTDI devices to provide serial and parallel IO from Python.
Examples:
>>> from pylibftdi import BitBangDevice
>>> with BitBangDevice('FT0123') as dev:
... dev.port |= 1
>>> # Send a MIDI 'note on' message
>>> from pylibftdi import Device
>>> with Device() as dev:
... dev.baudrate = 31250
... dev.write('\x90\x64\x64')
The two main use cases it serves are:
- the need to control or monitor external equipment, for which a FTDI module may be a cheap and reliable starting point.
- the need to interact with existing devices which are known to contain FTDI chipsets for their USB interface.
FTDI (http://www.ftdichip.com) create devices (chipsets, modules, cables etc) to interface devices to the USB port of your computer.
libftdi (http://www.intra2net.com/en/developer/libftdi/) is an open source driver to communicate with these devices, and runs on top of libusb. It works on Windows, Linux, and Mac OS X, and likely other systems too.
pylibftdi is a pure Python module which interfaces (via ctypes) to libftdi, exposing a simple file-like API to connected devices. It supports serial and parallel IO in a straight-forward way, and aims to be one of the simplest ways of interacting with the world outside your PC.
Contents¶
Introduction¶
pylibftdi is a minimal Pythonic interface to FTDI devices using libftdi.
Features: |
|
---|---|
Limitations: |
|
Usage¶
The primary interface is the Device
class in the pylibftdi package; this
gives serial access on relevant FTDI devices (e.g. the UM232R), providing a
file-like interface (read, write). Baudrate is controlled with the baudrate
property.
If a Device instance is created with mode='t'
(text mode) then read() and
write() can use the given encoding
(defaulting to latin-1). This doesn’t
make a lot of difference on Python 2 (and can be omitted), but allows easier
integration with passing unicode strings between devices in Python 3.
Multiple devices are supported by passing the desired device serial number (as
a string) in the device_id
parameter - this is the first parameter in both
Device() and BitBangDevice() constructors. Alternatively the device ‘description’
can be given, and an attempt will be made to match this if matching by serial
number fails.
Examples¶
>>> from pylibftdi import Device
>>>
>>> with Device(mode='t') as dev:
... dev.baudrate = 115200
... dev.write('Hello World')
The pylibftdi.BitBangDevice wrapper provides access to the parallel IO mode of
operation through the port
and direction
properties. These provide an
8 bit IO port including all the relevant bit operations to make things simple.
>>> from pylibftdi import BitBangDevice
>>>
>>> with BitBangDevice('FTE00P4L') as bb:
... bb.direction = 0x0F # four LSB are output(1), four MSB are input(0)
... bb.port |= 2 # set bit 1
... bb.port &= 0xFE # clear bit 0
There is support for a number of external devices and protocols, including interfacing with HD44780 LCDs using the 4-bit interface.
History & Motivation¶
This package is the result of various bits of work using FTDI’s devices, primarily for controlling external devices. Some of this is documented on the codedstructure blog, codedstructure.blogspot.com
Several other open-source Python FTDI wrappers exist, and each may be best for some projects. Some aim at closely wrapping the libftdi interface, others use FTDI’s own D2XX driver (ftd2xx) or talk directly to USB via libusb or similar (such as pyftdi).
The aim for pylibftdi is to work with libftdi, but to provide a high-level Pythonic interface. Various wrappers and utility functions are also part of the distribution; following Python’s batteries included approach, there are various interesting devices supported out-of-the-box - or at least there will be soon!
Plans¶
- Add more examples: SPI devices, knight-rider effects, input devices, MIDI…
- Perhaps add support for D2XX driver, though the name then becomes a slight liability ;)
License¶
Copyright (c) 2010-2020 Ben Bass <benbass@codedstructure.net>
pylibftdi is released under the MIT licence; see the file “LICENSE.txt” for information.
All trademarks referenced herein are property of their respective holders. libFTDI itself is developed by Intra2net AG. No association with Intra2net is claimed or implied, but I have found their library helpful and had fun with it…
Quick Start¶
Install pylibftdi¶
See the installation instructions for more detailed requirements, but hopefully things will work by just running the following:
$ python3 -m pip install pylibftdi
Connect and enumerate FTDI devices¶
Connect the FTDI device to a free USB port. Run the list_devices
example
to enumerate connected FTDI devices:
$ python3 -m pylibftdi.examples.list_devices
For each connected device, this will show manufacturer, model identifier, and serial number. With a single device connected, the output maybe something like the following:
FTDI:UM232H:FTUBIOWF
Though hopefully with a different serial number, or else you’ve either stolen mine, or you are me…
Test some actual IO¶
Output example¶
Connect an LED between D0 of your bit-bang capable device and ground, via a 330 - 1K ohm resistor as appropriate.
Test the installation and functioning of pylibftdi with the following:
$ python3 -m pylibftdi.examples.led_flash
The LED should now flash at approximately 1Hz.
Input example¶
To test some input, remove any connections from the port lines initially, then run the following, which reads and prints the status of the input lines regularly:
$ python3 -m pylibftdi.examples.pin_read
The pin_read
example is a complete command line application which can
be used to monitor for particular values on the attached device pins, and
output an appropriate error code on match. Repeat the above with a trailing
--help
for info.
Using pylibftdi
from the REPL¶
Since pylibftdi
v0.18.0, a __main__.py
module is included which
imports all the exported constants, classes and functions from pylibftdi
.
This allows quick interaction with FTDI devices from the Python REPL:
$ python3 -im pylibftdi
>>> d = Device()
>>> d.write('Hello World')
>>>
Installation¶
Unsurprisingly, pylibftdi
depends on libftdi
, and installing this varies
according to your operating system. Chances are that following one of the
following instructions will install the required prerequisites. If not, be
aware that libftdi in turn relies on libusb
.
Installing pylibftdi
itself is straightforward - it is a pure Python package
(using ctypes
for bindings), and has no dependencies outside the Python
standard library for installation. Don’t expect it to work happily without
libftdi
installed though :-)
$ pip install pylibftdi
Depending on your environment, you may want to set up a virtual environment
or use either the --user
flag, or prefix the command with sudo
to
gain root privileges.
Windows¶
I perform only limited testing of pylibftdi on Windows, but it should work correctly provided the requirements of libftdi and libusb are correctly installed.
Recent libftdi binaries for Windows seem to be available from the picusb project on Sourceforge. Download libftdi1-1.1_devkit_x86_x64_21Feb2014.zip or later from that site, which includes the required
Installing libraries on Windows is easier with recent versions of Python (2.7.9, 3.4+) installing pip directly, so the standard approach of pip install pylibftdi will now easily work on Windows.
Mac OS X¶
I suggest using homebrew to install libftdi:
$ brew install libftdi
On OS X Mavericks (and presumably future versions) Apple include a driver for
FTDI devices. This needs unloading before libftdi
can access FTDI devices
directly. See the Troubleshooting section for instructions.
Linux¶
There are two steps in getting a sensible installation in Linux systems:
- Getting
libftdi
and its dependencies installed - Ensuring permissions allow access to the device without requiring root
privileges. Symptoms of this not being done are programs only working
properly when run with
sudo
, giving ‘-4’ or ‘-8’ error codes in other cases.
Each of these steps will be slightly different depending on the distribution
in use. I’ve tested pylibftdi
on Debian Wheezy (on a Raspberry Pi),
Ubuntu (various versions, running on a fairly standard ThinkPad laptop),
and Arch Linux (running on a PogoPlug - one of the early pink ones).
Debian (Raspberry Pi) / Ubuntu etc¶
On Debian like systems (including Ubuntu, Mint, Debian, etc), the package
libftdi1-dev
should give you what you need as far as the libftdi library
is concerned:
$ sudo apt-get install libftdi1-dev
The following works for both a Raspberry Pi (Debian Wheezy) and Ubuntu 12.04, getting ordinary users (e.g. ‘pi’ on the RPi) access to the FTDI device without needing root permissions:
Create a file
/etc/udev/rules.d/99-libftdi.rules
. You will need sudo access to create this file.Put the following in the file:
SUBSYSTEMS=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", GROUP="dialout", MODE="0660" SUBSYSTEMS=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6010", GROUP="dialout", MODE="0660" SUBSYSTEMS=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6011", GROUP="dialout", MODE="0660" SUBSYSTEMS=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6014", GROUP="dialout", MODE="0660" SUBSYSTEMS=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6015", GROUP="dialout", MODE="0660"
The list of USB product IDs above matches the default used by pylibftdi
, but
some FTDI devices may use other USB PIDs. You could try removing the match on
idProduct
altogether, just matching on the FTDI vendor ID as follows:
SUBSYSTEMS=="usb", ATTRS{idVendor}=="0403", GROUP="dialout", MODE="0660"
Or use lsusb
or similar to determine the exact values to use (or try checking
dmesg
output on device insertion / removal).
udevadm monitor --environment
is also helpful, but note that the environment
‘keys’ it gives are different to the attributes (filenames within /sys/devices/…)
which the ATTRS will match. Perhaps ENV{} matches work just as well, though I’ve
only tried matching on ATTRS.
Note that changed udev rules files will be picked up automatically by the udev daemon, but will only be acted upon on device actions, so unplug/plug in the device to check whether you’re latest rules iteration actually works :-)
Also note that the udev rules above assume that your user is in the ‘dialout’ group - if not, add it to your user with the following, though note that this will not apply immediately, not a full reboot may be needed on some systems:
sudo usermod -aG dialout $USER
See http://wiki.debian.org/udev for more on writing udev rules.
Arch Linux¶
The libftdi
package (sensibly enough) provides the libftdi
library:
$ sudo pacman -S libftdi
Similar udev rules to those above for Debian should be included (again in
/etc/udev/rules.d/99-libftdi.rules
or similar), though the GROUP directive
should be changed to set the group to ‘users’:
SUBSYSTEMS=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", GROUP="users", MODE="0660"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6010", GROUP="users", MODE="0660"
(etc...)
Testing installation¶
Connect your device, and run the following (as a regular user):
$ python3 -m pylibftdi.examples.list_devices
If all goes well, the program should report information about each connected
device. If no information is printed, but it is when run with sudo
, a
possibility is permissions problems - see the section under Linux above
regarding udev
rules.
If the above works correctly, then try the following:
$ python3 -m pylibftdi.examples.led_flash
Even without any LED connected, this should ‘work’ without any error - quit with Ctrl-C. Likely errors at this point are either permissions problems (e.g. udev rules not working), or not finding the device at all - although the earlier stage is likely to have failed if this were the case.
Feel free to contact me (@codedstructure on Twitter) if you have any issues with installation, though be aware I don’t have much in the way of Windows systems to test.
Basic Usage¶
pylibftdi is a minimal Pythonic interface to FTDI devices using libftdi. Rather than simply expose all the methods of the underlying library directly, it aims to provide a simpler API for the main use-cases of serial and parallel IO, while still allowing the use of the more advanced functions of the library.
General¶
The primary interface is the Device
class in the pylibftdi
package; this
gives serial access on relevant FTDI devices (e.g. the UM232R), providing a
file-like interface (read, write). Baudrate is controlled with the baudrate
property.
If a Device instance is created with mode='t'
(text mode) then read() and
write() can use the given encoding
(defaulting to latin-1). This doesn’t
make a lot of difference on Python 2 (and can be omitted), but allows easier
integration with passing unicode strings between devices in Python 3.
Multiple devices are supported by passing the desired device serial number (as
a string) in the device_id
parameter - this is the first parameter in both
Device() and BitBangDevice() constructors. Alternatively the device ‘description’
can be given, and an attempt will be made to match this if matching by serial
number fails.
In the event that multiple devices (perhaps of identical type) have the same
description and serial number, the device_index
parameter may be given to
open matching devices by numerical index; this defaults to zero, meaning the
first matching device.
Examples¶
>>> from pylibftdi import Device
>>>
>>> with Device(mode='t') as dev:
... dev.baudrate = 115200
... dev.write('Hello World')
The pylibftdi.BitBangDevice wrapper provides access to the parallel IO mode of
operation through the port
and direction
properties. These provide an
8 bit IO port including all the relevant bit operations to make things simple.
>>> from pylibftdi import BitBangDevice
>>>
>>> with BitBangDevice('FTE00P4L') as bb:
... bb.direction = 0x0F # four LSB are output(1), four MSB are input(0)
... bb.port |= 2 # set bit 1
... bb.port &= 0xFE # clear bit 0
There is support for a number of external devices and protocols, specifically for interfacing with HD44780 LCDs using the 4-bit interface.
Bit-bang mode¶
Bit-bang mode allows the programmer direct access (both read and write) to the state of the IO lines from a compatible FTDI device.
The interface provided by FTDI is intended to mirror the type of usage on a microcontroller, and is similar to the ‘user port’ on many old 8-bit computers such as the BBC Micro and Commodore 64.
The basic model is to have two 8 bit ports - one for data, and one for ‘direction’. The data port maps each of the 8 bits to 8 independent IO signals, each of which can be configured separately as an ‘input’ or an ‘output’.
In pylibftdi, the data port is given by the port
attribute of a BitBangDevice instance, and the direction control is provided by the direction
attribute. Both these attributes are implemented as Python properties, so no method calls are needed on them - simple read and write in Python-land converts to read and write in the physical world seen by the FTDI device.
The direction register maps to
where each bit maps to a separate digital signal,
Read-Modify-Write¶
Port vs Latch
Via the augmented assignment operations, pylibftdi BitBangDevice
instances support read-modify-write operations, such as arithmetic (+=
etc), bitwise (&=
), and other logical operations such as shift (<<=
)
Examples¶
>>> from pylibftdi import BitBangDevice
>>>
>>> with BitBangDevice('FTE00P4L') as bb:
... bb.direction = 0x0F # four LSB are output(1), four MSB are input(0)
... bb.port |= 2 # set bit 1
... bb.port &= 0xFE # clear bit 0
>>> with BitBangDevice() as bb:
... bb.port = 1
... while True:
... # Rotate the value in bb.port
... bb.port = ((bb.port << 1) | ((bb.port >> 8) & 1)) & 0xFF
... time.sleep(1)
The Bus class¶
Dealing with bit masks and shifts gets messy quickly. Some languages such as C and C++ provide direct support for accessing bits - or series of consecutive bits - with bitfields. The Bus
class provides the facility to provide a similar level of support to pylibftdi BitBangDevice
classes.
As an example, consider an HD44780 LCD display. These have a data channel of either 4 or 8 bits, and a number of additional status lines - rs
which acts as a register select pin - indicating whether a data byte is a command (0) or data (1), and e
- clock enable.:
class LCD(object):
"""
The UM232R/245R is wired to the LCD as follows:
DB0..3 to LCD D4..D7 (pin 11..pin 14)
DB6 to LCD 'RS' (pin 4)
DB7 to LCD 'E' (pin 6)
"""
data = Bus(0, 4)
rs = Bus(6)
e = Bus(7)
Serial mode¶
The default mode of pylibftdi devices is to behave as a serial UART device, similar to the ‘COM1’ device found on older PCs. Nowadays most PCs operate with serial devices over USB-serial adapters, which may often include their own FTDI chips. To remain compatible with the RS232 standard however, these adapters will often include level-shifting circuitry which is of no benefit in communicating with other circuits operating at the 3.3 or 5 volt levels the FTDI hardware uses.
The default serial configuration is 9600 baud, 8 data bits, 1 stop bit and no parity (sometimes referred to as 8-N-1). This is the default configuration of the old ‘COM’ devices back to the days of the original IBM PC and MS-DOS.
Setting line parameters¶
Changing line parameters other than the baudrate is supported via use of the underlying FTDI function calls.
The SerialDevice class¶
While the standard Device
class supports standard read
and write
methods, as well as a baudrate
property, further functionality is provided by the SerialDevice
class, available either as a top-level import from pylibftdi
or through the serial_device
module. This subclasses Device
and adds additional properties to access various control and handshake lines.
The following properties are available:
property meaning direction cts
Clear To Send Input rts
Ready To Send Output dsr
Data Set Ready Input dtr
Data Transmit Ready Output ri
Ring Indicator Input
Note that these lines are normally active-low, and pylibftdi
makes no attempt to hide this from the user. It is impractical to try to ‘undo’ this inversion in any case, since it can be disabled in the EEPROM settings of the device. Just be aware if using these lines as GPIO that the electrical sense will be the opposite of the value read. The lines are intended to support handshaking rather than GPIO, so this is not normally an issue; if CTS is connected to RTS, then values written to RTS will be reflected in the value read from CTS.
Subclassing Device - A MIDI device¶
To abstract application code from the details of any particular interface, it may be helpful to subclass the Device
class, providing the required configuration in the __init__
method to act in a certain way. For example, the MIDI protocol used by electronic music devices is an asynchronous serial protocol operating at 31250 baud, and with the same 8-N-1 parameters which pylibftdi defaults to.
Creating a MidiDevice
subclass of Device
is straightforward:
class MidiDevice(Device):
"subclass of pylibftdi.Device configured for MIDI"
def __init__(self, *o, **k):
Device.__init__(self, *o, **k)
self.baudrate = 31250
Note it is important that the superclass __init__
is called first; calling it on an uninitialised Device
would fail, and even if it succeeded, the superclass __init__
method resets baudrate
to 9600 anyway to ensure a consistent setup for devices which may have been previously used with different parameters.
Use of the MidiDevice
class is simple - as a pylibftdi Device instance, it provides a file-based API. Simply read()
and write()
the data to an instance of the class:
>>> m = MidiDevice()
>>> m.write('\x90\x80\x80')
>>> time.sleep(1)
>>> m.write('\x80\x00')
Advanced Usage¶
libftdi
function access¶
Three attributes of Device
instances are documented which allow direct
access to the underlying libftdi
functionality.
fdll
- this is a reference to the loadedlibftdi
library, loaded via ctypes. This should be used with the normal ctypes protocols.ctx
- this is a reference to the context of the current device context. It is managed as a raw ctypes byte-string, so can be modified if required at the byte-level using appropriatectypes
methods.ftdi_fn
- a convenience function wrapper, this is the preferred method for accessing library functions for a specific device instance. This is a function forwarder to the localfdll
attribute, but also wraps the device context and passes it as the first argument. In this way, usingdevice.ftdi_fn.ft_xyz
is more like the D2XX driver provided by FTDI, in which the device context is passed in at initialisation time and then the client no longer needs to care about it. A call to:>>> device.ftdi_fn.ft_xyz(1, 2, 3)
is equivalent to the following:
>>> device.fdll.ft_xyz(ctypes.byref(device.ctx), 1, 2, 3)
but has the advantages of being shorter and not requiring ctypes to be in scope.
incorrect operations using any of these attributes of devices are liable to crash the Python interpreter
Examples¶
The following example shows opening a device in serial mode, switching temporarily to bit-bang mode, then back to serial and writing a string. Why this would be wanted is anyone’s guess ;-)
>>> from pylibftdi import Device
>>>
>>> with Device() as dev:
>>> dev.ftdi_fn.ftdi_set_bitmode(1, 0x01)
>>> dev.write('\x00\x01\x00')
>>> dev.ftdi_fn.ftdi_set_bitmode(0, 0x00)
>>> dev.write('Hello World!!!')
The libftdi documentation should be consulted in conjunction with the ctypes reference for guidance on using these features.
pylibftdi questions¶
None of these are yet frequently asked, and perhaps they never will be… But they are still questions, and they relate to pylibftdi.
Using pylibftdi - General¶
Can I use pylibftdi with device XYZ?¶
If the device XYZ is (or uses as it’s ) an FTDI device, then possibly. A large number of devices will work, but won’t be recognised due to the limited USB Vendor and Product IDs which pylibftdi checks for.
To see the vendor / product IDs which are supported, run the following:
>>> from pylibftdi import USB_VID_LIST, USB_PID_LIST
>>> print(', '.join(hex(pid) for pid in USB_VID_LIST))
0x403
>>> print(', '.join(hex(pid) for pid in USB_PID_LIST))
0x6001, 0x6010, 0x6011, 0x6014, 0x6015
If a FTDI device with a VID / PID not matching the above is required, then the device’s values should be appended to the appropriate list after import:
>>> from pylibftdi import USB_PID_LIST, USB_VID_LIST, Device
>>> USB_PID_LIST.append(0x1234)
>>>
>>> dev = Device() # will now recognise a device with PID 0x1234.
Which devices are recommended?¶
While I used to do a lot of soldering, I prefer the cleaner way of breadboarding nowadays. As such I can strongly recommend the FTDI DIP modules which plug into a breadboard nice and easy, can be self-powered from USB, and can be re-used for dozens of different projects.
I’ve used (and test against) the following, all of which have 0.1” pin spacing in two rows 0.5” or 0.6” apart, so will sit across the central divide of any breadboard:
- UB232R
- a small 8 pin device with mini-USB port; serial and CBUS bit-bang.
- UM245R
- a 24-pin device with parallel FIFO modes. Full-size USB type B socket.
- UM232R
- a 24-pin device with serial and bit-bang modes. Full-size USB type B socket.
- UM232H
- this contains a more modern FT232H device, and libftdi support is fairly recent (requires 0.20 or later). Supports USB 2.0 Hi-Speed mode though, and lots of interesting modes (I2C, SPI, JTAG…) which I’ve not looked at yet. Mini-USB socket.
Personally I’d go with the UM232R device for compatibility. It works great with both UART and bit-bang IO, which I target as the two main use-cases for pylibftdi. The UM232H is certainly feature-packed though, and I hope to support some of the more interesting modes in future.
Using pylibftdi - Programming¶
How do I set the baudrate?¶
In both serial and parallel mode, the internal baudrate generator (BRG) is
set using the baudrate
property of the Device
instance. Reading this
will show the current baudrate (which defaults to 9600); writing to it
will attempt to set the BRG to that value.
On failure to set the baudrate, it will remain at its previous setting.
In parallel mode, the actual bytes-per-second rate of parallel data is 16x the programmed BRG value. This is an effect of the FTDI devices themselves, and is not hidden by pylibftdi.
How do I send unicode over a serial connection?¶
If a Device
instance is created with mode='t'
, then text-mode is
activated. This is analogous to opening files; after all, the API is
intentionally modelled on file objects whereever possible.
When text-mode is used, an encoding can be specified. The default is
latin-1
for the very practical reason that it is transparent to 8-bit
binary data; by default a text-mode serial connection looks just like a
binary mode one.
An alternative encoding can be used provided in the same constructor call
used to instantiate the Device
class, e.g.:
>>> dev = Device(mode='t', encoding='utf-8')
Read and write operations will then return / take unicode values.
Whether it is sensible to try and send unicode over a ftdi connection is a separate issue… At least consider doing codec operations at a higher level in your application.
How do I use multiple-interface devices?¶
Some FTDI devices have multiple interfaces, for example the FT2232H has 2 and the FT4232H has four. In terms of accessing them, they can be considered as independent devices; once a connection is established to one of them, it is isolated from the other interfaces.
To select which interface to use when opening a connection to a specific
interface on a multiple-interface device, use the interface_select
parameter of the Device (or BitBangDevice) class constructor.
The value should be one of the following values. Symbolic constants are
provided in the pylibftdi namespace.
interface_select
Meaning INTERFACE_ANY (0) Any interface INTERFACE_A (1) INTERFACE A INTERFACE_B (2) INTERFACE B INTERFACE_C (3) INTERFACE C INTERFACE_D (4) INTERFACE D
You should be able to open multiple Device
s with different
interface_select
settings.
Thanks to Daniel Forer for testing multiple device support.
What is the difference between the port
and latch
BitBangDevice properties?¶
latch reflects the current state of the output latch (i.e. the last value
written to the port), while port
reflects input states as well. Writing to
either port
or latch
has an identical effect, so when pylibftdi is used
only for output, there is no effective difference, and port
is recommended
for simplicity and consistency.
The place where it does make a difference is during read-modify-write operations. Consider the following:
>>> dev = BitBangDevice() # 1
>>> dev.direction = 0x81 # 2 # set bits 0 and 7 are output
>>> dev.port = 0 # 3
>>> for _ in range(255): # 4
>>> dev.port += 1 # 5 # read-modify-write operation
In this (admittedly contrived!) scenario, if one of the input lines D1..D6
were held low, then they would cause the counter to effectively ‘stop’. The
+= 1
operation would never actually set the bit as required (because it is
an input at 0), and the highest output bit would never get set.
Using dev.latch
in lines 3 and 5 above would resolve this, as the
read-modify-write operation on line 5 is simply working on the in-memory
latch value, rather than reading the inputs, and it would simply count up from
0 to 255 in steps of one, writing the value to the device (which would be
ignored in the case of input lines).
Similar concepts exist in many microcontrollers, for example see http://stackoverflow.com/a/2623498 for a possibly better explanation, though in a slightly different context :)
If you aren’t using read-modify-write operations (e.g. augmented assignment),
or you have a direction on the port of either ALL_INPUTS (0) or ALL_OUTPUTS
(1), then just ignore this section and use port
:)
What is the purpose of the chunk_size
parameter?¶
While libftdi is performing I/O to the device, it is not really running Python code at all, but C library code via ctypes. If there is a significant amount of data, especially at low baud-rates, this can be a significant delay during which no Python bytecode is executed. The most obvious result of this is that no signals are delivered to the Python process during this time, and interrupt signals (Ctrl-C) will be ignored.
Try the following:
>>> dev = Device()
>>> dev.baudrate = 120 # nice and slow!
>>> dev.write('helloworld' * 1000)
This should take approximately 10 seconds prior to returning, and crucially,
Ctrl-C interruptions will be deferred for all that time. By setting
chunk_size
on the device (which may be set either as a keyword parameter
during Device
instantiation, or at a later point as an attribute of the
Device
instance), the I/O operations are performed in chunks of at most
the specified number of bytes. Setting it to 0, the default value, disables
this chunking.
Repeat the above command but prior to the write operation, set
dev.chunk_size = 10
. A Ctrl-C interruption should now kick-in almost
instantly. There is a performance trade-off however; if using chunk_size
is
required, set it as high as is reasonable for your application.
Using pylibftdi - Interfacing¶
How do I control an LED?¶
pylibftdi devices generally have sufficient output current to sink or source the 10mA or so which a low(ish) current LED will need. A series resistor is essential to protect both the LED and the FTDI device itself; a value between 220 and 470 ohms should be sufficient depending on required brightness / LED efficiency.
How do I control a higher current device?¶
FTDI devices will typically provide a few tens of milli-amps, but beyond that things either just won’t work, or the device could be damaged. For medium current operation, a standard bipolar transistor switch will suffice; for larger loads a MOSFET or relay should be used. (Note a relay will require a low-power transistor switch anyway). Search online for something like ‘mosfet logic switch’ or ‘transistor relay switch’ for more details.
What is the state of an unconnected input pin?¶
This depends on the device and the EEPROM configuration values. Most devices will have weak (typ. 200Kohm) pull-ups on input pins, so there is no harm leaving them floating. Consult the datasheet for your device for definitive information, but you can always just leave an (unconnected) device and read it’s pins when set as inputs; chances are they will read 255 / 0xFF:
>>> dev = BitBangDevice(direction=0)
>>> dev.port
255
While not recommended for anything serious, this does allow the possibility of reading a input switch state by simply connecting a switch between an input pin and ground (possibly with a low value - e.g. 100 ohm - series resistor to prevent accidents should it be set to an output and set high…). Note that with a normal push-to-make switch, the value will read ‘1’ when the switch is not pressed; pressing it will set the input line value to ‘0’.
Developing pylibftdi¶
How do I checkout and use the latest development version?¶
pylibftdi is currently developed on GitHub, though started out as a Mercurial repository on bitbucket.org. There may still be references to old bitbucket issues in the docs.
To use / develop on the latest version, it must first be cloned locally, after which it can be ‘installed’. Clone the repository to a local directory and install (with the ‘develop’ target ideally) as follows:
$ git clone https://github.com/codedstructure/pylibftdi
$ cd pylibftdi
$ python3 -m venv env
$ source env/bin/activate
(env) $ python3 setup.py develop
Note this also creates a virtual environment within the project directory; see here
Note for now there is only the master branch, so need to worry about which branch is required.
How do I run the tests?¶
Tests aren’t included in the distutils distribution, so clone the repository and run from there. pylibftdi supports Python 2.7 as well as Python 3.4+, so these tests can be run for each Python version:
$ git clone https://github.com/codedstructure/pylibftdi
<various output stuff>
$ cd pylibftdi
$ python2.7 -m unittest discover
..........................
----------------------------------------------------------------------
Ran 26 tests in 0.006s
OK
$ python3.7 -m unittest discover
..........................
----------------------------------------------------------------------
Ran 26 tests in 0.007s
OK
How can I determine and select the underlying libftdi library?¶
Since pylibftdi 0.12, the Driver exposes a libftdi_version
method,
which returns a tuple whose first three entries correspond to major, minor,
and micro versions of the libftdi driver being used.
With the recent (early 2013) release of libftdi1 - which can coexist with the earlier 0.x versions - it is now possible to select which library to load when instantiating the Driver:
Python 2.7.2 (default, Jun 20 2012, 16:23:33)
[GCC 4.2.1 Compatible Apple Clang 4.0 (tags/Apple/clang-418.0.60)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from pylibftdi import Driver
>>> Driver().libftdi_version()
(1, 0, 0, '1.0', 'v1.0-6-gafb9082')
>>> Driver('ftdi').libftdi_version()
(0, 99, 0, '0.99', 'v0.17-305-g50d77f8')
>>> Driver('libftdi1').libftdi_version()
(1, 0, 0, '1.0', 'v1.0-6-gafb9082')
>>> Driver(('libftdi1', 'libftdi')).libftdi_version()
(1, 0, 0, '1.0', 'v1.0-6-gafb9082')
>>> Driver(('libftdi', 'libftdi1')).libftdi_version()
(0, 99, 0, '0.99', 'v0.17-305-g50d77f8')
>>> Driver(('libftdi', 'libftdi1')).libftdi_version()
pylibftdi
now prefers libftdi1 over libftdi, if both are installed. Since
different OSs require different parameters to be given to find a library,
the default search list given to ctypes.util.find_library is as follows:
Driver._dll_list = ('ftdi1', 'libftdi1', 'ftdi', 'libftdi')
This covers Windows (which requires the ‘lib’ prefix), Linux (which requires its absence), and Mac OS X, which is happy with either.
pylibftdi troubleshooting¶
Once up-and-running, pylibftdi is designed to be very simple, but sometimes getting it working in the first place can be more difficult.
Error messages¶
FtdiError: unable to claim usb device. Make sure the default FTDI driver is not in use (-5)
¶
This indicates a conflict with FTDI’s own drivers, and is (as far as I know) mainly a problem on Mac OS X, where they can be disabled (until reboot) by unloading the appropriate kernel module.
MacOS (Mavericks and later)¶
Starting with OS X Mavericks, OS X includes kernel drivers which will reserve the FTDI device by default. In addition, the FTDI-provided VCP driver will claim the device by default. These need unloading before libftdi will be able` to communicate with the device:
sudo kextunload -bundle-id com.apple.driver.AppleUSBFTDI
sudo kextunload -bundle-id com.FTDI.driver.FTDIUSBSerialDriver
Similarly to reload them:
sudo kextload -bundle-id com.apple.driver.AppleUSBFTDI
sudo kextload -bundle-id com.FTDI.driver.FTDIUSBSerialDriver
Earlier versions of pylibftdi
(prior to 0.18.0) included scripts for
MacOS which unloaded / reloaded these drivers, but these complicated cross-platform
packaging so have been removed. If you are on using MacOS with programs which
need these drivers on a frequent basis (such as the Arduino IDE when using
older FTDI-based Arduino boards), consider implementing these yourself, along the
lines of the following (which assumes ~/bin is in your path):
cat << EOF > /usr/local/bin/ftdi_osx_driver_unload
sudo kextunload -bundle-id com.apple.driver.AppleUSBFTDI
sudo kextunload -bundle-id com.FTDI.driver.FTDIUSBSerialDriver
EOF
cat << EOF > /usr/local/bin/ftdi_osx_driver_reload
sudo kextload -bundle-id com.apple.driver.AppleUSBFTDI
sudo kextload -bundle-id com.FTDI.driver.FTDIUSBSerialDriver
EOF
chmod +x /usr/local/bin/ftdi_osx_driver_*
OS X Mountain Lion and earlier¶
Whereas Mavericks includes an FTDI driver directly, earlier versions of OS X did not, and if this issue occurred it would typically as a result of installing some other program - for example the Arduino IDE.
As a result, the kernel module may have different names, but FTDIUSBSerialDriver.kext is the usual culprit. Unload the kernel driver as follows:
sudo kextunload /System/Library/Extensions/FTDIUSBSerialDriver.kext
To reload the kernel driver, do the following:
sudo kextload /System/Library/Extensions/FTDIUSBSerialDriver.kext
If you aren’t using whatever program might have installed it, the driver could be permanently removed (to prevent the need to continually unload it), but this is dangerous:
sudo rm /System/Library/Extensions/FTDIUSBSerialDriver.kext
Diagnosis¶
Getting a list of USB devices
Mac OS X¶
Start ‘System Information’, then select Hardware > USB, and look for your
device. On the command line, system_profiler SPUSBDataType
can be used.
In the following example I’ve piped it into grep -C 7 FTDI
, to print 7
lines either side of a match on the string ‘FTDI’:
ben$ system_profiler SPUSBDataType | grep -C 7 FTDI
UM232H:
Product ID: 0x6014
Vendor ID: 0x0403 (Future Technology Devices International Limited)
Version: 9.00
Serial Number: FTUBIOWF
Speed: Up to 480 Mb/sec
Manufacturer: FTDI
Location ID: 0x24710000 / 7
Current Available (mA): 500
Current Required (mA): 90
USB Reader:
Product ID: 0x4082
Linux¶
Use lsusb
. Example from my laptop:
ben@ben-laptop:~$ lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 006 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 007 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 008 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 008 Device 011: ID 0a5c:217f Broadcom Corp. Bluetooth Controller
Bus 002 Device 009: ID 17ef:481d Lenovo
Bus 002 Device 016: ID 0403:6014 Future Technology Devices International, Ltd FT232H Single HS USB-UART/FIFO IC
Where did my ttyUSB devices go?¶
When a pylibftdi.Device() is opened, any kernel device which was previously present will become unavailable. On Linux for example, a serial-capable FTDI device will (via the ftdi_sio driver) create a device node such as /dev/ttyUSB0 (or ttyUSB1,2,3 etc). This device allows use of the FTDI device as a simple file in the Linux filesystem which can be read and written. Various programs such as the Arduino IDE (at least when communicating with some board variants) and libraries such as PySerial will use this device. Once libftdi opens a device, the corresponding entry in /dev/ will disappear. Prior to pylibftdi version 0.16, the simplest way to get the device node to reappear would be to unplug and replug the USB device itself. Starting from 0.16, this should no longer be necessary as the kernel driver (which exports /dev/ttyUSB…) is reattached when the pylibftdi device is closed. This behaviour can be controlled by the auto_detach argument (which is defaulted to True) to the Device class; setting it to False reverts to the old behaviour.
Note that on recent OS X, libftdi doesn’t ‘steal’ the device, but instead refuses to open it. The kernel devices can be seen as /dev/tty.usbserial-xxxxxxxx, where xxxxxxxx is the device serial number. FTDI’s Application Note AN134 details this further (see section ‘Using Apple-provided VCP or D2XX with OS X 10.9 & 10.10’). See the section above under Installation for further details on resolving this.
Gathering information¶
Starting with pylibftdi version 0.15, an example script to gather system information is included, which will help in any diagnosis required.
Run the following:
python3 -m pylibftdi.examples.info
this will output a range of information related to the versions of libftdi libusb in use, as well as the system platform and Python version, for example:
pylibftdi version : 0.18.0
libftdi version : libftdi_version(major=1, minor=4, micro=0, version_str=b'1.4', snapshot_str=b'unknown')
libftdi library name : libftdi1.so.2
libusb version : libusb_version(major=1, minor=0, micro=22, nano=11312, rc=b'', describe=b'http://libusb.info')
libusb library name : libusb-1.0.so.0
Python version : 3.7.3
OS platform : Linux-5.0.0-32-generic-x86_64-with-Ubuntu-19.04-disco
pylibftdi Package¶
pylibftdi
Package¶
pylibftdi - python wrapper for libftdi
Copyright (c) 2010-2020 Ben Bass <benbass@codedstructure.net> See LICENSE file for details and (absence of) warranty
pylibftdi: https://github.com/codedstructure/pylibftdi
libftdi can be found at: http://www.intra2net.com/en/developer/libftdi/
Neither libftdi nor Intra2net are associated with this project; if something goes wrong here, it’s almost definitely my fault rather than a problem with the libftdi library.
_base
Module¶
pylibftdi - python wrapper for libftdi
Copyright (c) 2010-2020 Ben Bass <benbass@codedstructure.net> See LICENSE file for details and (absence of) warranty
pylibftdi: https://github.com/codedstructure/pylibftdi
-
exception
pylibftdi._base.
LibraryMissingError
[source]¶ Bases:
pylibftdi._base.FtdiError
device
Module¶
pylibftdi.device - access to individual FTDI devices
Copyright (c) 2010-2020 Ben Bass <benbass@codedstructure.net> See LICENSE file for details and (absence of) warranty
pylibftdi: https://github.com/codedstructure/pylibftdi
-
class
pylibftdi.device.
Device
(device_id=None, mode='b', encoding='latin1', interface_select=None, device_index=0, **kwargs)[source]¶ Bases:
object
Represents a connection to a single FTDI device
-
__init__
(device_id=None, mode='b', encoding='latin1', interface_select=None, device_index=0, **kwargs)[source]¶ 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).
Parameters: - 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.
- mode – either ‘b’ (binary) or ‘t’ (text). This primarily affects Python 3 calls to read() and write(), which will accept/return unicode strings which will be encoded/decoded according to the given…
- encoding – the codec name to be used for text operations.
- interface_select – select interface to use on multi-interface devices
- device_index – optional index of the device to open, in the event of multiple matches for other parameters (PID, VID, device_id). Defaults to zero (the first device found).
The following parameters are only available as keyword parameters and override class attributes, so may be specified in subclasses.
Parameters: - lazy_open – if True, then the device will not be opened immediately - the user must perform an explicit open() call prior to other operations.
- chunk_size – if non-zero, split read and write operations into chunks of this size. With large or slow accesses, interruptions (i.e. KeyboardInterrupt) may not happen in a timely fashion.
- auto_detach – default True, whether to automatically re-attach the kernel driver on device close.
- index – optional index into list_devices() to open. Useful in the event that multiple devices of differing VID/PID are attached, where device_index is insufficient to select as device indexing restarts at 0 for each VID/PID combination.
-
flush
(flush_what=1)[source]¶ Instruct the FTDI device to flush its FIFO buffers
By default both the input and output buffers will be flushed, but the caller can selectively chose to only flush the input or output buffers using flush_what:
Parameters: flush_what – select what to flush: FLUSH_BOTH (default); FLUSH_INPUT (just the rx buffer); FLUSH_OUTPUT (just the tx buffer)
-
next
()¶
-
read
(length) → bytes/string of up to `length` bytes.[source]¶ read upto length bytes from the FTDI device :param length: maximum number of bytes to read :return: value read from device :rtype: bytes if self.mode is ‘b’, else decode with self.encoding
-
readline
(size=0)[source]¶ readline() for file-like compatibility.
Parameters: size – maximum amount of data to read looking for a line Returns: a line of text, or size bytes if no line-ending found This only works for mode=’t’ on Python3
-
write
(data) → count of bytes actually written[source]¶ write given data string to the FTDI device
Parameters: data (string or bytes) – string to be written Returns: count of bytes written, which may be less than len(data)
-
writelines
(lines)[source]¶ writelines for file-like compatibility.
Parameters: lines – sequence of lines to write
-
auto_detach
= True¶
-
baudrate
¶ get or set the baudrate of the FTDI device. Re-read after setting to ensure baudrate was accepted by the driver.
-
chunk_size
= 0¶
-
closed
¶ The Python file API defines a read-only ‘closed’ attribute
-
ftdi_fn
¶ this allows the vast majority of libftdi functions which are called with a pointer to a ftdi_context struct as the first parameter to be called here preventing the need to leak self.ctx into the user code (and import byref from ctypes):
>>> with Device() as dev: ... # set 8 bit data, 2 stop bits, no parity ... dev.ftdi_fn.ftdi_set_line_property(8, 2, 0) ...
-
lazy_open
= False¶
-
softspace
= 0¶
-
driver
Module¶
pylibftdi.driver - interface to the libftdi library
Copyright (c) 2010-2014 Ben Bass <benbass@codedstructure.net> See LICENSE file for details and (absence of) warranty
pylibftdi: https://github.com/codedstructure/pylibftdi
-
class
pylibftdi.driver.
Driver
(libftdi_search=None, **kwargs)[source]¶ Bases:
object
This is where it all happens… We load the libftdi library, and use it.
-
__init__
(libftdi_search=None, **kwargs)[source]¶ Parameters: libftdi_search (string or sequence of strings) – force a particular version of libftdi to be used can specify either library name(s) or path(s)
-
libftdi_version
()[source]¶ Returns: the version of the underlying library being used Return type: tuple (major, minor, micro, version_string, snapshot_string)
-
list_devices
()[source]¶ Returns: (manufacturer, description, serial#) for each attached device, e.g.: [(‘FTDI’, ‘UM232R USB <-> Serial’, ‘FTE4FFVQ’), (‘FTDI’, ‘UM245R’, ‘FTE00P4L’)]
Return type: a list of string triples the serial number can be used to open specific devices
-
fdll
¶ ctypes DLL referencing the libftdi library
This is the main interface to FTDI functionality.
-
-
class
pylibftdi.driver.
ftdi_device_list
[source]¶ Bases:
_ctypes.Structure
-
dev
¶ Structure/Union member
-
next
¶ Structure/Union member
-
-
class
pylibftdi.driver.
ftdi_version_info
[source]¶ Bases:
_ctypes.Structure
-
major
¶ Structure/Union member
-
micro
¶ Structure/Union member
-
minor
¶ Structure/Union member
-
snapshot_str
¶ Structure/Union member
-
version_str
¶ Structure/Union member
-
-
class
pylibftdi.driver.
libftdi_version
(major, minor, micro, version_str, snapshot_str)¶ Bases:
tuple
-
major
¶ Alias for field number 0
-
micro
¶ Alias for field number 2
-
minor
¶ Alias for field number 1
-
snapshot_str
¶ Alias for field number 4
-
version_str
¶ Alias for field number 3
-
bitbang
Module¶
pylibftdi - python wrapper for libftdi
Copyright (c) 2010-2014 Ben Bass <benbass@codedstructure.net> See LICENSE file for details and (absence of) warranty
pylibftdi: https://github.com/codedstructure/pylibftdi
-
class
pylibftdi.bitbang.
BitBangDevice
(device_id=None, direction=255, lazy_open=False, sync=True, bitbang_mode=1, interface_select=None, **kwargs)[source]¶ Bases:
pylibftdi.device.Device
simple subclass to support bit-bang mode
Internally uses async mode at the moment, but provides a ‘sync’ flag (defaulting to True) which controls the behaviour of port reading and writing - if set, the FIFOs are ignored (read) or cleared (write) so operations will appear synchronous
- Adds three read/write properties to the base class:
direction: 8 bit input(0)/output(1) direction control. port: 8 bit IO port, as defined by direction. latch: 8 bit output value, allowing e.g. bb.latch += 1 to make sense
when there is a mix of input and output lines
-
__init__
(device_id=None, direction=255, lazy_open=False, sync=True, bitbang_mode=1, interface_select=None, **kwargs)[source]¶ 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).
Parameters: - 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.
- mode – either ‘b’ (binary) or ‘t’ (text). This primarily affects Python 3 calls to read() and write(), which will accept/return unicode strings which will be encoded/decoded according to the given…
- encoding – the codec name to be used for text operations.
- interface_select – select interface to use on multi-interface devices
- device_index – optional index of the device to open, in the event of multiple matches for other parameters (PID, VID, device_id). Defaults to zero (the first device found).
The following parameters are only available as keyword parameters and override class attributes, so may be specified in subclasses.
Parameters: - lazy_open – if True, then the device will not be opened immediately - the user must perform an explicit open() call prior to other operations.
- chunk_size – if non-zero, split read and write operations into chunks of this size. With large or slow accesses, interruptions (i.e. KeyboardInterrupt) may not happen in a timely fashion.
- auto_detach – default True, whether to automatically re-attach the kernel driver on device close.
- index – optional index into list_devices() to open. Useful in the event that multiple devices of differing VID/PID are attached, where device_index is insufficient to select as device indexing restarts at 0 for each VID/PID combination.
-
read_pins
()[source]¶ read the current ‘actual’ state of the pins
Returns: 8-bit binary representation of pin state Return type: int
-
direction
¶ get or set the direction of each of the IO lines. LSB=D0, MSB=D7 1 for output, 0 for input
-
latch
¶ latch property - the output latch (in-memory representation of output pin state)
Note _latch is not masked by direction (except on initialisation), as otherwise a loop incrementing a mixed input/output port would not work, as it would ‘stop’ on input pins. This is the primary use case for ‘latch’. It’s basically a port which ignores input.
Returns: the state of the output latch
-
port
¶ get or set the state of the IO lines. The value of output lines is persisted in this object for the purposes of reading, so read-modify-write operations (e.g. drv.port+=1) are valid.
serial_device
Module¶
pylibftdi - python wrapper for libftdi
Copyright (c) 2010-2014 Ben Bass <benbass@codedstructure.net> See LICENSE file for details and (absence of) warranty
pylibftdi: https://github.com/codedstructure/pylibftdi
-
class
pylibftdi.serial_device.
SerialDevice
(device_id=None, mode='b', encoding='latin1', interface_select=None, device_index=0, **kwargs)[source]¶ Bases:
pylibftdi.device.Device
simple subclass to support serial(rs232) lines
cts, dsr, ri - input dtr, rts - output modem_status - return a two byte bitfield of various values
Note: These lines are all active-low by default, though this can be changed in the EEPROM settings. pylibftdi does not attempt to hide these settings, and simply writes out the given values (i.e. ‘1’ will typically make an output line ‘active’ - and therefore low)
-
cts
¶ get the state of CTS (1 = ‘active’)
-
dsr
¶ get the state of DSR (1 = ‘active’)
-
dtr
¶ set (or get the previous set) state of the DTR line
Returns: the state of the DTR line; None if not previously set
-
modem_status
¶ Layout of the first byte: B0..B3 - must be 0 B4 Clear to send (CTS) 0 = inactive 1 = active B5 Data set ready (DTS) 0 = inactive 1 = active B6 Ring indicator (RI) 0 = inactive 1 = active B7 Receive line signal detect (RLSD) 0 = inactive 1 = active
Layout of the second byte: B0 Data ready (DR) B1 Overrun error (OE) B2 Parity error (PE) B3 Framing error (FE) B4 Break interrupt (BI) B5 Transmitter holding register (THRE) B6 Transmitter empty (TEMT) B7 Error in RCVR FIFO
‘{:016b}’.format(d.modem_status) ‘0110000000000001’ - b5,b6 set in MSB (‘2nd byte’), b0 set in first byte (despite the libftdi docs saying this shouldn’t be set)
-
ri
¶ get the state of RI (1 = ‘active’)
-
rts
¶ set (or get the previous set) state of the RTS line
Returns: the state of the RTS line; None if not previously set
-
util
Module¶
pylibftdi - python wrapper for libftdi
Copyright (c) 2010-2014 Ben Bass <benbass@codedstructure.net> See LICENSE file for details and (absence of) warranty
pylibftdi: https://github.com/codedstructure/pylibftdi
-
class
pylibftdi.util.
Bus
(offset, width=1)[source]¶ Bases:
object
This class is a descriptor for a bus of a given width starting at a given offset (0 = LSB). The device which does the actual reading and writing is assumed to be a BitBangDevice instance in the ‘device’ attribute of the object to which this is attached.
Subpackages¶
examples Package¶
examples
Package¶
pylibftdi examples
bit_server
Module¶
bit_server.py - remote HTTP interface to bit-bangged FTDI port This runs as a web server, connect to port 8008
Change HTTP_PORT for different port number or supply alternate as args[1]
- Requires:
- pylibftdi
-
class
pylibftdi.examples.bit_server.
ReqHandler
(request, client_address, server)[source]¶ Bases:
http.server.BaseHTTPRequestHandler
lcd
Module¶
Write a string (argv[1] if run from command line) to a HD44780 LCD module connected via a FTDI UM232R/245R module using pylibftdi
example usage:
# while true; > do python lcd.py $( awk ‘{print $1}’ /proc/loadavg); > sleep 5; > done
Copyright (c) 2010-2014 Ben Bass <benbass@codedstructure.net> All rights reserved.
-
class
pylibftdi.examples.lcd.
LCD
(device)[source]¶ Bases:
object
- The UM232R/245R is wired to the LCD as follows:
- DB0..3 to LCD D4..D7 (pin 11..pin 14) DB6 to LCD ‘RS’ (pin 4) DB7 to LCD ‘E’ (pin 6)
-
init_four_bit
()[source]¶ set the LCD’s 4 bit mode, since we only have 8 data lines and need at least 2 to strobe data into the module and select between data and commands.
-
data
¶ This class is a descriptor for a bus of a given width starting at a given offset (0 = LSB). The device which does the actual reading and writing is assumed to be a BitBangDevice instance in the ‘device’ attribute of the object to which this is attached.
-
e
¶ This class is a descriptor for a bus of a given width starting at a given offset (0 = LSB). The device which does the actual reading and writing is assumed to be a BitBangDevice instance in the ‘device’ attribute of the object to which this is attached.
-
rs
¶ This class is a descriptor for a bus of a given width starting at a given offset (0 = LSB). The device which does the actual reading and writing is assumed to be a BitBangDevice instance in the ‘device’ attribute of the object to which this is attached.
led_flash
Module¶
Flash an LED connected via a FTDI UM232R/245R module using pylibftdi
Optionally supply a flash rate (in Hz, default 1) as an argument
Copyright (c) 2010-2014 Ben Bass <benbass@codedstructure.net> All rights reserved.
list_devices
Module¶
Report connected FTDI devices. This may be useful in obtaining serial numbers to use as the device_id parameter of the Device() constructor to communicate with a specific device when more than one is present.
example usage:
$ python pylibftdi/examples/list_devices.py FTDI:UB232R:FTAS1UN5 FTDI:UM232R USB <-> Serial:FTE4FFVQ
To open a device specifically to communicate with the second of these devices, the following would be used:
>>> from pylibftdi import Device
>>> dev = Device(device_id="FTE4FFVQ")
>>>
Copyright (c) 2011-2014 Ben Bass <benbass@codedstructure.net> All rights reserved.
magic_candle
Module¶
- Magic Candle - light falling on the LDR turns on the LED, which due
- to arrangement keeps the LED on until LDR/LED path is blocked
LDR (via a transistor switch - dark = ‘1’) - D0 LED (via series resistor) - D1
pylibftdi - codedstructure 2013-2014
-
class
pylibftdi.examples.magic_candle.
Candle
[source]¶ Bases:
object
-
be_light
¶ This class is a descriptor for a bus of a given width starting at a given offset (0 = LSB). The device which does the actual reading and writing is assumed to be a BitBangDevice instance in the ‘device’ attribute of the object to which this is attached.
-
is_dark
¶ This class is a descriptor for a bus of a given width starting at a given offset (0 = LSB). The device which does the actual reading and writing is assumed to be a BitBangDevice instance in the ‘device’ attribute of the object to which this is attached.
-
midi_output
Module¶
-
class
pylibftdi.examples.midi_output.
MidiDevice
(*o, **k)[source]¶ Bases:
pylibftdi.device.Device
-
__init__
(*o, **k)[source]¶ 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).
Parameters: - 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.
- mode – either ‘b’ (binary) or ‘t’ (text). This primarily affects Python 3 calls to read() and write(), which will accept/return unicode strings which will be encoded/decoded according to the given…
- encoding – the codec name to be used for text operations.
- interface_select – select interface to use on multi-interface devices
- device_index – optional index of the device to open, in the event of multiple matches for other parameters (PID, VID, device_id). Defaults to zero (the first device found).
The following parameters are only available as keyword parameters and override class attributes, so may be specified in subclasses.
Parameters: - lazy_open – if True, then the device will not be opened immediately - the user must perform an explicit open() call prior to other operations.
- chunk_size – if non-zero, split read and write operations into chunks of this size. With large or slow accesses, interruptions (i.e. KeyboardInterrupt) may not happen in a timely fashion.
- auto_detach – default True, whether to automatically re-attach the kernel driver on device close.
- index – optional index into list_devices() to open. Useful in the event that multiple devices of differing VID/PID are attached, where device_index is insufficient to select as device indexing restarts at 0 for each VID/PID combination.
-
pin_read
Module¶
Display values on input pins of a BitBangDevice.
- TODO:
- ANSI colours / display differences in bold
- example - beep on pin 1 going high:
- $ pylibftdi/examples/pin_read.py -n 0.01 -m 1 -k 1 && beep
Copyright (c) 2011-2014 Ben Bass <benbass@codedstructure.net> All rights reserved.
-
pylibftdi.examples.pin_read.
display_loop
(interval=1, count=0, match=None, mask=255)[source]¶ display and compare the value
Parameters: - interval – polling interval in seconds
- count – number of polls to do, or infinite if 0
- match – value to look for to exit early
- mask – mask of read value before comparing to match
Returns: ‘ok’. either a match was made or none was requested
Return type: bool
serial_loopback
Module¶
test serial loopback; assumes Rx and Tx are connected
Copyright (c) 2010-2020 Ben Bass <benbass@codedstructure.net> All rights reserved.
info
Module¶
Report environment info relevant to pylibftdi
example usage:
$ python3 -m pylibftdi.examples.info
pylibftdi version : 0.15.0
libftdi version : libftdi_version(major=1, minor=1, micro=0, version_str=b'1.1', snapshot_str=b'unknown')
libftdi library path : /usr/local/lib/libftdi1.dylib
libusb version : libusb_version(major=1, minor=0, micro=19, nano=10903, rc=b'', describe=b'http://libusb.info')
libusb library path : /usr/local/lib/libusb-1.0.dylib
Python version : 3.4.0
OS platform : Darwin-14.1.0-x86_64-i386-64bit
Copyright (c) 2015-2020 Ben Bass <benbass@codedstructure.net>