-
Notifications
You must be signed in to change notification settings - Fork 8
FTDI FT2232HL Support for Arduino Emulator
Phil Schatzmann edited this page Oct 6, 2025
·
9 revisions
Warning: this functionality is experimental and not fully tested. Please provide some feed back to confirm what's working and what's not!
I have implemented FTDI support (for the FT2232HL) in the Arduino Emulator, which is providing GPIO, SPI, and I2C functionality through USB.

The FTDI FT2232HL is a dual-channel USB-to-UART/SPI/I2C converter that provides:
- Dual independent channels (Channel A and Channel B)
- MPSSE mode for high-speed serial protocols (SPI, I2C)
- Bitbang mode for GPIO operations
- 16 GPIO pins (8 per channel: ADBUS0-7, BDBUS0-7)
- USB connection to host computer
- External pull-up resistors for I2C (typically 4.7kΩ on SCL and SDA lines)
- GPIO Mode: ADBUS0-ADBUS7 available as digital I/O
-
SPI Mode:
- ADBUS0: SCK (Clock)
- ADBUS1: MOSI (Master Out, Slave In)
- ADBUS2: MISO (Master In, Slave Out)
- ADBUS3-7: Available for CS or other GPIO
-
I2C Mode:
- ADBUS0: SCL (Clock) - requires 4.7kΩ pull-up
- ADBUS1: SDA_OUT (Data Out)
- ADBUS2: SDA_IN (Data In) - requires 4.7kΩ pull-up
- ADBUS3-7: Available for other functions
- GPIO Mode: BDBUS0-BDBUS7 available as digital I/O
- Similar protocol support as Channel A
- libftdi1: FTDI device communication library
- pkg-config: For finding libftdi1 (Linux/macOS)
- FTDI D2XX drivers: Alternative high-performance drivers (optional)
# Install libftdi1 development library and pkg-config
sudo apt-get update
sudo apt-get install libftdi1-dev pkg-config
# Verify installation
pkg-config --libs libftdi1
# Should output: -lftdi1
# Install dependencies
sudo apt-get install cmake build-essential libusb-1.0-0-dev
# Clone and build libftdi
git clone https://github.com/libftdi/libftdi.git
cd libftdi
mkdir build && cd build
cmake ..
make
sudo make install
sudo ldconfig
# Create udev rule for FTDI devices (prevents need for sudo)
sudo tee /etc/udev/rules.d/99-ftdi.rules << EOF
# FTDI FT232/FT2232 devices
SUBSYSTEM=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", MODE="0666", GROUP="dialout"
SUBSYSTEM=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6010", MODE="0666", GROUP="dialout"
SUBSYSTEM=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6011", MODE="0666", GROUP="dialout"
SUBSYSTEM=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6014", MODE="0666", GROUP="dialout"
EOF
# Add your user to dialout group
sudo usermod -a -G dialout $USER
# Reload udev rules and restart
sudo udevadm control --reload-rules
sudo udevadm trigger
# Log out and back in, or restart system
# Install development libraries
sudo dnf install libftdi1-devel pkgconfig
# Or on older versions:
sudo yum install libftdi1-devel pkgconfig
# Set up permissions (same udev rules as above)
# Install from official repository
sudo pacman -S libftdi pkg-config
# Install from AUR for latest version
yay -S libftdi-git
# Install Homebrew if not already installed
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# Install libftdi
brew install libftdi pkg-config
# Verify installation
pkg-config --libs libftdi1
# Install MacPorts, then:
sudo port install libftdi1 +universal
# Install dependencies
brew install cmake libusb pkg-config
# Clone and build
git clone https://github.com/libftdi/libftdi.git
cd libftdi
mkdir build && cd build
cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local
make
sudo make install
# Install vcpkg
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
.\bootstrap-vcpkg.bat
# Install libftdi1
.\vcpkg install libftdi1:x64-windows
# Or for 32-bit: .\vcpkg install libftdi1:x86-windows
# Integrate with Visual Studio
.\vcpkg integrate install
-
Download FTDI D2XX drivers:
- Go to FTDI website
- Download "D2XX Direct Drivers" for Windows
- Install the driver package
-
Download libftdi1 binaries:
- Download from libftdi releases
- Extract to
C:\libftdi1\
- Add
C:\libftdi1\bin
to PATH
# In MSYS2 terminal
pacman -S mingw-w64-x86_64-libftdi mingw-w64-x86_64-pkg-config
- Windows 10/11: Drivers are usually installed automatically
- Older Windows: May need manual driver installation from FTDI website
- Driver conflicts: If device doesn't work, check Windows Device Manager
- Virtual Serial Port: Windows may create COM ports - disable if using direct FTDI access
# Linux/macOS: List USB devices
lsusb | grep -i ftdi
# Should show something like: "Bus 001 Device 005: ID 0403:6010 Future Technology Devices International, Ltd FT2232C/D/H Dual UART/FIFO IC"
# Check device permissions (Linux)
ls -l /dev/bus/usb/001/005 # Use actual bus/device numbers
# Should show readable/writable permissions for your user
# Test with libftdi tools (if available)
ftdi_eeprom --help
// Simple test program
#include <ftdi.h>
#include <iostream>
int main() {
struct ftdi_context *ftdi = ftdi_new();
if (!ftdi) {
std::cout << "Failed to create FTDI context" << std::endl;
return -1;
}
// Try to open first FTDI device
int ret = ftdi_usb_open(ftdi, 0x0403, 0x6010);
if (ret == 0) {
std::cout << "FTDI device opened successfully!" << std::endl;
ftdi_usb_close(ftdi);
} else {
std::cout << "Failed to open FTDI device: " << ftdi_get_error_string(ftdi) << std::endl;
}
ftdi_free(ftdi);
return 0;
}
# Compile test (Linux/macOS)
g++ test_ftdi.cpp -lftdi1 -o test_ftdi
./test_ftdi
# Enable FTDI support during configuration
cmake -B build -S . -DUSE_FTDI=ON
# Optional: Also enable other features
cmake -B build -S . -DUSE_FTDI=ON -DUSE_RPI=ON
# Build the project
cmake --build build
cmake_minimum_required(VERSION 3.11...3.19)
# Simple FTDI sketch
arduino_sketch(my_ftdi_project main.ino)
# FTDI sketch with additional libraries
arduino_sketch(sensor_project sensor.ino LIBRARIES MySensorLib)
#include "Arduino.h"
#ifdef USE_FTDI
#include "HardwareSetupFTDI.h"
#endif
void setup() {
Serial.begin(115200);
#ifdef USE_FTDI
// Initialize FTDI with default parameters (VID:0x0403, PID:0x6010)
if (FTDI.begin()) {
Serial.println("FTDI initialized successfully");
} else {
Serial.println("FTDI initialization failed");
}
#endif
}
void setup() {
// Configure pins
pinMode(0, OUTPUT); // ADBUS0 as output
pinMode(1, INPUT); // ADBUS1 as input
pinMode(8, OUTPUT); // BDBUS0 as output (Channel B)
}
void loop() {
// Digital write/read
digitalWrite(0, HIGH);
int state = digitalRead(1);
// Channel B GPIO
digitalWrite(8, !digitalRead(8)); // Toggle pin 8
delay(1000);
}
#include <SPI.h>
void setup() {
SPI.begin();
pinMode(3, OUTPUT); // Use ADBUS3 as chip select
digitalWrite(3, HIGH);
}
void loop() {
digitalWrite(3, LOW); // Select device
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
uint8_t response = SPI.transfer(0x42);
SPI.endTransaction();
digitalWrite(3, HIGH); // Deselect device
Serial.print("SPI Response: 0x");
Serial.println(response, HEX);
delay(1000);
}
#include <Wire.h>
void setup() {
Wire.begin();
Wire.setClock(100000); // 100kHz
}
void loop() {
// Write to I2C device at address 0x48
Wire.beginTransmission(0x48);
Wire.write(0x01); // Register address
Wire.write(0xAB); // Data
uint8_t error = Wire.endTransmission();
if (error == 0) {
Serial.println("I2C write successful");
}
// Read from I2C device
Wire.requestFrom(0x48, 1);
if (Wire.available()) {
uint8_t data = Wire.read();
Serial.print("I2C data: 0x");
Serial.println(data, HEX);
}
delay(1000);
}
void setup() {
// Select specific FTDI device by VID/PID
FTDI.setDeviceParams(0x0403, 0x6010);
// Or by description/serial
FTDI.setDeviceParams(0x0403, 0x6010, "My FTDI Device", "FT123456");
if (FTDI.begin()) {
Serial.println("Specific FTDI device found");
}
}
class HardwareSetupFTDI {
public:
bool begin(bool asDefault = true);
void end();
void setDeviceParams(int vendor_id, int product_id,
const char* description = nullptr,
const char* serial = nullptr);
HardwareGPIO_FTDI* getGPIO();
HardwareI2C_FTDI* getI2C();
HardwareSPI_FTDI* getSPI();
};
// Global instance
extern HardwareSetupFTDI FTDI;
-
GPIO:
pinMode()
,digitalWrite()
,digitalRead()
- SPI: Full SPI library compatibility
- I2C: Full Wire library compatibility
- No analog I/O (analogRead/analogWrite) - FT2232HL is digital only
- No PWM support - use external PWM controller if needed
- No tone generation - use external buzzer controller
- No pulse measurement functions - would require custom implementation
- Check USB connection
- Verify device permissions (
sudo
or udev rules) - Ensure correct VID/PID values
- Install libftdi1-dev package
- Check pkg-config can find libftdi1:
pkg-config --libs libftdi1
- Verify pull-up resistors on SCL and SDA (typically 4.7kΩ)
- Check device address (7-bit vs 8-bit addressing)
- Ensure proper connections
- Verify wiring: SCK, MOSI, MISO connections
- Check SPI mode and clock settings
- Ensure proper chip select timing
Use Case | Recommended Hz | Notes |
---|---|---|
LED dimming | 200-1000 | Avoid visible flicker (>100 Hz) |
Motor control | 500-2000 | Balance between smoothness and accuracy |
Servo | 50 | Standard RC servo frequency |
Fan control | 25-100 | Low frequency for quiet operation |
Audio tone | 100-5000 | Limited quality, for beeps only |
Jitter (µs) | Rating | Action |
---|---|---|
< 10 | Excellent | No action needed |
10-50 | Good | Acceptable for most uses |
50-100 | Fair | Consider optimization |
> 100 | Poor | Enable real-time priority or reduce frequency |
sudo nano /etc/security/limits.conf
# Add these lines (replace 'username'):
username soft rtprio 99
username hard rtprio 99
ulimit -r
# Should show: 99
# After installing dependencies above
cmake -B build -S . -DUSE_FTDI=ON
cmake --build build
# Run example
./build/examples/ftdi-test/ftdi-test
# Same as Linux after installing via Homebrew
cmake -B build -S . -DUSE_FTDI=ON
cmake --build build
# Using vcpkg toolchain
cmake -B build -S . -DUSE_FTDI=ON -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake
cmake --build build --config Release
# Or open in Visual Studio and build
# In MSYS2 MinGW64 terminal
cmake -B build -S . -DUSE_FTDI=ON -G "MinGW Makefiles"
cmake --build build
- Permission denied: Check udev rules and user groups
-
Library not found: Run
sudo ldconfig
after installation -
CMake can't find libftdi1: Install
pkg-config
package
- Homebrew not found: Install Homebrew first
-
Library architecture mismatch: Use
brew install libftdi --universal
- Permission issues: Usually not needed on macOS
- Driver not installed: Install FTDI D2XX drivers from FTDI website
- Library not found: Ensure libftdi1 DLLs are in PATH
- COM port conflicts: Disable VCP drivers in Windows Device Manager if using direct access
Enable debug logging:
void setup() {
Serial.begin(115200);
Logger.setLevel(LogLevel::Debug); // Enable debug messages
}
- GPIO: Suitable for moderate-speed digital I/O
- SPI: Up to ~10MHz clock speeds supported
- I2C: Standard (100kHz) and Fast (400kHz) modes supported
- Latency: USB communication introduces some latency compared to native hardware