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(map(hex, USB_VID_LIST)) ['0x403'] >>> print(map(hex, USB_PID_LIST)) ['0x6001', '0x6010', '0x6011', '0x6014'] 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 with a Mercurial repository on bitbucket. To use / develop on that 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:: $ hg clone http://bitbucket.org/codedstructure/pylibftdi $ cd pylibftdi $ python setup.py develop If permission-related issues occur, then consider using the ``--user`` flag to setup.py to install for only the local user, or try prefixing the above command with ``sudo``. 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.6/2.7 as well as Python 3.2+, so these tests can be run for each Python version:: $ hg clone http://bitbucket.org/codedstructure/pylibftdi $ cd pylibftdi $ python2.7 -m unittest discover ................ ---------------------------------------------------------------------- Ran 17 tests in 0.011s OK $ python3.3 -m unittest discover ................ ---------------------------------------------------------------------- Ran 17 tests in 0.015s 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.