Der FTDI-Chip ist bei einfachen USB-Geräten relativ weit verbreitet. Er simuliert eine serielle Schnittstelle am USB-Port. Wer selbst einfache Geräte programmieren will, kann FTDI unter Linux mit der offenen Bibliothek libftdi nutzen. Im folgenden Tutorial wird ein einfaches Beispiel zum Ansprechen des Chips mit Hilfe dieser Bibliothek gezeigt.

Das Beispiel ist recht einfach gestaltet: Eine Leuchtdiode (LED) wird mittels USB an einem Rechner angeschlossen und soll bei bestimmten Ereignissen leuchten. Anwendungsfälle lassen sich eine ganze Reihe ausdenken:

  • Die Diode soll leuchten, wenn neue E-Mail-Nachrichten vorliegen.
  • Die LED soll leuchten, wenn Netzwerkpakete empfangen und/oder abgeschickt werden.
  • Die Diode blinkt im Takt zur Musik, die auf dem Rechner gespielt wird.
  • Eine Infrarot-Diode kann als Fernbedienung benutzt werden. Der Computer kann damit den Fernseher oder DVD-Spieler steuern.

Diese Fälle übersteigen die Ansprüche dieses Tutorials und sollten als Anregung verstanden werden. Der erste Fall wird in einem neuen Artikel behandelt werden, dann jedoch mittels Perl und der Bibliothek D2XX. Das folgende Tutorial behandelt die von Intra2Net entwickelte Bibliothek libftdi.

Hardware

Neben dem Rechner werden einige Elektronikteile benötigt: Eine einfache Leuchtdiode (LED) ist das zentrale Bauteil. Diese wird an ein FTDI-Breakout-Board angeschlossen. Günstige Boards gibt es von SparkFun (Abb. 1). In Deutschland kann man diese Boards leicht bei Watterott beziehen. Es genügt das Board „FTDI Basic Breakout – 3.3V oder 5V” oder ein „FT232R Breakout” mit 3,3V, wie sie in Abbildung 1 zu sehen sind. Alternativ kann auch USB-zu RS232R-Kabel verwendet werden, was ebenfalls günstig ist. Bei den meisten Anschlüssen ist es sinnvoll das LED mit einem 220 Ω-Widerstand (rot-rot-braun-gold) abzusichern.

ftdi_breakout_boards_01

Abbildung 1: Links das 3,3V FT232R-Breakout-Board, das alle 8 RS232-Ausgänge besitzt, rechts das Basic Board (hier 5V) mit vier Ausgängen.

ftdi_breakout_boards_02

Abbildung 2: FTDI-Breakout-Board mit USB-Kabel, LED (difus, 5mm), 220 Ω-Widerstand.

Der Kostenpunkt der gesamten Hardware samt USB-Kabel liegt in etwa zwischen 15 und 20 EUR. Für ein paar Euro mehr kann man z.B. bei Conrad Electronic schöne Gehäuse erstehen, in die die LED-Anzeige eingebaut werden kann.

FDTI-Treiber installieren

Aktuelle Linux-Kernels erkennen den FTDI-Chip zumeist ohne Probleme, sofern das Kernel-Modul ftdi_sio vorhanden ist. Prüfen kann man dies, indem man ein Breakout-Board an einen freien USB-Port anschließt und auf der Kommandozeile lsmod | grep ftdi eingibt. Das Modul ftdi_sio sollte als geladen in der Liste erscheinen. Falls das nicht der Fall ist, kann man die Module per Hand nachladen: sudo modprobe ftdi_sio. Sollte das zu Fehlermeldungen führen, ist das Modul entweder nicht im Kernel, oder es liegen andere Probleme vor. dmesg mag in diesem Fall Aufschluss über mögliche Fehler geben.

Ist das Modul installiert und wird der FTDI-Chip richtig erkannt, ist alles gut! dmesg gibt auch im Erfolgsfall entsprechende Informationen, sobald ein USB-Kabel mit FTDI-Chip angesteckt wird. Zur Überwachung kann man den Befehl tail -f /var/log/messages eingeben (ggf. mit vorangestelltem sudo) und den Chip danach einstecken. Nachrichten wie „Detected FT232RL“ oder „FTDI USB Serial Device converter now attached to ttyUSB“ sollten im Message-Log erscheinen.

Unter Debian und Ubuntu liegt die Bibliothek von Intra2net in zwei Paketvarianten vor: Einmal als libftdi1 und einmal als libftdipp1. Letztere ist die C++-Version, während es sich bei der ersten um jene in C handelt. Im Tutorial benutzen wir nur die C-Variante.

Für das unten gezeigte Beispiel wird neben einem C-Compiler (gcc und am besten auch noch libc6-dev) das Paket libftdi-dev benötigt. Die C++-Variante des Entwicklungspaket heißt demzufolge libftdipp-dev.

Hilfe, ich will nicht root sein!

Debian, zumindest Lenny, scheint die Berechtigungen für den Zugriff auf FTDI richtig zu setzen. Beim Einstecken eines FTDI-Geräts sollte im Verzeichnis /dev/ ein Eintrag ttyUSBx erscheinen, wobei x für die Ziffer 0 oder höher steht (je nachdem, wie viele Geräte angeschlossen sind). Die Berechtigungen sollten idealerweise auf 660 für den Benutzer root und die Gruppe dialout gesetzt sein.

Unter Ubuntu funktioniert das Ganze nicht out-of-the-box. Hier darf nur root auf das Gerät zugreifen, was beim Einsatz des Geräts sicher nicht im Sinne des Erfinders ist. Schuld daran sind fehlende Einstellungen im udev-Subsystem (In Debian sind diese vorhanden). Man kann dies sehr einfach erreichen, indem man als root eine Datei /etc/udev/rules.d/40-permissions.rules (unter neueren Ubutus kann es sein, dass es eine andere Datei mit ähnlichem Inhalt bereits gibt) mit folgendem Inhalt anlegt:

ID von Vendor und Produkt sind die des FTDI-Chips. Mit lsusb kann überprüft werden, ob die Nummern auch die des eingesteckten Geräts sind. Es gibt möglicherweise FTDI-kompatible Chips mit anderen Nummern, soweit ich das im Internet erkennen konnte. Falls die Nummern nicht übereinstimmen sollten, kann man die obige Zeile einfach entsprechend abändern. Nach dem Eintragen sollte man das udev-System neu starten: sudo /etc/init.d/udev restart. Unter Karmic oder einem anderen Upstart-System genügt: sudo restart udev.

Der aktuelle Benutzer (also der, der auf das Gerät zugreifen will) muss Mitglied der Gruppe dialout sein! Prüfen lässt sich das mit groups. Falls man noch nicht Mitglied der Gruppe ist, hilft ein sudo usermod -a -G dialout <user>. <user> muss natürlich mit dem eigentlichen Benutzernamen ersetzt werden. Danach muss man ggf. seine Sitzung (oder den Terminal) neu starten, um als Mitglied der Gruppe geführt zu werden. Nun kann man das Gerät auch ohne root-Rechte ansprechen (neu einstecken)!

FTDI/RS232-Basics

FTDI-Einführungen gibt es einige, deshalb will ich mich hier kurz fassen: Die serielle Standardschnittstelle RS232 haben viele Rechner heute nicht mehr. Sie wird mit einer Spannung von bis zu ±12 V betrieben und besitzt bis zu 8 Anschlüsse. USB unterscheidet sich stark davon: Sie Spannung beträgt maximal 5V (zumindest bei Standardanschlüssen) und es existieren nur 2 Anschlüsse. Darüber hinaus ist das USB-Protokoll relativ komplex und verlangt beispielsweise eine Gerätedetektion u.ä. Details des Datenaustauschs werden von libftdi übernommen und sind in diesem Tutorial daher nicht von Belang.

Wie wird FTDI nun angesprochen? Je nach Breakout-Board kann man maximal 8 Ausgänge für den Ein- und Ausgang von Signalen benutzen. Zusätzlich existiert noch ein serieller Datentransfer, wie er bei seriellen Geräten zum Einsatz kommt. Beispiele dafür sind Modems. Solche Geräte können per Terminalemulator angesprochen werden – unter Linux sei hier auf kermit, minicom, picocom und gtkterm verwiesen, wobei libftdi diesen Modus auch beherrscht. Im Terminalmodus empfängt das Endgerät einzelne Zeichen vom Rechner über die TX-Leitung und schickt ggf. Daten über RX zurück. Dazu wird eine Baudrate gesetzt.

In den anderen Modi werden die Signale direkt, d.h. die Leitungen unter Strom gesetzt bzw. Signaleingänge abgefragt. Es gibt zwei Modi: einen „Standard”- oder „einfachen” Modus und den sog. „Bitbang”-Modus. Im einfachen Modus ist festgelegt, welche Leitungen zum Empfangen von Daten und welche zum Abschicken dieser fungieren. Im Bitbang-Modus können die Leitungen über ein Bitmaske beliebig für den Ein- und Ausgang definiert werden. Folgende Tabelle gibt eine Übersicht über die Leitungen:

Leitung

Name

Bitbang-Bit

Ein-/Ausgang

TX

Transmit Data

0

A

RX

Receive Data

1

E

RTS

Request to Send

2

A

CTS

Clear to Send

3

E

DTR

Data Terminal Ready

4

A

DSR

Dataset Ready

5

E

DCD

Data Carrier Detect

6

E

RI

Ring Indicator

7

E

Im Gegensatz zu der Bibliothek FTD2XX bietet libftdi weniger Möglichkeiten, um Pins direkt im einfachen Modus anzusprechen (nicht, dass das viele wären). Deshalb ist die Verwendung des Bitbang-Modus fast immer sinnvoll, außer man muss lediglich ein oder zwei Ausgänge ansprechen.

Versuchsaufbau

Zum Testen bauen wir einen kleinen Versuchsaufbau auf einer Steckplatine (Breadboad) auf: Zum Einsatz kommt das 5V-FTDI-Breakout und drei LEDs. Mit anderen Worten: Es wird eine einfache Ampel simuliert. Abb. 3 zeigt die verwendeten Komponenten: 3 LEDs, 3 Widerstände (wie oben), ein Kabel und eine kurze Steckleiste. Dazu kommt eine Steckplatine. Der Versuchsaufbau wird so gebaut, wie in Abb. 4 gezeigt. Das braune Kabel wird dabei mit dem 5V-Anschluss verbunden, die Widerstände und die LEDs werden jeweils paarweise hintereinandergeschaltet und mit DTR, RX und TX verbunden. Es ist darauf zu achten, dass die Anode (der längere Fuß) der LEDs in Richtung 5V gelegt wird.

Abbildung 3: Kompontenten des Versuchsaufbaus.

Abbildung 3: Kompontenten des Versuchsaufbaus.

Abbildung 4: Versuchsaufbau

Abbildung 4: Versuchsaufbau

Nun ist das Ganze bereit!

Programmieren mit libftdi: Beispiel in C

Die Bibliothek libftdi ist in C geschrieben und logischerweise am einfachsten von C aus anzusprechen. Im Folgenden findet sich ein Listing, das eine einfache deutsche Ampelschaltung simuliert. Das Beispiel ist von einem Listing auf Hack-A-Day und der libftdi-API inspiriert worden.

Das Listing besitzt einige Ampel-Funktionen und die obligatorische Hauptfunktion am Ende. In der Hauptfunktion wird zuerst der FTDI-Kontext definiert (Z. 49). Dabei handelt es sich um eine Datenstruktur, welche alle relevanten Daten für das Gerät enthält. Danach wird der Kontext initialisert (Z. 53–56) und das Gerät geöffnet (Z. 59–63). Im Anschluss wird noch die Id des Geräts ausgelesen, was allerdings nicht bei allen Geräten funktioniert (Z. 66–70).

Nun kommt der eigentlich spannende Teil: Die Ampelschaltung an sich. Dazu wird das Gerät in den Bitbang-Modus versetzt (Z. 73) und die drei Pins DTR, RX und TX als schreibende Ausgänge gesetzt. Die Ampel muss zunächst ausgeschaltet werden (Z. 76). Grund dafür ist, dass die Belegung in unserem Fall gewissermaßen invertiert ist: Da die LEDs am +5V-Pol angeschlossen sind, leuchten sie nach Aktivierung des Bitbang-Modus. Im Gegensatz zum Beispiel von Hack-A-Day habe ich die LEDs an diesen Pol angeschlossen, da zumindest beim Sparkfun-Gerät ein Anschluss an Ground den LEDs nur ein sehr schwaches Glimmen entlocken konnte. Nun ja…

Die Ampelschaltung wird dreimal durchlaufen (Z. 79–89): Am Anfang soll die Ampel fünf Sekunden lang grün zeigen, dann 2 Sekunden lang auf gelb stehen, bevor weitere 5 Sekunden lang der Verkehr gestoppt wird. Dann wird kurz gelb-rot gezeigt, bevor man wieder losfahren kann. Zum Umschalten werden die Funktionen aufgerufen (Z. 22–44). Da die Schaltung, wie gesagt, invertiert ist, werden die Zahlenwerte der Leitungen von 255 abgezogen. Dadurch wird das relevante Bit auf 0 gesetzt und die LED leuchtet. Schön ist dies bei der gelb-rot-Schaltung sichtbar, da hier ja zwei LEDs gleichzeitig leuchten.

Am Ende des Programms werden alle Leitungen ausgeschaltet und das Gerät de-initialisert (Z. 92–103). So einfach geht’s!

Kompiliert wird das Programm mit dem Aufruf cc -lftdi -o ampel ampel.c. Wichtig ist, dass libftdi-dev und ein C-Kompiler installiert sind (s.o.). Aufgerufen wird das Programm dann einfach mit ./ampel.

Programmieren mit libftdi: Beispiel in Python

Das zweite Listing zeigt die Ampelschaltung in Python. Die Bindings sind dabei automatisch mit Hilfe von swig für Python erstellt worden. Python ruft demnach tatsächlich die C-Funktionen der Bibliothek auf.

Unter Debian und Ubuntu kann man die Python-Verbindung zu libftdi mit sudo apt-get install python-ftdi installieren. Damit kann man in Python das Modul ftdi importieren und die Funktionen wie in C aufrufen. Probleme hatte ich allerdings mit ftdi_read_chipid. Hier verlangte der Python-Wrapper eine unsigned int, die ich jedoch nicht liefern konnte, selbst als ich das libc-Modul importiert hatte. Die Python-Bindings sind ansonsten sehr schlecht dokumentiert. Falls jemand einen Tipp hat, bin ich dafür sehr dankbar!

Das Python-Programm funktioniert genau wie das C-Programm und kann mit python ampel.py aufgerufen werden.

So, ich hoffe, das Tutorial hilft dem einen oder anderen. Zu Abschluss noch ein kleines Video zur Präsentation der Ampelschaltung. Viel Spaß!