Using a FTDI adapter as an IR emitter

This post is part 1 of 5 of  Using a FTDI adapter as an IR

[Crazy intro, just talking to myself]

20 years ago, when I first heard about linux, it didn’t attract me much… spending lots ot time compiling the kernel or the drivers on a 486 seemed so crazy, I wasn’t geeky enough for that. Catched the linux train many years later with Ubuntu 6.04 or 6.10 when almost everything “just worked” and a few google searchs were enough when something didn’t work as expected.

And this week I found myself compiling libftdi and LIRC on a LEGO Mindstorms EV3! Gosh… what happened to me?

[end of crazy intro, start of long and probably boring intro]

Two years ago I found a way to use the soundcard of my laptop as a remote controller for my LEGO motors, thanks to LIRC. It worked OK and it even worked with my Android 4.x phone but never worked properly with ev3dev (and, some months later, I found that it also didn’t worked with my Android 5.x phone) and like most everything else I never really gave him a good use.

Last week someone asked at eurobricks forum how to use a HiTech IR controller with EV3. I also found a way to use it with ev3dev (picking up other people work) and once again never really giving it a good use. Hey, but somebody in the forum said it had tried my code! Thats amazing!

So I returned to LIRC and soundcard, decided to update my own howto. LIRC had evolved a bit in last two years and while reading some docs I found that LIRC also supports FTDI adapters. In fact, its extremely easy to make a USB IR emmiter with just a FTDI adapter and an IR LED, not even a resistor is needed!

I already had a few FTDI cables and adapters but they all use the FT232R model and for reliable timings a FT230X is needed. But my “local” supplier had a Sparkfun Beefy 3 that used FT231X, it’s not the FT230X but it seemed similar enough so I gave it a try… and it works!

[end of long boring intro]

So we need a recent version of LIRC that implements ftdix driver. Ubuntu and Debian jessie (so ev3dev also) only have 0.9.0… We need to download the source code directly from LIRC and compile ourselves. I downloaded the last version available, 0.9.4d.

For LIRC to compile the ftdix driver we also need libftdi. Ubuntu and Debian have it but I also compiled it from source – not sure why but at least for ev3dev just installing Debian libftdi packages is not enough and it seems that just compilling libftdi is also not enough, I had to do both.

My EV3 is running ev3dev snaphot 2017-02-06. Two days later there’s already a new snaphot but I only updated with apt:

sudo apt update
sudo apt upgrade
sudo apt dist-upgrade

After reboot my Ev3 is running kernel 4.4.47:

Linux ev3dev 4.4.47-19-ev3dev-ev3 #1 PREEMPT Wed Feb 8 14:15:28 CST 2017 armv5tejl GNU/Linux

First we install all dependencies needed for both LIRC and libftdi:

sudo apt install libftdi-dev build-essential pkg-config xsltproc libusb-1.0 cmake libboost-all-dev

This takes about an hour, lots of packages (mostly related to libboost)

Before spending lots of time compiling it is better to test if out FTDI adapter works as expected so we can download this “hello ftdi” example:

I saved it as “hello-ftdi.c”.

Now we insert our FTDI adapter and look for it at the end of dmesg:

[47800.964059] usb 1-1.2: new full-speed USB device number 8 using ohci
[47801.111337] usb 1-1.2: New USB device found, idVendor=0403, idProduct=6015
[47801.111424] usb 1-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[47801.111472] usb 1-1.2: Product: FT231X USB UART
[47801.111515] usb 1-1.2: Manufacturer: FTDI
[47801.111553] usb 1-1.2: SerialNumber: DN01DR29
[47801.306754] usbcore: registered new interface driver usbserial
[47801.414060] usbcore: registered new interface driver ftdi_sio
[47801.423075] usbserial: USB Serial support registered for FTDI USB Serial Device
[47801.437994] ftdi_sio 1-1.2:1.0: FTDI USB Serial Device converter detected
[47801.449290] usb 1-1.2: Detected FT-X
[47801.454135] usb 1-1.2: FTDI USB Serial Device converter now attached to ttyUSB0

We see that it is detected and we take note of the idVendor and idProduct values:

idVendor=0403, idProduct=6015

For later use we also take note of its Serial Number:

DN01DR29

Now we edit the “hello-ftdi.c” program and update the idVendor and idProduct.

/* hello-ftdi.c: flash LED connected between CTS and GND.
   This example uses the libftdi API.
   Minimal error checking; written for brevity, not durability. */

#include <stdio.h>
#include <ftdi.h>

#define LED 0x08  /* CTS  (brown wire on FTDI cable) */

int main()
{
    unsigned char c = 0;
    struct ftdi_context ftdic;

    /* Initialize context for subsequent function calls */
    ftdi_init(&ftdic);

    /* Open FTDI device based on FT232R vendor & product IDs */
    if(ftdi_usb_open(&ftdic, 0x0403, 0x6015) < 0) {
        puts("Can't open device");
        return 1;
    }

    /* Enable bitbang mode with a single output line */
    ftdi_enable_bitbang(&ftdic, LED);

    /* Endless loop: invert LED state, write output, pause 1 second */
    for(;;) {
        c ^= LED;
        ftdi_write_data(&ftdic, &c, 1);
        sleep(1);
    }
}

Then we compile our “hello-ftdi” test program:

gcc hello-ftdi.c -lftdi -o hello-ftdi
hello-ftdi.c: In function 'main':
hello-ftdi.c:25:5: warning: 'ftdi_enable_bitbang' is deprecated (declared at /usr/include/ftdi.h:413) [-Wdeprecated-declarations]
     ftdi_enable_bitbang(&ftdic, LED);

We can ignore that warning, as long as we get a “hello-ftdi” binary file.

To run it we need root permissions:

sudo ./hello-ftdi

If we connect a common led between CTS (A) and GND (K) we will see it blink each second so we can replace it with a infrared LED (940 nm is better but 950 nm will also work). And yes, we don’t need to use a resistor.

If we check dmesg again, we notice that our test program disconnected the ttyUSB device, as required:

[15564.602213] ftdi_sio ttyUSB0: FTDI USB Serial Device converter now disconnected from ttyUSB0
[15564.602615] ftdi_sio 1-1.2:1.0: device disconnected

This post was to long for my web server so I broke in several.