10.4Hardware-Basteleien

Die eigentliche Besonderheit des Raspberry Pi ist weder seine winzige Größe noch sein Preis – die riesige Faszination für den Raspberry Pi geht vielmehr von 40 Pins (elektrischen Kontakten) aus, die zur Messung und Steuerung elektronischer Geräte verwendet werden können. Sowohl Elektronik-Bastler als auch Embedded-Linux-Profis bekommen mit dem Raspberry Pi ein Spielzeug bzw. Werkzeug in die Hand, das die Entwicklung computergesteuerter Geräte so einfach wie selten zuvor macht.

Dieser Abschnitt gibt hierzu eine Einführung und präsentiert einige Beispiele. Im Internet sowie in Raspberry-Pi-Büchern und -Zeitschriften finden Sie unzählige weitere Anleitungen für anspruchsvollere Projekte.

Zerstören Sie Ihren Raspberry Pi nicht durch Unachtsamkeit!

Auch wenn ich mich in diesem Abschnitt an Elektronikeinsteiger und nicht an Embedded-Linux-Profis wende, gehe ich im Weiteren davon aus, dass Sie elementare Grundregeln im Umgang mit elektronischen Komponenten kennen:

Das Layout der 40-Pin-Steckerleiste

Die Platine des Raspberry Pi enthält in einer Ecke eine Steckerleiste mit 2×20 Kontakten in einem Rasterabstand von 2,54 mm. Beim Raspberry Pi 2 hat diese Steckerleiste die offizielle Bezeichnung »J8-Header«. Bei älteren Modellen wurde die damals kleinere GPIO-Leiste mit 26 Pins »P1-Header« genannt.

Diese Steckerleiste stellt neben einigen allgemein verwendbaren Kontakten (General Purpose Input/Output = GPIO) auch zwei Versorgungsspannungen (3,3 V bzw. 5 V) sowie die Masse (also 0 V) zur Verfügung.

Abbildung 10.15 fasst die Belegung der 40 Pins des J8-Headers zusammen (Quelle: http://elinux.org/RPi_Low-level_peripherals, ohne Gewähr!). Viele Pins erfüllen je nach Programmierung alternative Funktionen. Beispielsweise können die Pins 3 und 5 nicht nur als GPIO-Kontakte verwendet werden, sondern auch zum Anschluss einer elektronischen Komponente mit I2C-Bus.

Schematischer Plan des Raspberry Pi mit Pin-Nummerierung

Abbildung 10.15Schematischer Plan des Raspberry Pi mit Pin-Nummerierung

Tabelle 10.1 erklärt die wichtigsten Abkürzungen, die zur Beschreibung von GPIO-Pins verwendet werden. Viele weitere Details können Sie auf der folgenden Seite nachlesen:

http://elinux.org/RPi_BCM2835_GPIOs

Diese Seite enthält eine umfassende Beschreibung aller GPIO-Pins des Broadcom BCM2835 System-on-a-Chip. Dieser Bauteil, der auch die CPU und die GPU enthält, war das Kernstück der Raspberry-Pi-Platine der ersten Generation. Der aktuelle Raspberry Pi 2 enthält den kompatiblen Nachfolge-Chip BCM2836. Leider gibt es zum BCM2836 momentan weit weniger umfassende Dokumentation als zum BCM2835.

Abkürzung

Bedeutung

GND

Ground (Masse, also 0 V)

GPIO

General Purpose Input Output

GPCLK

General Purpose Clock (einstellbarer Taktgeber)

I2S

Inter-IC Sound Interface (Übertragung von Audio-Daten)

I2C

Inter-Integrated Circuit (serieller Datenbus)

PWM

Pulse Width Modulation (für SPI)

SD1

Secondary memory Data bus

SPI

Serial Peripheral Interface (serieller Datenbus)

SPI-MOSI

Master out, Slave in (für SPI)

SPI-MISO

Master in, Slave out (für SPI)

SPI-SCLK

Serial Clock (für SPI)

UART

Universal Asynchronous Receiver Transmitter (serielle Schnittstelle)

Tabelle 10.1Abkürzungen

GPIO-Nummerierungswirrwarr

Leider gibt es verschiedene Möglichkeiten, die Pins der GPIO-Leiste zu bezeichnen.

Der Kontakt des J8-Headers mit der Pin-Nummer 11 entspricht »GPIO 17« in der BCM-Nomenklatur, aber »GPIO 0« in der Raspberry-Pi-Nomenklatur. In den weiteren Beispielen in diesem Buch beziehe ich mich immer auf die Pin-Nummer. Wenn Sie aber Anleitungen aus dem Internet folgen, müssen Sie immer hinterfragen, welche Nomenklatur zur Anwendung kommt und welcher Pin nun wirklich gemeint ist.

Pin 1 und 17 stellen eine Spannung von 3,3 V zur Verfügung und werden oft dazu verwendet, externe Schaltungen mit Strom zu versorgen. Die beiden Pins dürfen allerdings zusammen maximal mit 50 mA belastet werden.

Die Pins 2 und 4 mit einer Versorgungsspannung von 5 V werden über eine selbstrückstellende Sicherung (poly fuse) geleitet. Fließt hier zu viel Strom, schaltet sich der Raspberry Pi für eine Weile ab. Mit etwas Glück kommt es zu keinen bleibenden Schäden.

Wenn Sie GPIO-Kontakte zur Steuerung verwenden (Konfiguration als Output) und auf HIGH stellen, beträgt die Spannung am betreffenden GPIO-Pin 3,3 V. Der Steuerungsstrom pro Pin sollte 8 mA nicht überschreiten (bzw. 50 mA für alle GPIOs sowie Pin 1 und 17). Verwenden Sie also geeignete Vorwiderstände!

Soweit Sie GPIO-Kontakte als Eingänge verwenden, dürfen Sie eine Spannung von 3,3 V nicht überschreiten! 5 V sind definitiv zu viel und können Ihren Raspberry Pi zerstören.

Vor jedem Projekt müssen Sie sich die Frage stellen: »Welche der vielen GPIO-Pins setze ich ein?« Solange es nur darum geht, erste Experimente durchzuführen und ein paar Leuchtdioden ein- und auszuschalten, können Sie dazu jeden der 17 GPIO-n-Pins verwenden. Diverse Spezialfunktionen stehen allerdings auf ausgewählten Pins zur Verfügung. Ein kurzer Überblick, wobei sich die Pin-Nummern auf den J8-Header des Raspberry Pi beziehen:

Noch mehr Informationen finden Sie auf der folgenden Seite, die sich allerdings nicht auf die Pin-Nummern des J8-Headers bezieht, sondern BCM-Nummern verwendet:

http://elinux.org/RPi_BCM2835_GPIOs

Bevor Sie Ihr erstes Bastelprojekt beginnen, müssen Sie sich überlegen, wie Sie den elektronischen Kontakt zu einem der 26 Pins herstellen. Für kleine Versuchsaufbauten auf einem Steckboard sind kurze Kabel mit Stecker und Buchse ideal (siehe Abbildung 10.16). Die Kabel werden in diversen Raspberry-Pi-Shops angeboten, oft zusammen mit einem Steckboard als Starter-Kit. Suchen Sie gegebenenfalls im Internet nach breadboard jumper wire male female.

Steckboard-Kabel

Abbildung 10.16Steckboard-Kabel

Mit ein wenig Erfahrung im Löten und einer Buchsenleiste im 2,54-mm-Raster (erhältlich in jedem Elektronikmarkt) können Sie sich selbst passende Stecker herstellen. Eine andere Alternative ist ein 40-Pin-Stecker mit einem Flachbandkabel, dessen Drähte Sie dann trennen. Manche Raspberry-Pi-Händler bieten auch spezielle Cobbler an, um alle 40 Pins des J8-Headers über ein Flachbandkabel mit den Kontaktreihen eines Steckboards zu verbinden.

Löten Sie auf keinen Fall die Kabel direkt an die Stecker-Pins! Die unvermeidlichen Lötreste machen es nahezu unmöglich, später einen Flachbandstecker zu verwenden.

In Ergänzung zu den 40 Pins des J8-Headers enthält die Platine des Raspberry Pi einige weitere Kontaktstellen – die P2-, P3-, P5- und P6-Header. Diese Kontaktstellen sind nicht mit Steckern verbunden. Wenn Sie diese Kontakte nutzen möchten, müssen Sie Ihre elektronischen Bauteile, Kabel oder Stecker dort anlöten.

Die acht Kontakte des P5-Headers auf der Rückseite (!) der Platine stellen unter anderem die Kontakte GPIO28 bis -31 zur Verfügung. Diese können als zweite I2C- oder als I2S-Schnittstelle verwendet werden. Die beiden Kontakte des P6-Headers bieten die Möglichkeit eines Hardware-Resets. Eine Verbindung der beiden Kontakte startet die CPU des Raspberry Pi neu.

Im weiteren Verlauf dieses Kapitels beziehe ich mich ausschließlich auf die 40 Pins des J8-Headers! Eine vollständige Hardware-Beschreibung des Raspberry Pi finden Sie hier:

http://elinux.org/RPi_Hardware

LEDs ein- und ausschalten

Sozusagen als Hello World!-Projekt zeige ich Ihnen, wie Sie mit Ihrem Raspberry Pi eine Leuchtdiode (LED) ein- und ausschalten. Die erste Variante besteht darin, die LED direkt an die 3,3-V-Spannungsversorgung anzuschließen. Sie leuchtet dann immer.

Im Datenblatt Ihrer LED lesen Sie nach, wie groß der Spannungsabfall an der Diode ist und welchen Strom die Diode erwartet – z.B. 2 V und 10 mA. Die Größe des erforderlichen Vorwiderstands ergibt sich aus der Restspannung 3,3 V - 2 V = 1,3 V und der Formel R = U / I = 1,3 V / 10 mA mit 130 Ω. Wenn Sie den nächstgrößeren Widerstand verwenden, den Sie finden, kann nichts passieren. Die LED leuchtet dann entsprechend weniger hell.

Da derselbe Schaltungsaufbau später über einen GPIO-Pin mit einem maximalen Ausgangsstrom von 8 mA gesteuert werden soll, ist es besser, den Widerstand gleich entsprechend größer zu dimensionieren (1,3 V / 8 mA = 163 Ω). Ich habe für meine Experimente mit 330-Ω-Widerständen gearbeitet, womit sich ein Strom von 4 mA ergibt.

Auf einem Steckboard bauen Sie nun die Schaltung gemäß Abbildung 10.17 auf und verbinden die Schaltung mit den Pins 1 (3,3 V) und 25 (GND) des Raspberry Pi. Achten Sie auf die richtige Polung der LED. Der längere Draht der LED verbindet die Anode (Plus), der kürzere die Kathode (Minus).

Simple LED-Schaltung

Abbildung 10.17Simple LED-Schaltung

Nachdem Sie sich überzeugt haben, dass die obige Schaltung prinzipiell funktioniert, verwenden Sie nun anstelle von Pin 1 (3,3 V) einen GPIO-Kontakt, z.B. Pin 26 für GPIO 7.

Tipp

GPIO-Pins sind zur Steuerung, nicht zur Stromversorgung gedacht. Wenn Sie ein elektronisches Bauteil mit mehr als 8 mA bei 3,3 V versorgen möchten, verwenden Sie zur Stromversorgung Pin 2 oder 4 (5 V) und steuern den Stromfluss durch einen GPIO-Ausgang über einen Transistor. Einen entspechenden Schaltungsaufbau finden Sie hier:

http://www.raspberrypi-spy.co.uk/2012/06/control-led-using-gpio-output-pin

Beim Einschalten des Raspberry Pi wird die LED nun nicht mehr leuchten. Vielmehr können Sie die LED jetzt durch ein Python-Programm steuern. Den erforderlichen Quellcode geben Sie mit einem Editor ein:

#!/usr/bin/python3 import RPi.GPIO as GPIO import time # Pin-Nummern verwenden (nicht GPIO-Nummern!) GPIO.setmode(GPIO.BOARD) # Pin 26 (= GPIO 7) zur Datenausgabe verwenden GPIO.setup(26, GPIO.OUT) # Pin 26 einschalten GPIO.output(26, GPIO.HIGH) # Pin 26 nach fünf Sekunden wieder ausschalten time.sleep(5) GPIO.output(26, GPIO.LOW) # alle vom Script benutzten GPIOs/Pins wieder freigeben GPIO.cleanup()

Der Programmcode sollte auch ohne Python-Erfahrung auf Anhieb verständlich sein. chmod macht die Script-Datei ausführbar. Bei älteren Raspbian-Versionen darf nur root GPIO-Funktionen steuern. Daher muss das Script mit sudo ausgeführt werden. Aktuelle Raspbian-Versionen sind hier liberaler konfiguriert; das Script funktioniert bei Ihnen auch ohne sudo:

pi$ chmod a+x led1.py pi$ ./led1.py (Raspbian Wheezy) pi$ sudo ./led1.py (Raspbian Jessie)

Natürlich ist Python nicht die einzige Programmiersprache, die Sie zur GPIO-Steuerung einsetzen können. Python ist aber das populärste Werkzeug für diesen Zweck und steht bei den meisten Raspberry-Pi-Distributionen inklusive der GPIO-Bibliothek standardmäßig zur Verfügung. Eine kurze Einführung in die GPIO-Bibliothek für Python sowie einen Überblick, wie Sie GPIO-Pins mit anderen Programmiersprachen steuern, finden Sie hier:

http://sourceforge.net/projects/raspberry-gpio-python
http://elinux.org/RPi_Low-level_peripherals#GPIO_Code_examples

Nicht immer ist es praktisch, für jede Veränderung eines GPIO-Pins gleich ein Python-Script zu verfassen. Die Bibliothek WiringPi stellt das Kommando gpio zur Verfügung, mit dem Sie einzelne GPIO-Pins direkt im Terminal manipulieren können. Bei aktuellen Raspbian-Versionen steht das Kommando standardmäßig zur Verfügung (Paket wiringpi). Bei älteren Versionen ist die Installation von WiringPi aus einem Git-Repository ist in wenigen Minuten erledigt:

pi$ sudo apt-get install git pi$ git clone git://git.drogon.net/wiringPi pi$ cd wiringPi pi$ ./build

Mit dem Kommando gpio können Sie nun ebenfalls die LED ein- und ausschalten. Das Kommando erfordert keine root-Rechte. Die Option -1 (eins, nicht L) bewirkt dabei, dass gpio physische Pin-Nummern des J8-Headers als Parameter erwartet.

pi$ gpio -1 mode 26 out pi$ gpio -1 write 26 1 (LED ein) pi$ gpio -1 write 26 0 (LED aus)

gpio readall verrät den aktuellen Status aller GPIO-Pins. Dabei gibt die erste/letzte Spalte die BCM-Bezeichnung des Pins an, die zweite/vorletzte Spalte die Wiring-Pi-Bezeichnung, die dritte/drittletzte den Raspberry-Pi-Namen.

pi$ gpio readall  +----+----+--------+-----+---+---Pi 2---+---+-----+--------+----+----+ |BCM |wPi | Name |Mode | V | Physical | V | Mode| Name | wPi| BCM|  +----+----+--------+-----+---+----++----+---+-----+--------+----+----+ | | | 3.3v | | | 1 || 2 | | | 5v | | | | 2 | 8 | SDA.1 | IN | 1 | 3 || 4 | | | 5V | | | | 3 | 9 | SCL.1 | IN | 1 | 5 || 6 | | | 0v | | | | 4 | 7 |GPIO. 7 | IN | 1 | 7 || 8 | 1 | ALT0| TxD | 15 | 14 | | | | 0v | | | 9 || 10 | 1 | ALT0| RxD | 16 | 15 | | 17 | 0 |GPIO. 0 | IN | 0 | 11 || 12 | 0 | IN | GPIO. 1| 1 | 18 | | 27 | 2 |GPIO. 2 | IN | 0 | 13 || 14 | | | 0v | | | | 22 | 3 |GPIO. 3 | IN | 0 | 15 || 16 | 0 | IN | GPIO. 4| 4 | 23 | | | | 3.3v | | | 17 || 18 | 0 | IN | GPIO. 5| 5 | 24 | | 10 | 12 | MOSI | IN | 0 | 19 || 20 | | | 0v | | | | 9 | 13 | MISO | IN | 1 | 21 || 22 | 0 | OUT | GPIO. 6| 6 | 25 | | 11 | 14 | SCLK | IN | 0 | 23 || 24 | 0 | OUT | CE0 | 10 | 8 | | | | 0v | | | 25 || 26 | 1 | OUT | CE1 | 11 | 7 | | 0 | 30 | SDA.0 | IN | 1 | 27 || 28 | 1 | IN | SCL.0 | 31 | 1 | | 5 | 21 |GPIO.21 | OUT | 1 | 29 || 30 | | | 0v | | | | 6 | 22 |GPIO.22 | IN | 1 | 31 || 32 | 0 | IN | GPIO.26| 26 | 12 | | 13 | 23 |GPIO.23 | IN | 0 | 33 || 34 | | | 0v | | | | 19 | 24 |GPIO.24 | IN | 0 | 35 || 36 | 0 | IN | GPIO.27| 27 | 16 | | 26 | 25 |GPIO.25 | IN | 0 | 37 || 38 | 0 | IN | GPIO.28| 28 | 20 | | | | 0v | | | 39 || 40 | 0 | IN | GPIO.29| 29 | 21 |  +----+----+--------+-----+---+---Pi 2---+---+-----+--------+----+----+ |BCM |wPi | Name |Mode | V | Physical | V | Mode| Name | wPi| BCM|  +----+----+--------+-----+---+---Pi 2---+---+-----+--------+----+----+

Um das Beispiel ein wenig interessanter zu machen, zeigt Abbildung 10.18 eine Schaltung mit nunmehr drei Dioden (grün, gelb und rot), die durch die GPIOs 7, 8 und 25 gesteuert werden (Pin 26, 24 und 22). Das Ziel besteht darin, die LEDs in Abhängigkeit von der CPU-Temperatur ein- und auszuschalten: Die grüne LED soll leuchten, wenn die CPU-Temperatur zwischen 30 und 45 Grad beträgt, die gelbe LED bei Temperaturen zwischen 45 und 60 Grad und die rote LED bei Temperaturen darüber.

Nachdem Sie die Schaltung aufgebaut haben, testen Sie, ob alle drei LEDs funktionieren:

pi$ sudo -s pi$ gpio -1 mode 26 out pi$ gpio -1 write 26 1 (grüne LED ein) pi$ gpio -1 write 26 0 (grüne LED aus) pi$ gpio -1 mode 24 out pi$ gpio -1 write 24 1 (gelbe LED ein) pi$ gpio -1 write 24 0 (gelbe LED aus) pi$ gpio -1 mode 22 out pi$ gpio -1 write 22 1 (rote LED ein) pi$ gpio -1 write 22 0 (rote LED aus)
LED-Anzeige der CPU-Temperatur

Abbildung 10.18LED-Anzeige der CPU-Temperatur

Ein Shell-Script zum Ein- und Ausschalten der drei LEDs in Abhängigkeit von der CPU-Temperatur ist rasch geschrieben. Wenn Ihnen Python lieber ist, können Sie den Code natürlich ebenso gut damit formulieren.

#!/bin/bash # Datei /home/pi/led-rot-gelb-gruen greenpin=26 yellowpin=24 redpin=22 gpio -1 mode $greenpin out gpio -1 mode $yellowpin out gpio -1 mode $redpin out # CPU-Temperatur temp=$(cat /sys/class/thermal/thermal_zone0/temp) echo $temp # grüne LED ansteuern if [[ "$temp" -ge 30000 && "$temp" -le 45000 ]]; then gpio -1 write $greenpin 1 else gpio -1 write $greenpin 0 fi # gelbe LED ansteuern if [[ "$temp" -ge 45000 && "$temp" -le 60000 ]]; then gpio -1 write $yellowpin 1 else gpio -1 write $yellowpin 0 fi # rote LED ansteuern if [[ "$temp" -ge 60000 ]]; then gpio -1 write $redpin 1 else gpio -1 write $redpin 0 fi

Diese Datei muss ausführbar sein:

root# chmod a+x /home/pi/led-rot-gelb-gruen

Jetzt geht es nur noch darum, dieses Script einmal pro Minute aufzurufen. Dazu legen Sie im Verzeichnis /etc/cron.d die folgende Datei an (siehe auch Abschnitt 14.6, »Prozesse automatisch starten (Cron)«):

# Datei /etc/cron.d/cpu-temp PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin */1 * * * * root /home/pi/led-rot-gelb-gruen

Von nun an werden die drei LEDs minütlich je nach CPU-Temperatur ein- und ausgeschaltet. Vergessen Sie nicht, /etc/cron.d/cpu-led zu löschen, wenn Sie die Pins 22, 24 und 26 später für eine andere Schaltung verwenden möchten!

Eine LED mit einem Taster ein- und ausschalten

Die einfachste Form, an den Raspberry Pi Eingaben weiterzuleiten, ist ein simpler Taster, der den Stromkreis schließt, solange er gedrückt ist. Während umgangssprachlich oft alles, worauf man drücken kann, ein »Schalter« ist, unterscheidet die Elektrotechnik zwischen Schaltern, die den Zustand beibehalten (wie ein Lichtschalter), und Tastern, die zurückspringen, wenn man sie loslässt (wie bei Ihrer Tastatur). Für dieses Beispiel benötigen Sie also einen Taster. Wenn Sie zum Testaufbau ein Steckboard verwenden, fragen Sie in Ihrem Elektronikgeschäft nach einem print-taster.

Das Ziel dieses Abschnitts ist eine Schaltung, bei der Sie durch einen kurzen Druck auf eine Taste eine LED einschalten. Drücken Sie nochmals, soll die LED wieder ausgehen. Die Aufgabenstellung klingt erdenklich trivial, aber Sie werden sehen, dass dieser Eindruck täuscht.

Bevor Sie den Taster aber mit einem GPIO-Pin verbinden, müssen Sie sich Gedanken darüber machen, wie der Raspberry Pi Eingaben verarbeitet. Es ist möglich, einen GPIO-Pin als Input zu konfigurieren. Die Ausgangsspannung dieses Pins ist damit undefiniert. Wenn von außen eine Spannung nahe 0 V angelegt wird, wird das als low = 0 interpretiert. Ist die angelegte Spannung hingegen nahe 3,3 V, wird das Signal als high = 1 interpretiert. Als Input verwendete GPIOs können nicht zwischen anderen Zuständen unterscheiden und können somit nicht zur Messung der angelegten Spannung verwendet werden.

Ein Input-Pin soll nie unbeschaltet sein, weil seine Spannung dann undefiniert ist (floating). Gleichzeitig ist es nicht empfehlenswert, den Pin direkt mit der Masse oder mit der Versorgungsspannung (3,3 V) zu verbinden: Sollte der GPIO-Pin irrtümlich als Output-Pin programmiert sein, würden unter Umständen große Ströme fließen, die Ihren Raspberry Pi mit etwas Pech zerstören. Die Lösung für dieses Problem sind Pull-up- oder Pull-down-Widerstände in der Größenordnung von circa 1 kΩ bis 10 kΩ, um den Signaleingang für beide möglichen Zustände des Tasters mit der Masse bzw. mit 3,3 V zu verbinden. Hintergrundinformationen zu Pull-up- und Pull-down-Widerständen können Sie in der Wikipedia nachlesen:

http://de.wikipedia.org/wiki/Open_circuit#Beschaltung_der_Signalleitungen

Bei der Beschaltung des Raspberry Pi können Sie sich Pull-up- und Pull-down-Widerstände unter Umständen sparen: Zum einen sind die Pins 3 und 5 des J8-Headers standardmäßig mit 1,8 kΩ externen Pull-up-Widerständen verbunden; zum anderen lassen sich alle GPIOs im Input-Modus so programmieren, dass CPU-interne Pull-up- oder Pull-down-Widerstände aktiviert werden. Der interne Schaltungsaufbau ist auf der folgenden Seite gut beschrieben:

http://www.mosaic-industries.com/embedded-systems/microcontroller-projects/raspberry-pi/gpio-pin-electrical-specifications

Dennoch ist es empfehlenswert, Signaleingänge grundsätzlich mit einem externen Pull-up- oder Pull-down-Widerstand zu versehen. Sie vermeiden damit Probleme, wenn ein GPIO-Pin versehentlich falsch konfiguriert ist oder während der Initialisierung des Raspberry Pi einen anderen Zustand einnimmt, als Ihre Schaltung voraussetzt. Gefahrlos auf Pull-up-Widerstände können Sie nur verzichten, wenn Sie Ihren Taster mit den Pins 3 oder 5 verbinden. Diese beiden Pins stehen aber nur zur freien Verfügung, wenn Ihre Schaltung keine I2S-Komponenten enthält.

Abbildung 10.19 zeigt den Aufbau der Schaltung. Soweit es die Leuchtdiode betrifft, gibt es keine Veränderung im Vergleich zum vorigen Abschnitt – wenn man einmal davon absieht, dass diesmal Pin 23 zur Ansteuerung verwendet wird.

LED-Steuerung per Taster mit
  Pull-up-Widerstand

Abbildung 10.19LED-Steuerung per Taster mit Pull-up-Widerstand

Der Taster ist direkt mit der Masse und über den Pull-up-Widerstand R2 mit der Versorgungsspannung 3,3 V verbunden. Im Normalzustand lautet der Signalzustand an Pin 21 also High, beim Drücken Low. Der Widerstand R3 ist eine zusätzliche Sicherheitsmaßnahme. Er verhindert einen Kurzschluss für den zugegebenermaßen unwahrscheinlichen Fall, dass Pin 21 irrtümlich als Output programmiert wird, auf High gestellt und gleichzeitig der Taster gedrückt ist. Ohne R3 gäbe es dann eine direkte Verbindung zwischen 3,3 V an Pin 21 und der Masse; es würde mehr Strom fließen, als der Raspberry Pi liefern kann. Dank R3 ist der Strom selbst in diesem Fall auf  3,3 mA begrenzt.

Bevor Sie sich an die Programmierung machen, sollten Sie kurz überprüfen, ob der Schaltungsaufbau funktioniert. Zuerst schalten Sie versuchsweise die LED ein/aus:

pi$ gpio -1 mode 23 out pi$ gpio -1 write 23 1 (LED ein) pi$ gpio -1 write 23 0 (LED aus)

Dann testen Sie den Signaleingang an Pin 21, wobei Sie einmal die Taste gedrückt halten:

pi$ gpio -1 mode 21 in pi$ gpio -1 read 21 (Normalzustand) 1 pi$ gpio -1 read 21 (Taste gedrückt) 0

Wenn Sie ein direktes Feedback wünschen, können Sie Pin 21 mit einem kleinen Python-Script kontinuierlich abfragen:

#!/usr/bin/python3 import RPi.GPIO as GPIO import time # Pin-Nummern verwenden (nicht GPIO-Nummern!) GPIO.setmode(GPIO.BOARD) # GPIO 21 = Input GPIO.setup(21, GPIO.IN) while True: input = GPIO.input(21) print("Zustand: " + str(input)) time.sleep(0.01)

Sobald Sie dieses Programm starten, gibt es den aktuellen Signaleingang von Pin 21 regelmäßig im Terminal aus – bis Sie das Programm mit (Strg)+(C) wieder stoppen.

Die Überwachung von Signalzuständen durch eine Schleife ist selten ein optimales Konzept. Wenn die sleep-Zeit kurz ist, verursacht das Programm eine Menge unnötige CPU-Last; verwenden Sie eine längere Zeit, steigt die Reaktionszeit des Programms, und im ungünstigsten Fall übersieht es einen kurzen Impuls ganz. Wesentlich intelligenter ist es, das Python-Programm so zu formulieren, dass es einfach auf einen Signalwechsel wartet und erst dann durch ein Event aktiv wird.

Das folgende Python-Programm demonstriert diese Vorgehensweise: Mit def wird eine Callback-Funktion definiert, die immer dann aufgerufen werden soll, wenn die Taste gedrückt wird. Genau darum kümmert sich add_event_detect: Damit wird Pin 23 überwacht, und immer, wenn dessen Signalpegel von High auf Low fällt, wird die Funktion switch_on aufgerufen.

Das Programm soll laufen, bis es durch (Strg)+(C) beendet wird. Das ist der Zweck der Endlosschleife am Ende des Programms.

#!/usr/bin/python3 import RPi.GPIO as GPIO import time, sys # Pin-Nummern verwenden (nicht GPIO-Nummern!) GPIO.setmode(GPIO.BOARD) ledStatus = 0 # GPIO 21 = Input, 23 = Ouptput GPIO.setup(21, GPIO.IN) GPIO.setup(23, GPIO.OUT) GPIO.output(23, ledStatus) # Funktion definieren, um bei Tastendruck den LED-Zustand zu ändern def switch_on( pin ): global ledStatus ledStatus = not ledStatus GPIO.output(23, ledStatus) return # switch_on-Funktion aufrufen, wenn Signal von HIGH auf LOW wechselt GPIO.add_event_detect(21, GPIO.FALLING, callback=switch_on) # mit minimaler CPU-Belastung auf das Programmende durch Strg+C warten try: while True: time.sleep(5) except KeyboardInterrupt: GPIO.cleanup() sys.exit()

Wenn Sie Schaltung und Programm nun ausprobieren, werden Sie feststellen, dass das Ein- und Ausschalten recht unzuverlässig funktioniert. Schuld daran ist ein Verhalten aller mechanischen Taster und Schalter: Diese prellen, d.h., ein Metallblättchen schlägt mehrfach gegen einen Kontaktpunkt und löst deswegen ganz rasch hintereinander mehrere Pegelwechsel am Input-Pin aus.

Für das Problem gibt es zwei einfache Lösungen: Entweder bauen Sie in Ihre Schaltung einen Kondensator ein, der während seiner Ladezeit das Prellen verhindert, oder Sie entscheiden sich für eine Software-Lösung und warten nach jedem Input-Event 200 ms, bevor Sie wieder Eingaben entgegennehmen. Die Software-Lösung ist in der GPIO-Bibliothek für Python bereits vorgesehen. Sie geben einfach als zusätzlichen Parameter bei add_event_detect die gewünschte Entprellzeit in Millisekunden an:

GPIO.add_event_detect(21, GPIO.FALLING, callback=switch_on, bouncetime=200)

Bei meinen Tests hat das leider nicht funktioniert. Eine entsprechende Funktion lässt sich aber mit wenig Aufwand selbst programmieren: Bei jedem Tastendruck merken Sie sich in switch_on die gerade aktuelle Zeit (Variable lastTime). Die nächste Veränderung des LED-Zustands führen Sie erst durch, wenn zumindest 200 ms vergangen sind.

# Änderungen im Programmcode import datetime, time, sys lastTime=datetime.datetime.now() ... # bei Tastendruck LED-Zustand ändern def switch_on( pin ): global ledStatus, lastTime now = datetime.datetime.now() if(now-lastTime > datetime.timedelta(microseconds=200000)): ledStatus = not ledStatus GPIO.output(23, ledStatus) lastTime = now return

Temperatur messen

Das Ziel dieses Abschnitts ist die Messung der Umgebungstemperatur mit einem Temperatursensor. Der Raspberry Pi verfügt über keine Analog-Eingänge, an denen die Spannung mit einem Analog/Digital-Wandler gemessen werden kann. Alle GPIO-Inputs sind digitale Eingänge, die nur zwischen 0 und 1 unterscheiden können. Deswegen empfiehlt es sich, zur einfachen Temperaturmessung ein Bauelement mit einem integrierten A/D-Wandler zu verwenden.

Bewährt hat sich für diese Aufgabe das Bauelement DS1820, das oft auch als 1-Wire-Thermometer angepriesen wird. Dieser Name ergibt sich daraus, dass diese Komponente nur über drei Anschlüsse verfügt: Zwei dienen zur Stromversorgung und der dritte dient zur Signalübertragung in Form eines binären Datenstroms.

Der DS1820 kann sogar ohne explizite Versorgungsspannung betrieben werden und bezieht den Strom dann über die Signalleitung. Auf diese Schaltungsvariante gehe ich hier aber nicht ein.

Der DS1820 misst Temperaturen in einem Messbereich zwischen -55 °C und +125 °C. Die Temperatur wird als 9- oder 12-Bit-Zahl übertragen. Da jeder DS1820 mit einer eindeutigen Seriennummer ausgestattet ist, können mehrere Elemente parallel geschaltet und getrennt ausgewertet werden (über einen einzigen GPIO-Pin!). Beim Auslesen der Thermometer hilft ein eigenes Linux-Kernelmodul.

Es existieren verschiedene Varianten zum originalen DS1820: Am leichtesten erhältlich ist zumeist das Bauteil DS18S20, das fast vollständig kompatibel zum Original ist und als Grundlage für diesen Abschnitt diente. Ebenfalls populär ist die Variante DS18B20, bei dem die gewünschte Messgenauigkeit über ein Register programmiert werden kann. Eine kleinere Genauigkeit ermöglicht schnellere Messungen und reduziert den Stromverbrauch. Einige DS1820-Varianten werden zudem in einer wasserdichten Ausführung angeboten, die aber dieselben elektrischen Eigenschaften aufweist. Ein ausführliches Datenblatt sowie eine Beschreibung der Unterschiede zwischen den verschiedenen Varianten finden Sie hier:

http://datasheets.maximintegrated.com/en/ds/DS18S20.pdf
http://www.maximintegrated.com/app-notes/index.mvp/id/4377

Abbildung 10.20 zeigt den Schaltungsaufbau. Ähnlich wie bei mechanischen Schaltern muss auch beim DS1820 ein Pull-up-Widerstand verwendet werden. Beachten Sie, dass Sie – im Gegensatz zu den bisherigen Schaltungen – den Signaleingang nicht frei wählen können. Pin 7 = GPIO 4 habe ich hier deswegen verwendet, weil der 1-Wire-Kerneltreiber diesen Signaleingang standardmäßig benutzt! Andere GPIOs sind möglich, müssen dann aber in config.txt explizit angegeben werden.

Schaltungsaufbau zur Messung der Umgebungstemperatur

Abbildung 10.20Schaltungsaufbau zur Messung der Umgebungstemperatur

Welcher Pin des DS1820 ist Pin 1?

Die Belegung der Pins des DS1820 geht aus dem Datenblatt hervor. Dabei müssen Sie beachten, dass das Bauelement in der Sicht von unten (bottom view) dargestellt ist.

Raspbian verwendet sogenannte Device Trees zur Beschreibung der Hardware des Raspberry Pi. Der Device Tree wird beim Starten des Minicomputers geladen. In Abhängigkeit vom Device Tree entscheidet der Linux-Kernel dann, welche Treiber (Module) er braucht. Für die Standardkomponenten des Raspberry Pi funktioniert dies aufgrund von Konfigurationsdateien im Verzeichnis /boot automatisch. Wenn Sie aber wie für dieses Beispiel zusätzliche Hardware nutzen möchten, dann müssen Sie den Device Tree entsprechend modifizieren.

Zu diesem Zweck sind die Parameter dtparam=xxx bzw. dtoverlay=xxx vorgesehen, die Sie in die Datei /boot/config.txt einfügen können. Eine Zusammenfassung der gängigsten Einstellungen gibt die Datei /boot/overlays/README.

In unserem Fall wollen wir den vorgegebenen Device Tree um den 1-Wire-Treiber ergänzen. Die erforderliche Zeile in config.txt sieht so aus:

# Ergänzung in /boot/config.txt ... dtoverlay=w1-gpio-pullup

Nach einem Neustart des Raspberry Pi können Sie sich mit lsmod überzeugen, dass die 1-Wire-Kernelmodule geladen sind.

pi$ lsmod | grep w1 w1_gpio 3465 0 wire 25632 1 w1_gpio

Bevor Sie die Temperatur auslesen können, müssen Sie Pin 7 als Signaleingang konfigurieren:

root# gpio -1 mode 7 in

Der Datei /sys/devices/w1_bus_master1/w1_master_slaves können Sie nun die IDs aller angeschlossenen DS1820-Sensoren entnehmen. In diesem Beispiel gibt es nur einen Sensor, dessen ID-Code mit 10 beginnt:

pi$ cat /sys/devices/w1_bus_master1/w1_master_slaves ... 10-000802ae1551

Die Messdaten jedes Sensors liegen in einer Textdatei vor. Interessant ist die zweite Zeile: t=nnn gibt die Temperatur in Tausendstel Grad an, auch wenn die Messgenauigkeit geringer ist. Zum Messzeitpunkt betrug die Umgebungstemperatur also ca. 20,6 °C.

pi$ cat /sys/devices/w1_bus_master1/10-000802ae1551/w1_slave 29 00 4b 46 ff ff 02 10 0c : crc=0c YES 29 00 4b 46 ff ff 02 10 0c t=20625

IR-Empfänger

Wenn Sie Ihren Raspberry Pi als Media-Center verwenden und dieses mit einer IR-Fernbedienung steuern möchten, benötigen Sie einen IR-Empfänger. Das gängigste Bauteil hierfür hat die Bezeichnung TSOP4838. Es ist Mitglied einer ganzen Familie von IR-Empfängern, die für unterschiedliche Frequenzen optimiert sind. Das Bauteil TSOP4838 ist auf 38 kHz abgestimmt, also auf den Frequenzbereich typischer TV-Fernbedienungen. Technische Details können Sie im Datenblatt nachlesen. Beachten Sie, dass die Belegung der Pins je nach TSOP-Variante unterschiedlich ist!

http://www.vishay.com/docs/82459/tsop48.pdf

Die Schaltung in Abbildung 10.21 entspricht dem Vorschlag aus dem Datenblatt. Sowohl der Widerstand als auch der Kondensator sind optional; sie verbessern lediglich die elektrische Stabilität der Schaltung. Sie können also auch direkt die Pins 1, 2 und 3 des TSOP4838 mit den Pins 25 (GND), 12 und 1 (3,3 V) des J8-Headers des Raspberry Pi verbinden. Warum dient gerade Pin 12 als Signaleingang? Weil der mit ihm verbundene Eingang GPIO 18 standardmäßig vom lirc-Kerneltreiber verwendet wird.

Ein einfacher IR-Empfänger

Abbildung 10.21Ein einfacher IR-Empfänger

Damit der Kernel des Raspberry Pi weiß, dass er den IR-Treiber laden muss, ist wieder eine Veränderung in /boot/config.txt erforderlich:

# Ergänzung in /boot/config.txt ... dtoverlay=lirc-rpi

Nach einem Reboot vergewissern Sie sich mit lsmod, dass die IR-Treiber tatsächlich geladen wurden:

pi$ lsmod | grep lirc lirc_rpi 6638 0 lirc_dev 8169 1 lirc_rpi rc_core 16948 1 lirc_dev

Jetzt können Sie im Textmodus mit dem Kommando mode2 Signale der Device-Datei der IR-Schnittstelle auslesen. Danach brauchen Sie nur noch eine Fernbedienung auf den IR-Empfänger richten und einige Tasten drücken.

pi$ sudo apt-get install lirc pi$ mode2 -d /dev/lirc0 space 1613 pulse 584 space 537 pulse 593 space 524 pulse 603 space 530 ... <Strg>+<C>

Hinweis

Sollte auf Ihrem Raspberry Pi der Dämon lircd laufen, müssen Sie ihn vor dem Test der Fernbedienung durch mode2 beenden: kill $(pidof lircd)

mode2 ist nur dazu gedacht, die Fernbedienung auszuprobieren. In aller Regel werden Sie den IR-Empfänger in Kombination mit Kodi und dem Hintergrundprogramm lircd verwenden. Tipps zur richtigen Konfiguration Ihrer Fernbedienung finden Sie in Abschnitt 10.3, »Kodi und OpenELEC«.