This guide will show you how to use an FT232H to connect to I2C and SPI sensors and breakouts from your desktop PC running Windows, Mac OSX, or Linux. The FT232H also allows for general purpose digital input and output (GPIO) for things like buttons and LEDs.

The cool part about this is that you can then use any of the CircuitPython Libraries that have been written for the numerous sensors and breakouts.

CircuitPython and CircuitPython Libraries

As you are going through this guide, keep in mind the difference between CircuitPython and CircuitPython Libraries:

There are various hardware combinations that allow for running CircuitPython and CircuitPython Libraries. In this guide we will not be using the actual CircuitPython firmware. But we will be using CircuitPython Libraries. To explain this further, let's go over the main hardware platforms and explain where the FT232H fits in to all this.

CircuitPython on Microcontrollers

This is the most straight forward setup.

If you are using a microcontroller that can run CircuitPython, then you will most likely have the low level hardware interfaces needed to access the many sensors and other breakout boards - I2C, SPI, and GPIO. Even better, there is most likely a CircuitPython library written for the sensor.

In this case, you simply install CircuitPython, add the libraries, and then follow whatever guide goes along with your sensor.

CircuitPython on Single Board Computers

This setup requires a special shim library called Blinka.

Single Board Computers (SBC), like the Raspberry Pi and Beagle, also typically have I2C, SPI, and GPIO interfaces available. These boards are also powerful enough to run complete operating systems, like Linux. They can't run CircuitPython directly, but generally don't need to. They can run the much larger Python implementations, like CPython. To allow use of SBCs running Python to use CircuitPython libraries to access sensors over I2C/SPI/GPIO, the Blinka library was created.

In this case, you pip install Blinka, pip install libraries, and then follow whatever guide goes along with your sensor.

CircuitPython on Personal Computers

This is where the FT232H comes in. Here's why.

So what about your super powerful desktop or laptop PC? They can most definitely run Python. But can they also use CircuitPython libraries and talk to I2C/SPI sensors? Can they blink LEDs? Read buttons? Generally, no. As powerful as your Windows, Mac, or Linux PC is, it most likely does not have those low level hardware interfaces. Look on the back of your computer. Do you see an I2C port? A SPI port? A cluster of pins labeled GPIO? Nope.

So what can we do? Well, look again at the back of your PC. See any USB ports? Most likely there are several. Heck, there are probably even several USB ports on the front of your PC! Can we use USB? Yes, thanks to a specialized USB bridge chip made by FTDI - the FT232H.

This will allow us to do something like this:

With FT232H support added to Blinka, we can follow a similar approach as with the SBCs. The FT232H attached to the USB port acts as our surrogate set of low level hardware interfaces.

Neat! Let's see how we can get this all setup and working.

The support for the FT232H in Blinka utilizes the pyftdi library by eblot. This in turn relies on a few other things, like libusb. So before we can actually use the FT232H, we need to get everything setup. See the OS specific sections for what we went through to get things working for each.

Additional Information

Just for reference, here's the install info from the pyftdi library itself:

But first try the install instructions on the pages that follow for your OS.

Post Install Checks

After going through all the install steps for your OS, run this as a simple test to make sure everything is installed correctly. See the rest of the page for some potential hiccups you may run into.

Go ahead and plug in your FT232H to a USB port on your PC.

Check pyftdi is installed correctly

Launch Python:

Download: file
python3

and enter these commands:

Download: file
from pyftdi.ftdi import Ftdi
Ftdi().open_from_url('ftdi:///?')

You should get a list of connected FTDI devices. Most likely, there will be only one.

If an FTDI device can not be found for some reason, you'll see something like this:

If you get

NotImplementedError: Operation not supported or unimplemented on this platform

Go back to the setup steps and Zadig your board if on Windows

Check environment variable within python

At the Python REPL, type

import os
os.environ["BLINKA_FT232H"]

if you get a KeyError it means you did not set the environment variable right

If you see some other errors, go back through the install process for your OS and make sure everything ran correctly.

If you have set it correctly, you'll get a value back

Now type in import board

You should get no errors at all, in which case you can continue onto the next steps!

Board not supported None

If you get

NotImplementedError: Board not supported None

that could mean you did not set the FT232H environmental variable or you don't have the latest python libraries or the FT232H is not plugged in.

BLINKA_FT232H environment variableset, but no FT232H device found

If you get this error, check your USB cable - it could be that you have a charge-only not charge+sync cable.

If you're running Windows, verify you ran Zadig to install the libusbK driver

The device has no langid

On Windows, if you get ValueError: The device has no langid on an open_from_url() call that may mean you dont have libusbk.dll placed in C:\Windows\System32

NotImplementedError: Operation not supported or unimplemented on this platform

If you're running Windows, run Zadig to select/install the libusbK driver on this device

pyftdi.ftdi.FtdiError: UsbError: [Errno 13] Access denied (insufficient permissions)

If you get this on a Mac, it could be you have conflicting ftdi drivers installed, you'll need to remove them!

The easiest way we found to do that is run

brew remove libftdi

This may have been installed by avrdude, open-ocd or other tools! You may have to --force uninstall it depending on what tools you are using.

Note that there are two versions of this board in the wild. It was updated on Feb. 12, 2020 to have a USB C connector, additional pinouts, and other features (see product page for more info).

Pinouts for both the new version (USB C) and the original version are below.

I2C and SPI share the same pins, so only one mode can be used at a time.

Power Pins

  • 5V - this is the 5V power from the USB input.
  • GND - this is the common ground for all power and logic.
  • 3V power output - The new version has a 3.3V power output pin for up to 500mA

GPIO Pins

  • D4 to D7 - can be used as either digital inputs or outputs.
  • C0 to C7 - can be used as either digital inputs or outputs.

I2C Pins

  • SCL - the I2C clock signal is on D0.
  • SDA - the I2C data is on D1+D2.
  • I2C switch - The new version has a switch that connects D1 and D2 for easy I2C interfacing. Move the switch to ON to use I2C and/or the STEMMA QT connector. You can then use either D1 or D2 for SDA.

On the original version only: Note that there are two pins (D1 and D2) which must be tied together and treated as one to use I2C.

SPI Pins

  • SCLK - the SPI clock signal is on D0.
  • MOSI - Master Out, Slave In is on D1.
  • MISO - Master In, Slave Out is on D2.
  • CS0 - Chip Select is on D3. This is not used by Blinka, instead use one of the GPIO pins from above (see example section).

STEMMA QT

  • STEMMA QT connector - The new version has a Stemma QT connector that lets you plug & play any Stemma QT or Qwiic devices, sensors and displays. To use: make sure the I2C switch is set to ON to use the STEMMA QT connector.

All right, now that all that annoying install stuff is done, let's have some fun.

The following sections will provide some basic examples for the main use cases - GPIO, I2C, and SPI.

Make sure you've set the BLINKA_FT232H environment variable.

Installing Libraries for Breakouts

The general process for installing the CircuitPython library you are interested in will be the same as shown in the Python section of the Learn guide for your sensor. Just use pip3.

FAQ & Troubleshooting

There's a few oddities when running Blinka/CircuitPython on linux. Here's a list of stuff to watch for that we know of!

This FAQ covers all the various platforms and hardware setups you can run Blinka on. Therefore, some of the information may not apply to your specific setup.

Update Blinka/Platform Libraries

Most issues can be solved by forcing Python to upgrade to the latest blinka / platform-detect libraries. Try running

sudo python3 -m pip install --upgrade --force-reinstall adafruit-blinka Adafruit-PlatformDetect

Getting an error message about "board" not found or "board" has no attribute

Somehow you have ended up with either the wrong board module or no board module at all.

DO NOT try to fix this by manually installing a library named board. There is one out there and it has nothing to do with Blinka. You will break things if you install that library!

The easiest way to recover is to simply force a reinstall of Blinka with:
python3 -m pip install --upgrade --force-reinstall adafruit-blinka

 

Mixed SPI mode devices

Due to the way we share an SPI peripheral, you cannot have two SPI devices with different 'mode/polarity' on the same SPI bus - you'll get weird data

95% of SPI devices are mode 0, check the driver to see mode or polarity settings. For example:

Why am I getting AttributeError: 'SpiDev' object has no attribute 'writebytes2'?

This is due to having an older version of spidev. You need at least version 3.4. This should have been taken care of when you installed Blinka, but in some cases it does not seem to happen.

To check what version of spidev Python is using:

$ python3
Python 3.6.8 (default, Oct 7 2019, 12:59:55)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import spidev
>>> spidev.__version__
'3.4'
>>>

If you see a version lower then 3.4 reported, then try a force upgrade of spidev with (back at command line):

sudo python3 -m pip install --upgrade --force-reinstall spidev

No Pullup/Pulldown support on some linux boards or MCP2221

Some linux boards, for example, AllWinner-based, do not have support to set pull up or pull down on their GPIO. Use an external resistor instead!

Getting OSError: read error with MCP2221

If you are getting a stack trace that ends with something like:

return self._hid.read(64)
File "hid.pyx", line 122, in hid.device.read
OSError: read error

Try setting an environment variable named BLINKA_MCP2221_RESET_DELAY to a value of 0.5 or higher.

 

Windows:

set BLINKA_MCP2221_RESET_DELAY=0.5

 

Linux:

export BLINKA_MCP2221_RESET_DELAY=0.5

 

This is a value in seconds to wait between resetting the MCP2221 and the attempt to reopen it. The reset is seen by the operating system as a hardware disconnect/reconnect. Different operating systems can need different amounts of time to wait after the reconnect before the attempt to reopen. Setting the above environment variable will override the default reset delay time, allowing it to be increased as needed for different setups.

I can't get neopixel, analogio, audioio, rotaryio, displayio or pulseio to work!

Some CircuitPython modules like may not be supported.

  • Most SBCs do not have analog inputs so there is no analogio
  • Few SBCs have neopixel support so that is only available on Raspberry Pi (and any others that have low level neopixel protocol writing
  • Rotary encoders (rotaryio) is handled by interrupts on microcontrollers, and is not supported on SBCs at this time
  • Likewise pulseio PWM support is not supported on many SBCs, and if it is, it will not support a carrier wave (Infrared transmission)
  • For display usage, we suggest using python Pillow library or Pygame, we do not have displayio support

We aim to have, at a minimum, digitalio and busio (I2C/SPI). This lets you use the vast number of driver libraries

For analog inputs, the MCP3xxx library will give you AnalogIn objects. For PWM outputs, try the PCA9685. For audio, use pygame or other Python3 libraries to play audio.

Some libraries, like Adafruit_CircuitPython_DHT will try to bit-bang if pulsein isn't available. Slow linux boards (<700MHz) may not be able to read the pins fast enough), you'll just have to try!

Help, I'm getting the message "error while loading shared libraries: libgpiod.so.2: cannot open shared object file: No such file or directory"

It looks like libgpiod may not be installed on your board.

Try running the command: sudo apt-get install libgpiod2

All Raspberry Pi Computers Have:

  • 1 x I2C port with busio (but clock stretching is not supported in hardware, so you must set the I2C bus speed to 10KHz to 'fix it')
  • 2 x SPI ports with busio
  • 1 x UART port with serial - note this is shared with the hardware console
  • pulseio.pulseIn using gpiod
  • neopixel support on a few pins
  • No AnalogIn support (Use an MCP3008 or similar to add ADC)
  • No PWM support (Use a PCA9685 or similar to add PWM)

Google Coral TPU Dev Boards Have:

  • 1 x I2C port with busio
  • 1 x SPI ports with busio
  • 1 x UART port with serial - note this is shared with the hardware console
  • 3 x PWMOut support
  • pulseio.pulseIn using gpiod
  • No NeoPixel support
  • No AnalogIn support (Use an MCP3008 or similar to add ADC)

Orange Pi PC Plus Boards Have:

  • 1 x I2C port with busio
  • 1 x SPI ports with busio
  • 1 x UART port with serial
  • pulseio.pulseIn using gpiod
  • No NeoPixel support
  • No AnalogIn support (Use an MCP3008 or similar to add ADC)
  • No PWM support (Use a PCA9685 or similar to add PWM)

Orange Pi R1 Boards Have:

  • 1 x I2C port with busio
  • 1 x SPI port with busio
  • 1 x UART port with serial
  • No NeoPixel support
  • No AnalogIn support (Use an MCP3008 or similar to add ADC)
  • No PWM support (Use a PCA9685 or similar to add PWM)

Odroid C2 Boards Have:

  • 1 x I2C port with busio
  • No SPI support
  • 1 x UART port with serial - note this is shared with the hardware console
  • No NeoPixel support
  • No AnalogIn support (Use an MCP3008 or similar to add ADC)
  • No PWM support (Use a PCA9685 or similar to add PWM)

DragonBoard 410c Boards Have:

  • 2 x I2C port with busio
  • 1 x SPI port with busio
  • 1 x UART port with serial
  • No NeoPixel support
  • No AnalogIn support (Use an MCP3008 or similar to add ADC)
  • No PWM support (Use a PCA9685 or similar to add PWM)

NVIDIA Jetson Nano Boards Have:

  • 2 x I2C port with busio
  • No SPI support without reflashing the board
  • 2 x UART port with serial - note one of these is shared with the hardware console
  • No NeoPixel support
  • No AnalogIn support (Use an MCP3008 or similar to add ADC)
  • No PWM support (Use a PCA9685 or similar to add PWM)

FT232H Breakouts Have:

  • 1x I2C port OR SPI port with busio
  • 12x GPIO pins with digitalio
  • No UART
  • No AnalogIn support
  • No AnalogOut support
  • No PWM support

If you are using Blinka in FT232H mode, then keep in mind these basic limitations.

  • SPI and I2C can not be used at the same time since they share the same pins.
  • GPIO speed is not super fast, so trying to do arbitrary bit bang like things may run into speed issues.
  • There are no ADCs.
  • There are no DACs.
  • UART is not available (its a different FTDI mode)

MCP2221 Breakouts Have:

  • 1x I2C port with busio
  • 4x GPIO pins with digitalio
  • 3x AnalogIn with analogio
  • 1x AnalogOut with analogio
  • 1x UART with pyserial
  • No PWM support
  • No hardware SPI support

If you are using Blinka in MCP2221 mode, then keep in mind these basic limitations.

  • GPIO speed is not super fast, so trying to do arbitrary bit bang like things may run into speed issues.
  • UART is available via pyserial, the serial COM port shows up as a second USB device during enumeration
This guide was first published on Sep 29, 2019. It was last updated on Sep 29, 2019.