Raspberry Pi - EAH-Jena

Werbung
NERKA
Noch eine Raspberry Kurzanleitung
Alfred H. Gitter , Version vom 16. 3. 2016
Vorbemerkungen
Die vorliegende Schrift wurde und wird für gleich gesinnte Dilettanten erstellt. Sie ist unvollendet
und wird in unregelmäßigen Abständen erweitert oder geändert. Viele der behandelten Themen
liegen außerhalb der professionellen Fachkunde des Autors und die Bezeichnung als "Anleitung"
soll lediglich den einführenden und anwendungsnahen Inhalt charakterisieren und keinen Anspruch
auf überlegenes Wissen nahelegen. Ich hoffe, Leser zum Experimentieren mit dem Raspberry Pi
anzuregen und dafür einige Hinweise von Wert beizusteuern.
Der Rasperry Pi wird im Folgenden mit Π abgekürzt (Π ist der griechische Großbuchstabe Pi). Die
Schrift bezieht sich auf das Modell B, Revision 2, im folgenden mit Π_1B abgekürzt und das
neuere Modell, den Raspberry Pi 2 Model B, im folgenden mit Π_2B abgekürzt. In der Regel
beschränkt sich die Darstellung auf Eigenschaften des Π, die bei beiden Modellen gleich sind und
die erweiterten Möglichkeiten des Π_2B werden nicht benutzt.
Es wird vorausgesetzt, dass als Betriebssystem Raspbian Jessie (Full desktop image based on
Debian Jessie, vom 9. Februar 2016) installiert wird oder wurde. Sie unterscheidet sich leicht von
der Vorgängerversion (Wheezy) und stark von früheren Raspbian-Versionen. Als Programmiersprache dient Python 3 . Der Leser sollte über elementare Vorkenntnisse davon verfügen.
Alle Angaben erfolgen ohne Gewähr für Neuheit, Richtig- oder Vollständigkeit. Die Anleitung
enthält eigene Abbildungen, die ohne künstlerischen Anspruch das Verständnis erleichtern sollen.
Die Umsetzung der hier beschriebenen Experimente erfolgt ausdrücklich auf eigenes Risiko.
Rechts- und Schadenersatzansprüche sind daher ausgeschlossen. Für die Inhalte fremder Internetseiten, auf die verwiesen wird, sind ausschließlich die Betreiber dieser Seiten verantwortlich.
© by Prof. Dr. Alfred H. Gitter, Jena (2015 - 2016)
1
Inhalt
Vorbemerkungen..............................................................................................................................1
Hardware.......................................................................................................................3
Gehäuse, Energieversorgung, Bild, Ton, Tastatur und Maus...........................................................4
Speicherkarte, LAN und WLAN, Kontroll-LEDs, Drucker............................................................5
Digitale Anschlusspunkte: GPIOs...................................................................................................8
Software.......................................................................................................................11
Boot, Betriebssystem und Konfiguration.......................................................................................11
Kommandozeile (Konsole) und Paketverwaltung.........................................................................17
Editor, Browser und weitere Programme.......................................................................................21
Steuerung der GPIOs über das Betriebssystem.............................................................................24
Gnuplot und Mathematica (mit Aufgaben 1 und 2).......................................................................26
Programmieren mit Python..........................................................................................32
Erstes Programm: "Hallo!", Beispielprogramm (Zeit, Rundung, formatierte Ausgabe)...............32
GUI mit Python, Modul tkinter......................................................................................................35
Modul RPi.GPIO zur Steuerung der GPIOs..................................................................................38
Experiment 1: LED ein- und ausschalten....................................................................42
Schaltung 1 (LED) und Steuerung der GPIOs von der Konsole...................................................42
Blinken und Dimmen mit Python-Programmen............................................................................44
Schaltung 2 (LED und Transistor).................................................................................................48
Aufgabe 3.......................................................................................................................................49
Experiment 2: Schalter auslesen..................................................................................51
Schaltung 3 (Schalter)....................................................................................................................51
Daten eingeben mit Python-Programm..........................................................................................52
Desktop Shortcut für unser Programm..........................................................................................53
Aufgabe 4.......................................................................................................................................54
Experiment 3: Temperatursensor am Eindraht-Bus.....................................................55
Schaltung 4 (Temperatursensor DS18S20)....................................................................................55
Temperaturmessung von der Konsole mit DS18S20.....................................................................56
Python-Programm zur Temperaturmessung mit DS18S20 (mit Aufgabe 5).................................57
Experiment 4: Temperatursensor am I2C Bus.............................................................61
Schaltung 5 (Temperatursensor LM75).........................................................................................61
Temperaturmessung von der Konsole mit LM75..........................................................................61
Python-Programm zur Temperaturmessung mit LM75.................................................................63
Aufgabe 6.......................................................................................................................................65
Experiment 5: A/D-Wandler am SPI Bus....................................................................66
Schaltung 6 (A/D-Wandler MCP3208) und das Treibermodul für den SPI Bus...........................66
Python-Programm zur Spannungsmessung mit MCP3208...........................................................68
Aufgabe 7.......................................................................................................................................73
Experiment 6: Textausgabe auf LCD-Anzeigemodul..................................................74
Schaltung 7 (LCD-Modul C0802-04)............................................................................................74
Controller vom Typ HD47780.......................................................................................................77
Beschreiben der Anzeige...............................................................................................................80
Aufgabe 8.......................................................................................................................................82
Anhang.........................................................................................................................83
Internetradio- und Internetfernsehsender und ihre URLs..............................................................83
Raspbian ─ Wichtige Befehle für die Kommandozeile.................................................................88
Bash ─ Shell-Variablen..................................................................................................................89
2
Hardware
Der Raspberry Pi ( Π ) ist ein
Einplatinencomputer ( Single Board
Computer = SBC ). Es gibt ihn in
verschiedenen Ausführungen.
Wir benutzen hier das Modell B,
Revision 2, kurz Π_1B (Bild rechts
oben), oder eine neuere Ausführung,
Version 2, Modell B, kurz Π_2B
(Bild rechts unten), die im Februar
2015 herauskam.) Wichtigstes
Bauelement ist das System-on-a-Chip
(SoC) der Firma Broadcom ,
BCM2835 beim Π_1B und
BCM2836 beim Π_2B . Das SoC
enthält zwei Mikroprozessoren:
eine ARM CPU ( ARM1176JZF-S
beim Π_1B und ARM Cortex-A7
beim Π_2B ) und eine GPU
( Grafikprozessor , VideoCore IV bei
bei Π_1B und Π_2B ). Außerdem
enthält das SoC den Arbeitsspeicher
als SDRAM( 512 MB beim Π_1B
und 1024 MB beim Π_2B ).
SD-Slot
auf der
Rückseite
Raspberry Pi
(c)2011,12
Audio LEDs
Ausgang
Video
Ausgang
Stiftleiste P1 (GPIOs)
LAN
BCM
2835
Contr.
RJ-45
Buchse
( LAN )
Power
5 V Mikro-USB
HDMI
( Typ A )
Stiftleiste P1 (GPIOs)
PWR
ACT
LEDs
micro
SD-Slot
auf der
Rückseite
Energieversorgung
Mikro-USB
5V
AHG Febr. 2015
mit 40 Pins
2x
USB 2.0
Raspberry Pi 2 Model B V1.1
(c) Raspberry Pi 2014
BCM
2836
HDMI
( Typ A )
2x
USB 2.0
LAN
Contr.
Audio/
Video
Ausgang
2x
USB 2.0
RJ-45
Buchse
( LAN )
AHG Mai 2015
Den Arbeitsspeicher teilen sich CPU und GPU. Die Aufteilung kann beim Start des Betriebssystems
festgelegt werden. Ansonsten bekommt die GPU 64 MB und die CPU den Rest.
Die CPU des neueren Π_2B verfügt über kleinere, schnellere Datenspeicher (Cache) als Level 1
cache und Level 2 cache. Beim älteren Π_1B verfügt die CPU über einen Level 1 cache (16 KB)
und der Level 2 cache (128 KB) war ursprünglich nur für die GPU vorgesehen. In der Regel wird
jedoch der Level 2 cache des Π_1B beim Start des Betriebssystems zur Mitbenutzung durch die
CPU freigegeben. Falls viele Grafikberechnungen anfallen, kann man die Mitbenutzung durch die
CPU des Π_1B verhindern.
Der Π ist unter anderem mit einem internen USB-Hub ausgestattet, welcher zwei (Π_1B) beziehungsweise vier (Π_2B) USB-2.0-Anschlüsse bereitstellt, sowie einer Ethernet-Schnittstelle zur
Einbindung in Datennetze (LAN).
3
Gehäuse, Energieversorgung, Bild, Ton, Tastatur und Maus
Ein Gehäuse für den Π (im Bild nicht gezeigt) kann man kaufen oder selbst basteln. Bei billigen
Gehäusen sind die Löcher für die Buchsen des Π mitunter nicht ganz passend und man muss
gegebenenfalls die Gehäuselöcher mit einer kleinen Feile aufweiten.
Die Energieversorgung des Π erfolgt über eine (im Bild des Π nach rechts oben zeigende, metallische) Mikro-USB-Buchse mit einem Netzgerät (im Bild oben rechts gezeigt), das eine Ausgangsspannung von genau 5 V und einen Strom von mindestens 700 mA (es darf mehr sein) für den
Π_1B beziehungsweise mindestens 800 mA für den Π_2B) liefert.
Mit Netzgeräten nicht ausreichender Leistung
arbeitet der Π nicht oder fehlerhaft, insbesondere
beim Anschluss weiterer Geräte über die USBBuchsen (siehe unten). Für einen mobilen Einsatz
des Π kann ein geladener Akku an die MikroUSB-Buchse angesteckt werden. Im Auto kann
der Π über eine Bordspannungssteckdose und
einen Adapter, der 5 V Spannung erzeugt,
betrieben werden.Die Abbildung rechts zeigt in
der Mitte den Π_1B und oben links ein Kabel
zum Anschluss eines Monitors. Der Monitor wird
in der Regel über die HDMI-Buchse des Π
angeschlossen. Der Monitor sollte eine HDMI- oder DVI-Eingangsbuchse besitzen und wird mit
dem entsprechenden Kabel (zum Beispiel einem HDMI-DVI-Kabel) angeschlossen. HDMI und
DVI übertragen Bild und Ton in sehr guter Qualität. Es ist daher praktisch, wenn der Monitor
Lautsprecher enthält.
Ältere Monitore mit VGA-Buchse können über einen Adapter angeschlossen werden. Es ist auch
möglich, das Bild über die (im Bild des Π_1B nach rechts unten zeigende, gelbe) Cinch-Buchse des
Π_1B auf einem Bildschirm mit Composite Video Eingang zu zeigen. Das Tonsignal kann über die
(im Bild des Π_1B nach rechts unten zeigenden, blauen) Buchse für Klinkenstecker (Stereo, 3,5
mm Durchmesser) mit einem Kopfhörer gehört werden. Beim Π_2B gibt es einen kombinierten
analogen Audio- und Videoausgang über eine TRRS-Buchse
für vierpolige Klinkenstecker.
links
links
Das nebenstehende Schema zeigt die Anschlüsse eines Klinrechts
rechts
kensteckers, links für den analogen Audioausgang eines
Masse
Masse
Π_1B und rechts für die analogen Audio- und VideoVideo
ausgänge eines Π_2B .
Als Dateneingabegeräte dienen Tastatur und Maus, die über
die (im Bild des Π_1B nach links unten zeigenden, metallischen) USB-Buchsen des Π angeschlossen werden. Leider
hat der Π_1B nur zwei USB-Buchsen. Wenn man eine Funktastatur mit dazu gehöriger drahtloser
4
Maus (das Bild zeigt unter dem Π_1B ein besonders kleines Exemplar) mit einem einzelnen USBStick (wie im Bild gezeigt) an eine USB-Buchse anschließt, bleibt die zweite USB-Buchse zur
weiteren Verwendung frei. Da die Energieversorgung der USB-Buchsen beim Π schwach ist, sollten
die dort angeschlossenen Geräte (also auch Tastatur und Maus) möglichst wenig Strom brauchen.
Bei zu hohem Stromverbrauch kann es zu Fehlfunktionen (zum Beispiel der Tastatur) kommen.
Ein aktiver USB-Hub, der weitere USB-Buchsen mit eigener Stromversorgung bereitstellt, ist eine
sinnvolle Ergänzung. Damit können auch externe Geräte, die viel elektrische Leistung benötigen,
zum Beispiel externe Festplatten oder DVD-Laufwerke, angeschlossen werden.
Speicherkarte, LAN und WLAN, Kontroll-LEDs, Drucker
Statt einer Festplatte dient beim Π eine kleine Speicherkarte als Datenspeicher für das Betriebssystem, Programme und Daten. Beim Π_1B nimmt man eine SD- oder SDHC-Karte, möglichst
eine SDHC-Karte mit einer Speicherkapazität von mindestens 4 GB. Sie sollte hohe Lese- und
Schreibgeschwindigkeiten haben. Abhängig von der Schreibgeschwindigkeit werden SD- und
SDHC-Karten in Klassen eingeteilt; man sollte eine Karte der Klasse 4 (Schreibgeschwindigkeit 
4 Mbyte/s) oder höher verwenden und auch auf eine hohe Lesegeschwindigkeit achten. Die Karte
wird in die entsprechende Buchse, den SD-Slot (im Bild nicht zu sehen, da er unter der Platine
liegt), eingeschoben. Auch hier sollte man sich vorher, zum Beispiel im Internet, darüber
informieren, welche SD- oder SDHC-Karten vom Π erkannt werden. Entsprechend wird beim
Π_2B eine microSD-Karte verwendet.
Die Verbindung zu einem LAN und damit in der Regel auch zum Internet ist über eine (im Bild des
Π_1B nach links zeigende, metallische) RJ-45-Buchse möglich, in die ein (im Bild links vom
Π_1B gezeigtes) Patchkabel (auch Ethernet-Kabel oder LAN-Kabel genannt) mit 8-poligen RJ-45Stecker passt. Wenn eine USB-Buchse frei ist, kann dort eine WLAN-Antenne mit einem USBStick (im Bild rechts unten gezeigt) angeschlossen werden. Allerdings sollte man sich vorher, zum
Beispiel im Internet, darüber informieren, welche WLAN-USB-Sticks vom Π erkannt werden und
möglichst wenig Strom brauchen (siehe oben). Wenn man prüfen will, welche Funknetzwerke über
die WLAN-Antenne empfangen werden, kann man folgendes Shell-Skript (siehe unten) nutzen:
#!/bin/bash
# wlanscan (AHG, 2016)
sudo iw dev wlan0 scan > scan.tmp
e=`grep 'SSID:' scan.tmp | awk '{print $2}'`
z=`echo $e | wc -w`
f=`grep 'freq:' scan.tmp | awk '{print $2}'`
s=`grep 'signal:' scan.tmp | awk '{print $2}'`
i=1 ; echo
echo "Über wlan0 sind "${z}" Funknetzwerke erreichbar:"
while [ $i -le $z ]
do
t1=${i}") ESSID: "`echo $e | cut -d " " -f $i`
5
t2=", Frequenz: "`echo $f | cut -d " " -f $i`
t3=", Signalstärke: "`echo $s | cut -d " " -f $i\
| cut -d "." -f 1` ; echo ${t1}${t2}" MHz"${t3}" dBm"
i=`expr $i + 1`
done
echo ; rm scan.tmp
Nachdem man es als Datei wlanscan gespeichert und mit chmod a+x wlanscan ausführbar
gemacht hat (siehe unten) kann man es mit ./wlanscan aufrufen.
Die WLAN-Datenübertragung kann oft durch Ausrichtung der Empfangsantenne verbessert werden.
Folgendes Shell-Skript (siehe unten) zeigt die aktuelle Signalstärke einer bestehenden WLANVerbindung an:
#!/bin/bash
echo "Shell-Skript wlansignal (AHG, 2016), Abbruch mit Strg-C"
echo -e "ESSID: `iw dev wlan0 link | sed -n '2 p' | awk '{print $2}'`, \c"
echo -e "Frequenz: `iw dev wlan0 link | sed -n '3 p' | awk '{print $2}'` MHz, \c"
echo "Signalstärke (dBm):"
while true
do
echo -e "\r`iw dev wlan0 link | sed -n '6 p' | awk '{print $2}'` \c"
done
Nachdem man es als Datei wlansignal gespeichert und mit chmod a+x wlansignal ausführbar gemacht hat (siehe unten) kann man es mit ./wlansignal aufrufen.
Die Tätigkeit der Hardware wird durch kleine LEDs sichtbar gemacht. Beim Π_1B sind es:
Kontroll-LEDs im Raspberry Pi, Modell B, Revision 2 ( Π )
Name
Farbe
Beschreibung
ACT
grün
blinkt beim Zugriff auf die SD-Karte, ist auch von Programmen schaltbar
PWR
rot
leuchtet, wenn Versorgungsspannung (auf der 3,3 V Leitung) anliegt
FDX
grün
leuchtet, wenn eine Full Duplex-Verbindung zum LAN-Netzwerk besteht
LNK
grün
leuchtet bei Netzwerkverbindung, blinkt bei Datenverkehr über das LAN
100
gelb
leuchtet bei einer LAN-Übertragungsrate von 100 MBit/s (Fast Ethernet)
Sie befinden sich in einer Ecke auf der Platine des Π_1B . Beim Π_2B sind auf der Platine ebenfalls
die LEDs ACT und PWR. Die LEDs LNK und 100 befinden sich jedoch in der RJ-45-Buchse und
die fünfte LED ( FDX ) fehlt beim Π_2B .
Zur Installation eines lokalen Druckers, zum Beispiel des Modells Samsung ML-1410, wird dieser
am USB-Port des Π angeschlossen und eingeschaltet. Dann gibt man in der Konsole (siehe unten)
folgende Befehle ein:
sudo apt-get update
6
sudo apt-get upgrade
sudo apt-get install cups
sudo usermod -a -G lpadmin pi
Danach öffnet man im Menu unter Internet den Epiphany Webbrowser (siehe unten) und geht zur
Adresse
http://127.0.0.1:631
Im Browser öffnet sich die CUPS-Seite und im Reiter Verwaltung klicken wir auf Drucker
hinzufügen . Nach Eingabe von Benutzername und Passwort erscheint die Seite Drucker hinzufügen
(Schritt 1/5) , auf der man nach Lokale Drucker: das angeschlossene Modell (hier Samsung ML1510_700 genannt) wählt und auf Weiter klickt. Es öffnet sich die Seite Drucker hinzufügen (Schritt
3/5) , auf der man die Felder Name: , Beschreibung: und Ort: ausfüllt, Freigabe: wählt und auf
Weiter klickt. Nun folgt die Seite Drucker hinzufügen (Schritt 5/5) , auf der man einen Druckertreiber angeben soll. Falls der Drucker in der gezeigten Liste enthalten ist, wählt man ihn. Falls
nicht, wie im Beispiel des Samsung ML-1410, muss man eine Treiberdatei (mit der Endung .ppd)
bereitstellen. Für den Samsung ML-1410 ist dies die Datei Samsung-ML-1410-gdi.ppd , die man
vorher auf dem Π gespeichert haben muss. Dann wird auf Drucker hinzufügen geklickt. In der
nächsten Seite wählt man nach Page Size: die Option A4 und klickt auf Standardeinstellungen
festlegen . Schließlich zeigt eine neue Seite eine zusammenfassende Beschreibung und man schließt
das Browserfenster. Danach sollte der Drucker sofort einsatzbereit sein.
Die Dateien zur Konfiguration von CUPS stehen im Verzeichnis /etc/cups (und Unterverzeichnissen). Eine direkte Änderung dieser Dateien (mit einem Editor) ist in der Regel aber nicht nötig.
7
Digitale Anschlusspunkte: GPIOs
Der Π stellt elektrische Anschlusspunkte zur Verfügung, über die digitale Daten (logisch: 0 oder 1)
eingegeben oder ausgegeben werden können. Sie heißen GPIOs (General Purpose Input/Output). Es
gibt beim Π keine Anschlusspunkte zur Ein- oder Ausgabe von analogen elektrischen Signalen. Die
GPIO sind sehr empfindlich und können durch Überspannung ( > 3,3 V ) leicht zerstört werden. Insbesondere muss man beachten, dass das 5 V-Potential des Π nicht auf GPIOs gelegt werden darf.
Bei den GPIOs entspricht 0 V einer logischen 0 und 3,3 V einer logischen 1. Genauer gesagt wird an
einem als Eingang geschalteten GPIO eine Spannung zwischen 0 V und 0,8 V als logische 0 (low)
gelesen, eine zwischen 2,0 V und 3,3 V als logische 1 (high). Spannungswerte zwischen 0,8 V und
2,0 V sollten nicht verwendet werden, da deren Umsetzung in einen Logikpegel unbestimmt ist.
Zu einem als Eingang geschalteten GPIO kann per Software ein interner Pullup-Widerstand oder
Pulldown-Widerstand zugeschaltet werden. Deren Werte liegen zwischen 50 und 65 kΩ. Eine
Ausnahme bilden GPIOs 2 und 3, die beide (um ihre Nutzung für einen I2C Datenbus zu vereinfachen) einen, nicht abschaltbaren, internen 1,8 kΩ Pullup-Widerstand haben. Dies kann die
Nutzung der GPIOs 2 und 3 beeinflussen. Ein externer Pulldown-Widerstand wird in Abschnitt
Schaltung 3 (Schalter) verwendet.
Die digitalen elektrische Anschlusspunkte
sind als doppelreihige Stiftleiste namens P1
ausgeführt (siehe Abbildung rechts).
Beim Π_1B (Raspberry Pi Modell B,
Revision 2) hat die Stiftleiste 26 Pins und
beim Π_2B (Raspberry Pi 2 Model B) hat
sie 40 Pins. Die 26 Pins des Π_1B stimmen
mit den entsprechenden Pins des Π_2B
überein.
P1
Zweireihige Stiftleiste, P1 genannt, für die
Ein- und Ausgabe digitaler Daten über
GPIO-Pins (Stifte). Obere Reihe (rot ge
zeichnet): geradzahlig bezeichnete Pins,
von links (2) nach rechts nummeriert.
Untere Reihe (blau gezeichnet): ungeradzahlig bezeichnete Pins, von links (1) nach
rechts nummeriert. Der Abstand der Pins
beträgt jeweils 2,54 mm (1/10 Zoll).
Ein Teil der Pins der Stiftleiste P1 sind GPIOs, die einen BCM-Kanalnamen des System-on-a-Chip
haben. Andere Pins sind mit der Signalmasse (GND) oder einem positiven elektrischen Potential
(3,3 V oder 5 V) verbunden. Der Strom durch die GPIOS und 3,3 V Pins darf insgesamt maximal 50
mA betragen. Durch einen einzelnen GPIO sollten höchstens 16 mA fließen (siehe hier).
Die 5 V Pins können zusammen soviel Strom an externe Geräte abgeben, wie das Netzteil liefert,
abzüglich des Stroms, der vom Raspberry gebraucht wird.
8
Folgende Tabellen zeigen die Zuordnung von Pin-Nummern der Stiftleiste P1 zu den BCMKanalnamen der GPIOs und die Pins mit festem elektrischem Potential:
Pin
Pin
2
4
6
5V
5V
GND
1
3
5
3,3 V
8
10
12
14
16
18
20
22
24
26
GPIO GPIO GPIO
GPIO GPIO
GPIO GPIO GPIO
GND
GND
14
15
18
23
24
25
8
7
7
9
11
13
15
17
19
21
23
25
GPIO GPIO GPIO
GPIO GPIO GPIO
GPIO GPIO GPIO
GND
3,3 V
GND
2
3
4
17
27
22
10
9
11
Pin-Belegung der Stiftleiste P1 beim Π_1B (Raspberry Pi Modell B, Revision 2) und ebenso im
Anfangsteil der Stiftleiste P1 beim Π_2B (Raspberry Pi 2 Model B)
Pin
28
30
ID_SC GND
Pin
27
ID_SD
29
32
34
36
38
40
GPIO
GPIO GPIO GPIO
GND
12
16
20
21
31
33
35
37
39
GPIO GPIO GPIO GPIO GPIO
GND
5
6
13
19
26
Pin-Belegung im Endteil der Stiftleiste P1 beim Π_2B (Raspberry Pi 2 Model B)
Die mit ID_SC und ID_SD bezeichneten Pins des Π_2B ermöglichen den Anschluss eines
EEPROM-Speichers (ID EEPROM), von dem (beim Booten des Raspberry) Konfigurationsdaten
gelesen werden können (zum Beispiel die Belegung von GPIOs), die für das vorliegende Gerät
gelten. Diese beiden Pins dürfen nicht für andere Zwecke benutzt werden.
Einige GPIOs können vom System-on-a-Chip zum Betrieb eines seriellen Datenbusses oder für
andere Sonderfunktionen genutzt werden.
I2C : GPIO 2 (SDA) und GPIO 3 (SCL), GPIOs 2 und 3 mit 1,8 kΩ Pullup-Widerstand, siehe oben
1-Wire : GPIO 4 (mit dem Treiber w1-gpio), GPIO 4 kann durch Treiber w1-gpio verändert sein
General purpose Clock : GPIO 4 (GPCLK0)
SPI : GPIO 7 (Chip Select 1), GPIO 8 (Chip Select 0),
GPIO 9 (MISO), GPIO 10 (MOSI) und GPIO 11 (SCLK)
UART : GPIO 14 (TXD), GPIO 15 (RXD) und GPIO 17 (RTS), die Sonderfunktion (alternate
function) ist bei GPIOs 14 und 15 nach dem Start des Betriebssystems eingeschaltet
Pulsweitenmodulation : GPIO 18 (PWM)
Beim Π_1B sind zumindest GPIO 22, GPIO 23, GPIO 24, GPIO 25 und GPIO 27 für benutzerdefinierte digitale Ein- und Ausgaben frei verfügbar, ohne die oben genannten Sonderfunktionen
einzuschränken. GPIO 17 wird in der Regel nicht für die UART Schnittstelle gebraucht und ist dann
auch frei verfügbar. Beim Π_2B kommen weitere freie GPIOs auf der Stiftleiste P1 hinzu.
9
In den unten beschriebenen Experimenten müssen GPIO-Pins mit elektronischen Versuchsaufbauten auf einem Steckbrett verbunden werden. Geeignete Steckbrücken mit flexiblem Kabel, an
einem Ende mit Stecker (passend für das Steckbrett) und am anderen Ende mit Buchse (passend für
die GPIO-Pins) sind im Elektronikhandel leicht erhältlich.
In Versuchsaufbauten, bei denen man bis zu drei freien GPIOs ohne Sonderfunktion, sowie eventuell 3,3 V und GND braucht (siehe unten, Experimente 1 und 2), kann man folgende fünf zusammenhängende Pins auf der Stiftleiste P1 benutzen:
P1 Pin
9
11
13
15
17
Belegung
GND
GPIO 17
GPIO 27
GPIO 22
3,3 V
Ein 5-poliges Flachkabel kann, an einem Ende, an eine 5-polige Buchsenleiste mit passendem
Rastermaß (2,54 mm) gelötet werden und, am anderen Ende (über angelötete Drähte mit einem
Durchmesser von 0,5 mm oder 0,6 mm) mit einer Steckplatine verbunden werden. Die Buchsenleiste wird auf die fünf ungeradzahligen Pins 9 bis 17 von P1 aufgesteckt.
10
Software
Boot, Betriebssystem und Konfiguration
Zunächst soll der Boot-Prozess beschrieben werden, um einen tieferen Einblick in die Funktionsweise des Π zu gewinnen. Wer schnell zur praktischen Anwendung gelangen möchte, kann den
folgenden Absatz überspringen.
Mit Einschalten der Stromversorgung wird der Boot-Vorgang in der GPU mit Hilfe von drei Startprogrammen, bootloader genannt, eingeleitet. Zunächst läd die GPU aus dem unveränderlichen
ROM-Speicher im SoC den first-stage bootloader . Dieser erlaubt den Zugriff auf eine Partition der
SD-Karte, die ein FAT32 oder FAT16 Dateisystem enthalten muss, in welchem alle weiteren
Dateien stehen, die für das Booten gebraucht werden. Der first-stage bootloader läd von dort den
second-stage bootloader (Datei bootcode.bin) in den L2 cache. Der second-stage bootloader wird
ebenfalls in der GPU ausgeführt. Er läd den third-stage bootloader (Datei start.elf) in den Arbeitsspeicher (SDRAM). Der third-stage bootloader, der auch in der GPU ausgeführt wird, enthält
Voreinstellungen für den Betrieb des Π und liest die Datei config.txt (falls sie existiert), in der
Änderungen der Voreinstellungen eingetragen sein können (während der Konfiguration des Π).
Außerdem liest er die Datei cmdline.txt, in der Anweisungen für den Kernel stehen, und den Kernel
des Linux-Betriebssystems (Datei kernel.img) in den Arbeitsspeicher. Schließlich startet der thirdstage bootloader die CPU, welche den Kernel ausführt. Außerdem startet der third-stage bootloader
in der GPU ein eigenes Betriebssystem namens VideoCore OS, welches in der GPU ausgeführt wird
(unabhängg vom Linux-Betriebssystem, welches in der CPU läuft).
Verschiedene Linux-Betriebssysteme können auf dem Π laufen. Am einfachsten ist die Installation
über die New Out Of Box Software (oder kurz und liebevoll NOOBS genannt). Dafür muss
NOOBS auf eine SD- oder SDHC-Karte kopiert werden, welche mit dem Dateisystem FAT32
formatiert ist. Neue Speicherkarten mit mehr als 2 GB Speicherkapazität sind in der Regel bereits
mit FAT32 formatiert. Falls eine Neuformatierung notwendig ist, kann dies unter Linux mit dem
Programm GParted geschehen.1 Dabei werden alte Daten auf der Speicherkarte gelöscht.
Auf der Webseite http://www.raspberrypi.org/downloads finden sich der Download-Link für
NOOBS und eine englischsprachige Anleitung für das Kopieren von NOOBS. Die fertige Speicherkarte mit NOOBS schiebt man in den Π und schließt Monitor, Maus und Tastatur an, gegebenenfalls noch LAN. Nun startet man den Π durch Anschluss der Energieversorgung. Einen Knopf zum
Ein- und Ausschalten gibt es nicht. Es zeigt sich auf dem Monitor als Startsymbol die vertraute
1
Nach dem Einlegen der SD-Karte startet man GParted in einem neuen Fenster. In der Kopfzeile des Fensters sollte
etwas wie /dev/mmcblk0 - GParted stehen, wobei mmcblk0, oder ein anderer Name, die SD-Karte bezeichnet. Wir
wählen nun Device - Create Partition Table ... In der folgenden Warnung behalten wir die Option msdos und und
klicken auf Anwenden . Danach wählen wir Partition - New und setzen, im Fenster mit der Kopfzeile Create new
Partition , das File system auf fat 32 . Im Feld Label kann man der neuen Partition einen Namen geben, zum
Beispiel pi . Dann klicken wir auf Hinzufügen und danach auf Edit - Apply All Operations und bestätigen mit
Anwenden . Dann schließen wir das Fenster namens Applying pending operations, klicken einmal auf die Zeile,
welche die neue Partition zeigt, und wählen dann Partition - Manage Flags . Dort machen wir ein Häkchen vor
boot , indem wir auf das Kästchen davor klicken, und schließen das Fenster Manage flags ... wieder. Dann verlassen
wir das Programm, indem wir GParted - Beenden wählen.
11
Himbeere, das Symbol des Π. Anschließend kann man zwischen verschiedenen Betriebssystemen
wählen. Am einfachsten ist die Installation von Raspbian Jessie , welches dann bereits viele
nützliche Programme und eine grafische Oberfläche hat, die sich intuitiv bedienen lässt.
Statt mit NOOBS kann das Betriebssystem Raspbian auch direkt auf der Speicherkarte installiert
werden. Dazu läd man von der oben genannten Webseite (wo auch NOOBS angeboten wird), unter
RASPBIAN JESSIE, durch Klicken auf Download ZIP eine komprimierte (gepackte) neue Version
des Betriebssystems und dekomprimiert (entpackt) es. Dann installiert man es unter Linux, wie auf
der Webseite www.raspberrypi.org/documentation/installation/installing-images/linux.md beschrieben. Dabei wird die Speicherkarte mit einer Image-Datei überschrieben, welche sowohl eine
Partitionierung (mmcblk0p1 und mmcblk0p2) und in jeder Partition ein Dateisystem (FAT32
beziehungsweise EXT4) enthält, als auch alle Dateien des Betriebssystems Raspbian. (Es ist hier
unerheblich, ob die Speicherkarte vor dem Beschreiben partitioniert und formatiert war.)
Es gibt auch Betriebssysteme, die den Π als "Mediacenter" für das Abspielen von Audio- und
Videodateien, sowie Radio und Fernsehen nutzen, zum Beispiel OpenELEC, OSMC (Nachfolger
von Raspbmc) und XBian. Die drei genannten bauen auf der Abspielsoftware Kodi (Nachfolger von
XBMC) auf. Auf diese Betriebssysteme wird im folgenden nicht weiter eingegangen.
Im Folgenden gehen wir davon aus, dass das Betriebssystem Raspbian Jessie (Full desktop image
based on Debian Jessie, vom 9. Februar 2016) installiert wurde.
Nach Einsetzen der Speicherkarte und Einschalten der Stromversorgung wird der Boot-Vorgang
eingeleitet, mit dem Raspbian Jessie startet. Nach dem ersten Start des Betriebssystems erscheint
eine graphische Benutzeroberfläche (LXDE Desktop). Oben links lässt sich ein Menü öffnen und
wir wählen unter Preferences (später Einstellungen genannt) den Menüpunkt Raspberry Pi
Configuration . Es öffnet sich ein Fenster, in dem man die Konfiguration des Betriebssystems
vornehmen kann. Die Raspberry Pi Configuration ersetzt das in früheren Versionen von Raspbian
verwendete Konsolenprogramm raspi-config .
Wir beginnen im Reiter (Tab) Localisation setzen wir die deutsche Ländereinstellung fest. Dazu
klicken wir auf Set Locale... , wählen unter Language: die Option de (German) , Country: DE
(Germany) und Character Set: UTF-8 und bestätigen mit Klick auf OK . Danach klicken wir auf Set
Timezone... , wählen Area: Europe und Location: Berlin (deutsche Zeitzone) und bestätigen mit
Klick auf OK . Schließlich klicken wir auf Set Keyboard... , wählen Germany (Deutschland)
German (Deutsch) und bestätigen mit Klick auf OK . Die Einstellungen werden durch Klick auf OK
im Fenster Raspberry Pi Configuration bestätigt. Auf die Frage Would you like to reboot now?
antworten Yes und der Π startet erneut.
Wir öffnen erneut Raspberry Pi Configuration und wählen im Reiter System die Option Expand
Filesystem, um Raspbian den gesamten Speicherkartenplatz zur Verfügung zu stellen. (Nach Installation über NOOBS ist dies allerdings schon geschehen.) Dann klicken wir auf Change Password...,
ändern das Passwort (voreingestellt: raspberry) für den Benutzer pi und bestätigen mit Klick auf
OK . Das Passwort muss man sich natürlich merken. Hostname (raspberrypi), Boot (To Desktop)
12
und Auto login (angekreuzt) lassen wir unverändert. Wenn der LXDE Desktop den Bildschirm
ausfüllt, belassen wir Overscan auf der Option Enable ; umschließt den Desktop dagegen ein
schwarzer Rand, setzen wir Overscan auf die Option Disable . Wir aktivieren nicht Wait for network
und klicken nicht auf Add to Rastrack... . Mit Boot (To Desktop) finden wir nach dem Betriebssystemstart stets den (LXDE Desktop) vor. (Wenn man stattdessen Boot (To CLI) wählt, startet das
Betriebssystem im textbasierten Modus. In letzterem kann mit dem Befehl startx die graphische
Benutzeroberfläche aufgerufen werden.) Die Einstellungen werden durch Klick auf OK im Fenster
Raspberry Pi Configuration bestätigt. Auf die Frage Would you like to reboot now? antworten Yes
und der Π startet erneut.
Wir öffnen erneut Raspberry Pi Configuration und wählen im Reiter Interfaces : Camera: Disable ,
SSH: Enable (ermöglicht wir den Zugriff auf den Raspberry über ein Netzwerk), SPI: Enable (wird
in Experiment 5 gebraucht), I2C: Enable (wird in Experiment 4 gebraucht), Serial: Enable . Die
Einstellungen werden durch Klick auf OK im Fenster Raspberry Pi Configuration bestätigt. Auf die
Frage Would you like to reboot now? antworten Yes und der Π startet erneut.
Im Reiter Performance des Fensters Raspberry Pi Configuration ändern wir nichts. Beim Punkt
GPU Memory: kann man den Speicheranteil für den Grafikprozessor (GPU) festlegen. Falls man
Videodateien abspielen will, kann eine Erhöhung des voreingestellten Wertes (64) sinnvoll sein.
Alternativ kann statt des Programms Raspberry Pi Configuration auch das (langsam arbeitende)
Konsolenprogramm raspi-config zur Konfiguration verwendet werden. Es muss mit Root-Rechten,
also mit dem Befehl sudo raspi-config , gestartet werden.
Auf dem LXDE Desktop steht ein Terminalemulator namens LXTerminal zur Verfügung (Aufruf
zum Beispiel durch Mausklick auf das Monitorsymbol in der Menüleiste, dem LX Panel). Das
LXTerminal erlaubt in der graphischen Benutzeroberfläche die Eingabe von Befehlstext in einer
Konsole (auch Kommandozeile oder Terminal genannt). In die Konsole geschriebene Befehle
werden von einer Shell interpretiert. Raspbian verwendet eine Shell namens Bash .
In das LXDE System ist der Dateimanager PCManFM eingebunden. Damit kann man Dateien und
Order des Dateisystems (siehe unten) betrachten und öffnen. Im Dateisystem bekommt jeder
Benutzer ein eigenes Stammverzeichnis; der Benutze pi zum Beispiel /home/pi . Wenn man den
Dateimanager über das Menü oder die Menüleiste (Klick auf das Aktenschranksymbol) öffnet, wird
zunächst das Stammverzeichnis des Benutzers angezeigt. Wir wollen einen Ordner namens p
erzeugen, in dem später unsere Programme gespeichert werden. Dazu öffnen wir im PCManFMFenster den Reiter Datei und wählen Neu erzeugen... Ordner . Im Eingabefeld überschreiben wir
dann New mit p und schließen die Aktion mit Klick auf OK ab. Mit einem Doppelklick auf das
Ordnersymbol p können wir das Unterverzeichnis p , in dem wir unsere Programme speichern
werden, öffnen. Die unterste Zeile des PCManFM-Fensters, die Statuszeile, gibt rechts den freien
Speicherplatz an, sowie (in Klammern) den Gesamtgröße des (freien und belegten) Speichers auf
der Speicherkarte.
Später werden wir häufig in der Konsole eigene Programme aufrufen, die als ausführbare Dateien
13
im Ordner p gespeichert sind. Nachdem man in den Ordner p gewechselt ist, kann man ein
Programm prog , das sich in p befindet, mit dem Befehl ./prog aufrufen. Wem das zu umständlich
erscheint, kann folgendermaßen vorgehen: Man öffnet mit einem Texteditor (zum Beispiel Leafpad )
die (versteckte) Datei /home/pi/.profile und fügt am Ende folgende Zeilen ein:
# set PATH so it includes user's directory p if it exists
if [ -d "$HOME/p" ] ; then
PATH="$PATH:$HOME/p"
fi
Nach einem Neustart des Betriebssystems kann man die im Ordner p befindlichen ausführbaren
Programme mit ihrem Namen (zum Beispiel prog ) aufrufen (ohne vorangestelltes ./ ), auch wenn
man sich nicht im Ordner p befindet. Dieses Verfahren funktioniert so allerdings nur, wenn es im
Ordner /home/pi keine Dateien des Namens .bash_profile oder .bash_login gibt (dies ist normalerweise der Fall).
Wenn vor dem Systemstart das LAN-Kabel angeschlossen wurde, sollte auch bereits eine EthernetVerbindung (zum Internet) bestehen. Ist dies der Fall und man fährt mit dem Mauszeiger in der
Menüleiste über das Netzwerksymbol, erscheint eine Zeile eth0: Configured ... Mit dem Befehl
ifconfig eth0
wird in der Konsole die aktive Netwerkverbindung gezeigt und man kann nach inet addr: die IPAdresse des Π lesen (zum Beispiel 192.168.0.100 oder ähnlich). Wenn, wie oben beschrieben, der
Zugriff über ein Netzwerk via SSH erlaubt wurde, kann man von einem anderen Linux-Rechner im
Netzwerk auf den Π zugreifen. Dazu gibt man in der Konsole des anderen Linux-Rechners
ssh pi@IP-Adresse
ein, wobei statt IP-Adresse die aktuelle IP-Adresse des Π eingesetzt werden muss. Für den Zugriff
von einem Windows-Rechner aus kann man das Programm PuTTY benutzen.
Die Konfiguration des WLAN-Empfangs geschieht bei neueren Versionen des Betriebssystems
Raspbian weitgehend automatisch. Über die Benutzerschnittstelle dhcpcd-ui des Programms
dhcpcd , die ein Symbol in der Menüleiste hat, kann man für bekannte WLAN-Netzwerke das
Kennwort (WLAN-Schlüssel) eingeben, welches gepeichert wird.
Zum Auschalten des Π wählt man im Menü Shutdown und kann nach einer halben Minute die
Energieversorgung vom Π trennen.
Das Betriebssystem Raspbian legt bei der Installation eine 100 MB große Auslagerungsdatei ( swap
file ) auf der SD-Karte an. Dort werden Daten kurzzeitig gespeichert, wenn der Arbeitsspeicher ( 512
MB beimΠ_1B , 1024 MB beim Π_2B ) voll ist. Die Größe der Auslagerungsdatei wird in der Datei
/etc/dphys-swapfile festgelegt. Diese Datei kann mit Hilfe eines Texteditors eingesehen und (als
Root) verändert werden.
Die Konfiguration der Bildschirmauflösung und andere Festlegungen werden in einer Datei namens
config.txt im Verzeichnis /boot gespeichert (siehe oben, Abschnitt Boot, Betriebssystem und
14
Konfiguration), welche in der Konsole mit dem Befehl
sudo nano /boot/config.txt
im Editor (Zum Beispiel Nano , siehe unten) verändert werden kann. Das sollte man aber nur mit
Erfahrung tun.
Der Π speichert Datum und Tageszeit als sogenannte Systemzeit. Wenn eine Internetverbindung
besteht, werden Datum und Uhrzeit nach dem Start des Betriebssystems von einem sogenannten
NTP-Server (NTP = Network Time Protocol) geholt. Danach wird die Zeit mithilfe eines internen
Taktgebers des Π weitergezählt. Die Systemzeit kann man mit dem Konsolenbefehl
date
erfragen. Ohne Internetverbindung entspricht die Systemzeit nicht der aktuellen Zeit, da der Π
keine Echtzeituhr (real-time clock) enthält. Man kann in diesem Fall mit einem Konsolenbefehl,
zum Beispiel
sudo date 070813462016
Datum (hier: 8. Juli 2016) und Tageszeit (hier: 13 Uhr 46) manuell setzen.
Wenn man für die Textverarbeitung eigene TrueType Fonts vewenden will, kann man im Verzeichnis /home/pi/ ein Unterverzeichnis (Ordner) .fonts (mit Punkt am Anfang) erstellen und da
hinein die entsprechenden Dateien ( *.ttf ) kopieren.
Die Ausgabe des Tonsignals (Audio) kann entweder analog über den blauen 3,5mm-Klinenstecker
oder digital über die HDMI-Buchse erfolgen. Die Auswahl des Audioausgangs geschieht in Regel
automatisch durch das Betriebssystem, aber das tut es nicht immer so wie gewünscht. Um die
Auswahl des Audioausgangs zu prüfen, gibt man in der Konsole den Befehl
sudo amixer cget numid=3
ein und schaut den Wert der Variablen values in der letzten Zeile an (0 = automatische Auswahl, 1 =
analoger, 2 = digitaler Ausgang). Um das Tonsignal auf den analogen Ausgang zu legen, kann man
den Befehl
sudo amixer cset numid=3 1
verwenden. Für den digitalen Ausgang nimmt man entsprechend den Konsolenbefehl
sudo amixer cset numid=3 2
und die automatische Wahl des Audioausgangs wird mit
sudo amixer cset numid=3 0
hergestellt. Die Signalstärke des Audioausgangs (Lautstärke) kann mit einem Hilfsprogramm verändert werden, das mit dem Konsolenbefehl
alsamixer
aufgerufen wird. Wurde ein Verstärker am Audioausgang angeschlossen, ist es besser, dort die
15
Lautstärke einzustellen.
Auf dem Desktop sieht man Bildchen (Piktogramme), die Icons genannt werden. Die zugehörigen
Bilddateien (und weitere, die nicht auf dem Desktop dargestellt sind) haben das Format png oder
xpm und werden meistens im Ordner /usr/share/pixmaps abgelegt. Die Icons auf dem Desktop
markieren jeweils einen Desktop Shortcut, mit dem ein Programm gestartet oder ein Ordner
geöffnet werden kann. Dies geschieht, wenn man mit der linken Maustaste doppelt auf das Icon
klickt, welches dem Desktop Shortcut zugeordnet ist. Für jeden Desktop Shortcut gibt es eine
Textdatei im Ordner /home/pi/Desktop, die man mit einem Texteditor erstellen und bearbeiten kann
(siehe unten, im Abschnitt Desktop Shortcut für unser Programm). Unerwünschte Desktop Shortcut
kann man entfernen, indem man sie mit rechten Maustaste anklickt und dann im Menü auf Löschen
klickt. Damit wird die zugehörige Datei aus dem Ordner /home/pi/Desktop gelöscht und das Icon
nicht mehr auf dem Desktop gezeigt. Das Programm, welches vom Shortcut gestartet wird, bleibt
erhalten. Auch die Bilddatei des Icons wird nicht gelöscht und bleibt im Ordner /usr/share/pixmaps .
Für Programme im LX Panel (dem Startmenü von LXDE) erzeugt man einen Desktop Shortcut,
indem man mit der rechten Maustaste auf den Programmnamen klickt und die Option Dem Desktop
hinzufügen wählt. Man kann dies zum Beispiel mit dem oft gebrauchten Editor Leafpad machen.
Dateien für Desktop Shortcuts findet man auch im Ordner /usr/share/applications ; um eine davon
zu benutzen, kopiert man sie in den Ordner /home/pi/Desktop .
16
Kommandozeile (Konsole) und Paketverwaltung
Die Konsole (auch Kommandozeile oder Terminal genannt) in Form des LXTerminals erlaubt die
Eingabe von Befehlen, die von der Shell ausgeführt werden sollen. Raspbian Jessie bietet zunächst
standardardmäßig die Shell bash an. Dies kann jedoch geändert werden. Mit dem Befehl
echo $SHELL
wird der Pfad zur aktuell als Standard festgelegten Shell genannt.
Einige besondere Tastendrücke können die Arbeit mit der Shell beschleunigen. In der Shell bash
kann mit der Pfeiltaste ↑ der zuletzt eingegebene Befehl erneut aufgerufen werden. Früher eingegebene Befehle erreicht man durch weiteres Drücken von ↑ . Mit den zwei Pfeltasten ↓ und ↑ kann
man in den früher eingegebenen Befehlen blättern. Der Befehl
history -c
löscht die seit dem Start des Betriebssystems gesammelte Befehlsliste.
Kopieren und Einfügen mithilfe der Tastatur geschieht in der Shell bash über die Tastenkombinationen Strg+Shift+C und Strg+Shift+V (aus historischen Gründen nicht mit Strg+C und Strg+V).
Einmaliges Drücken der Tabulator-Taste ermöglicht die automatische Wortergänzung, zum Beispiel
von langen Dateinamen, sofern die Zuordnung bereits eindeutig ist. Leider funktioniert das in der
Shell bash nur für die Ergänzung von alphanumerischen Zeichen im Namen. Wenn die Zuordnung
noch nicht eindeutig ist, zum Beispiel bei zwei Dateinamen mit gleichem Anfang, zeigt erneutes
Drücken die Möglichkeiten an.
In Linux-Betriebssystemen befinden sich die Dateien sind in Verzeichnissen (Ordnern), die
wiederum in übergeordneten Verzeichnissen enthalten sind. Man nennt diese Anordnung
(Dateisystem) eine hierachische Struktur oder mathematisch gesprochen: Baum. Es ist aber ein
umgekehrter Baum, denn die Wurzel (Root) steht in der Anordnung (Hierachie) ganz oben. Ein
interner Zeiger des Betriebssystems zeigt auf ein Verzeichnis im Dateisystem, das sogenannte
Arbeitsverzeichnis. Ohne besondere Angabe eines anderen Verzeichnisses beziehen sich Befehle auf
das Arbeitsverzeichnis.
Man braucht in der Kommandozeile Befehle, die das Arbeitsverzeichnis ändern. Zum Beispiel
wechselt man mit
cd uv
in das Unterverzeichnis uv des aktuellen Arbeitsverzeichnisses und mit
cd ..
in das Verzeichnis, das über dem aktuellen Arbeitsvezeichnis liegt. Mit
cd /
wechselt man in das Wurzelverzeichnis (Root). Der Befehl
pwd
17
gibt den Namen des Arbeitsverzeichnisses am Bildschirm aus.
Der Schrägstrich / allein bedeutet Wurzelverzeichnis (Root), ./ steht für das aktuelle Verzeichnis und
../ steht für das übergeordnete (nächsthöhere) Verzeichnis. Verzeichnisebenen werden in LinuxBetriebssystemen stets durch einen einfachen Schrägstrich getrennt.
Manche Befehle können nur mit Administratorrechten ausgeführt werden, zum Beispiel für das
Löschen der Datei f eines anderen Benutzers. Dies gelingt, wenn man sudo vor den Befehl setzt:
sudo rm f
Eine Zusammenfassung wichtiger Konsolenbefehle findet man im Anhang (... Wichtige Befehle für
Kommandozeile ...). Im Web gibt es zahlreiche Beschreibungen für die Nutzung der Konsole, zum
Beispiel hier .
In Linuxsystemen, auch in Raspbian, gibt es das Konsolenprogramm fdisk zur Einrichtung und
Darstellung von Partitionen auf Datenträgern mit Master Boot Record (zum Beispiel USB-Sticks,
Speicherkarten und kleinere Festplatten). Es muss mit Administratorrechten ausgeführt werden. Mit
der Option -l zeigt es die Partitionen des nach der Option genannten Datenträgers. Wird kein
Datenträger angegeben, listet der Befehl
sudo fdisk -l
die Partitionen aller Datenträger auf. Die Partitionen sind beim Raspbian-Betriebssystem in der
Datei proc/partitions aufgeführt und können daher auch mit dem Befehl
cat /proc/partitions
angezeigt werden. Vor der Speicherkarte und ihren Partitionen werden 16 RAM-Disks (ram0 –
ram15) aufgelistet, die vom Raspbian-Betriebssystem erzeugt wurden.
Die Programme, die mit dem Betriebssystem Raspbian benutzt werden können, sind in Form von
"Paketen" gespeichert, die von einer Paketverwaltung namens APT verwaltet werden. Die für
Raspbian verfügbaren Pakete werden in einer Datenbank geführt, die auf dem Rechner gespeichert
ist. Um diese Datenbank auf einem neuen Stand zu halten, sollte man nach der Installation und auch
später von Zeit zu Zeit (zum Beispiel einmal im Monat)
sudo apt-get update
in die Konsole eingeben. Um die auf dem Rechner verfügbaren ("installierten") Pakete auf den
neuesten Stand zu bringen, gibt man danach noch folgenden Befehl in die Konsole ein:
sudo apt-get upgrade
Um ein Programm mit dem Namen prog , das über die Paketverwaltung verfügbar ist (Beispiele,
siehe unten), zu installieren, gibt man in der Konsole den Befehl
sudo apt-get install prog
ein. Wenn dies Programm nicht mehr gebraucht wird, kann man es mit dem Befehl
18
sudo apt-get purge prog
vollständig (einschließlich der Konfigurationsdateien) wieder entfernen. Weitere Befehle zur
Paketverwaltung finden sich im Anhang (... Wichtige Befehle für Kommandozeile ...) .
Cronjobs: Programme, die periodisch zu bestimmten Zeiten ausgeführt werden sollen, zum
Beispiel zu jeder vollen Stunde, können als sogenannte Cronjobs (griechisch χρόνος , die Zeit)
automatisch vom Cron-Dämon (crond) des Betriebssystems gestartet werden, welcher bei Raspbian
Jessie standardmäßig im Hintergrund läuft. Nachteilig ist, dass die Programme nicht ausgeführt
werden, wenn der Rechner zu den bestimmten Zeiten ausgeschaltet ist. (Dies Problem kann mit dem
Programm Anacron gelöst werden.) Man kann ein Programm auch nicht zu einem bestimmten
Zeitpunkt einmalig ausführen lassen. (Allerdings kann man den Cron-Dämon anweisen,
Programme nach dem Starten des Rechners auszuführen.) Die Information zu Cronjobs wird für
jeden Nutzer (einschließlich root) in einer eigenen Datei, Crontab, genannt, gespeichert. Die
Crontabs der Nutzer stehen im Verzeichnis /var/spool/cron/crontabs . Außerdem gibt es eine
sytemweite Crontab namens crontab im Verzeichnis /etc .
Um die Arbeit des Cron-Dämons nicht zu stören, wird die Crontab eines Nutzers folgendermaßen
bearbeitet. Der Konsolenbefehl
EDITOR=nano crontab -e
erlaubt die Änderung (e für edit) der Crontab des aktuellen Nutzers mit dem Editor nano . Statt
nano kann auch ein anderer Editor gewählt werden. Falls noch keine Crontab existiert, wird sie
angelegt. In der Crontab wird jeder Cronjob in einer Zeile beschrieben, in der eine Zeitangabe und
das auszuführende Programm stehen. Am Ende der Crontab muss eine Leerzeile oder Kommentarzeile stehen. Für die auszuführenden Programme müssen die Rechte so gesetzt sein, dass sie nur
vom Nutzer ausgeführt werden können.
Die Zeitangabe besteht bei den Crontabs der Nutzer nomalerweise aus fünf Spalten mit Sternchen
(*) oder Zahlen: Minute (0-59), Stunde (0-23), Tag des Monats (1-31), Monat des Jahres (1-12),
Tag der Woche (0-6, 0 ist Sonntag). Die Spalten werden durch Leerzeichen getrennt. Spalten, die
nicht zur Einschränkung der Zeit gebraucht werden, erhalten ein Sternchen. Zum Beispiel wird mit
11 11 11 11 * /home/pi/p/helau.sh
die Shell-Skripte helau.sh im Verzeichnis /home/pi/p am 11. 11. um 11 Uhr 11 ausgeführt. Mehrere
Werte in einer Spalte werden durch Komma (ohne folgendes Leerzeichen) getrennt. Das Zeichen gibt Bereiche an und / Intervalle. Mit
*/5 8-10 * * 2,3 /home/pi/p/messung.sh
wird Dienstags und Mittwochs zwischen 8 und 10 Uhr alle 5 Minuten die Shell-Skripte messung.sh
im Verzeichnis /home/pi/p ausgeführt.
Für manche Zeitangaben gibt es eine kürzere Schreibweise:
@reboot
nach jedem Start des Betriebssystems
@daily
täglich, entspricht
0 0 * * *
19
@hourly
stündlich, entspricht 0 * * * *
Ausgaben eines Cronjobs werden standardmäßig als E-Mail an den Nutzer gesandt, dessen Crontab
den Cronjob gestartet hat (und nicht in einer Konsole auf dem Bildschirm gezeigt). Man kann den
Standardausgabestrom (stdout, Datei-Deskriptor: 1) jedoch in eine Datei umleiten. Wählt man
/dev/null als Datei, wird die Ausgabe verworfen. Der Standardfehlerausgabestrom stderr hat den
Datei-Deskriptor 2. Mit der Zeile
@reboot python3 /home/pi/p/test.py >/dev/null 2>&1
oder, wenn das Pythonprogramm eine Shebang-Zeile enthält (siehe unten), mit
@reboot /home/pi/p/test.py >/dev/null 2>&1
wird das Python-Programm test.py , das im Verzeichnis /home/pi/p steht, nach jedem Systemstart
ausgeführt und die Ausgabe, einschließlich Fehlermeldungen (darum der Zusatz 2>&1) verworfen.
Mit dem Befehl
crontab -l
wird die Crontab des aktuellen Nutzers auf dem Bildschirm angezeigt (l für list) und mit
crontab -r
wird die Crontab des aktuellen Nutzers gelöscht (r für remove).
20
Editor, Browser und weitere Programme
Raspbian enthält die einfachen Texteditoren Leafpad und Nano . Leafpad hat im Gegensatz zu
Nano eine graphische Benutzeroberfläche und erlaubt das Schreiben von Programmen und Texten
ohne anspruchsvolle Formatierungen. Nano wird typischerweise in der Konsole aufgerufen, um
ohne grafische Benutzeroberfläche Konfigurationsdateien zu verändern. Raspbian Jessie enthält
auch das Office-Paket LibreOffice , welches aber, insbesondere beim Π_1B , relativ langsam
arbeitet.
PDF-Dokumente können mit dem Programm xpdf betrachtet werden. In der Konsole wird es für
eine nicht mit Passwort gesicherte PDF-Datei mit dem Befehl
xpdf pfad/zur/datei.pdf
aufgerufen und für eine passwortgesicherte PDF-Datei mit dem Befehl
xpdf -upw passwort pfad/zur/datei.pdf
Im Menü des Desktops kann xpdf unter Zubehör - PDF Viewer aufgerufen werden.
Das Laden von Webseiten aus dem Internet geschieht aufgrund der schwachen Leistung des Π
langsam. Als Browser ist bei Rasbian Jessie Epiphany bereits installiert. Alternativen wie NetSurf
oder Midori 2 (Paket midori) können über die Paketverwaltung (siehe oben) zusätzlich installiert
werden, aber Epiphany ist leistungsfähiger und kann auch Videos abspielen.
Weitere Programme können über die Paketverwaltung installiert werden. Statt LibreOffice kann
man für Textverarbeitung auch abiword benutzen und als Tabellenkalkulationsprogramm steht
gnumeric zur Verfügung. Mit dem Paket fonts-liberation kann man die oft verwendeten Liberation
Fonts installieren; sie verbrauchen 2,2 MB Plattenplatz. Zum Schreiben chinesischer Schriftzeichen
installiert man scim und scim-pinyin , was 48,7 MB an Speicher belegt. Zur Speicherung des
Bildschirminhalts (oder eines Teil davon) als Bild (Screenshot) dient shutter . Das freie E-BookBetrachterprogramm FBReader kann ( unter dem Namen fbreader, Speicherbedarf: 6,4 MB )
installiert werden. Im Menü erscheint dann unter Büro der Eintrag E-book reader , der auf den
FBReader verweist. Zur Darstellung elektronischer Schaltungen ist fritzing grundsätzlich geeignet
(siehe unten, Abschnitt Schaltung 1 (Standard-LED mit Vorwiderstand) ), aber das Programm läuft
langsam auf dem Π . Es belegt 142 MB im Speicher.
Wenn man das Paket youtube-dl installiert und mit dem Befehl
sudo chmod a+rx /usr/bin/youtube-dl
ausführbar macht, kann man, unter Beachtung des Urheberrechts und soweit vom jeweiligen
Anbieter erlaubt, Videos von verschiedenen Anbietern im mp4-Format herunterladen und
anschließend mit dem omxplayer abspielen (siehe unten). Mit der URL url, die man der
Adresszeile des Browsers entnimmt, ergibt der Konsolenbefehl
2
Midori arbeitet schneller, wenn man unter Einstellungen > Verhalten das automatische Laden von Bildern und die
Ausführung von Skripten und Netscape-Modulen abstellt und unter Privatsphäre beide Speicher für HTML5Internet-Daten einschaltet. Es kann auch nützlich sein, unter Programmstart die Option Letzte Reiter zeigen ohne
sie zu laden zu wählen und die am häufigsten besuchte Webseite als Startseite festzulegen.
21
youtube-dl -F url
eine Liste mit Formaten und Auflösungen, in denen das Video zur Verfügung steht. Um es mit dem
omxplayer abspielen zu können, wählt man das mp4-Format mit möglichst geringer Auflösung. Die
Zahl am Anfang der entsprechenden Zeile, zum Beispiel 18, benötigt man, um mit dem Konsolenbefehl
youtube-dl -f 18 url
das Video herunterzuladen. Man beachte den erheblichen Speicherbedarf der Videodateien.
Die Textbeschreibungssprache LaTeX wird mit den Konsolenbefehlen
sudo apt-get install texlive texlive-lang-german
sudo apt-get install texlive-generic-extra texlive-latex-extra
installiert, womit 1126 MB auf der Speicherkarte belegt werden (mit texlive-full statt texlive wären
es mehrere GB). LaTeX-Quellcode kann auf einem normalen Texteditor , zum Beispiel Leafpad ,
geschrieben werden, aber besondere LaTeX-Editoren erleichtern die Arbeit. Wir installieren mit
sudo apt-get install gummi
noch den einfachen LaTeX-Editor Gummi , der 19,3 MB auf der Speicherkarte belegt. Er ist im
Menü des Desktops unter Büro zu finden.
Will man Shell-Skripte mit der (früher sehr beliebten) Kornshell (statt mit bash ) schreiben, kann
man das Paket ksh installieren. Für fortgeschrittene Programmierung mit Python3 (siehe unten)
benötigt man python3-dev und python3-pip , aber die sollten bereits vorhanden sein. pip (Pip Installs
Python) ist eine Paketverwaltung für Python, die ab Python Version 3.4 standardmäßig zu Python
gehören soll. Man kann damit spezielle Pythonmodule installieren, zum Beispiel wifi für das
Arbeiten mit WLAN-Netzen:
sudo pip-3.2 install wifi
Wenn WLAN installiert wurde (siehe oben), kann man mit dem Modul wifi in Pythonprogrammen
WLAN-Netze bearbeiten (scannen, aktivieren usw.). Überdies enthält das Paket wifi auch Befehle
für die Konsole. Zum Beispiel zeigt der Befehl wifi scan eine Liste der empfangbaren Funknetzwerke mit Angabe der Signalstärke und ob sie verschlüsselt sind. Man kann diesen Befehl mit
anderen Konsolenbefehlen kombinieren (siehe oben, Abschnitt Kommandozeile (Konsole) und
Paketverwaltung). Zum Beispiel liefert
wifi scan | sort -nr
eine nach absteigender Signalstärke geordnete Liste der Funknetzwerke.
Zur übersichtlichen Darstellung von empfangbaren Funknetzwerken kann man auch das Programm
wicd-curses benutzen. Es kann über die normale Paketverwaltung installiert werden ( sudo aptget install wicd-curses ) und wird von der Konsole gestartet. Es erzeugt ein Fenster, in dem
die Empfangsstärke, Verschlüsselungsart und Kanalnummer der Funknetzwerke aufgelistet werden.
Eingabe von R über die Tastatur erneuert die Anzeige.
22
Zum Abspielen von Audio- und Videodateien und -streams ( zum Beispiel Internetradio ) kann man
das Programm omxplayer nutzen, das mit dem Betriebssystem Raspbian bereits installiert ist. Es
wird von der Konsole gestartet. Allerdings kann omxplayer nur wenige Dateiformate abspielen,
darunter MP3 (Audio) und MP4 (Video), jedoch keine Wiedergabelisten (zum Beispiel M3U). Liegt
beispielsweise eine Audiodatei musik.mp3 im aktuellen Verzeichnis der Konsole, kann sie mit
omxplayer -o local musik.mp3
abgespielt werden, wobei das Audiosignal auf dem analogen Audioausgang erscheint. Mit
omxplayer -o hdmi musik.mp3
wird das Audiosignal auf dem HDMI Audiokanal ausgegeben.
Es gibt auch Internetradio mit Streams im MP3-Format, die mittels omxplayer abgespielt werden
können, falls eine Internetverbindung besteht ( Programmbeispiel 1, Programmbeispiel 2 ). Eine
Liste geeigneter Internetradio-Sender und ihrer URLs findet man im Anhang.
Leider stellen nicht alle Radiosender einen MP3-Stream bereit, den der omxplayer wiedergeben
kann. Mehr Sender kann man hören, wenn man den VLC media player installiert:
sudo apt-get install vlc
Damit steht vlc , in der Version 2.2.0 oder höher, zur Verfügung. Einige weitere Codecs kann man
durch Austauch der Codec-Bibliothek mit dem Konsolenbefehl
sudo apt-get install libavcodec-extra
installieren.
vlc kann nicht ohne weiteres als Root aufgerufen werden, sondern nur von Benutzern ohne RootRechte. Da vlc, insbesondere mit graphischer Benutzeroberfläche, mehr Rechenzeit braucht, sollte
man ihn nur einsetzen, wenn der omxplayer ungeeignet ist. Etwas schneller arbeitet vlc, wenn man
ihn mit dem Befehl cvlc von der Kommandozeile aufruft. Da vlc mehr Audioformate, zum Beispiel
das PLS Format verarbeitet, kann man mehr Sender als mit dem omxplayer hören. Listen mit
Radio- und Fernsehsendern, die man über das Internet empfangen kann, finden sich im Anhang.
Leider unterstützt der VLC media player bisher nicht die die Hardwarebeschleunigung des Π .
Daher sollten Videos (in geeigneteten Dateiformaten) mit dem omxplayer abgespielt werden.
Jeder Π hat eine eigene Seriennummer. Mit dem Befehl
cat /proc/cpuinfo
wird der Inhalt der Datei cpuinfo im Verzeichnis /proc angezeigt und in der mit Serial: beginnenden
Zeile auch die Seriennummer. Mit dieser kann man eine Lizenz erwerben, die das Abspielen von
Videos im MPEG-2 Format ermöglicht.
Es gibt auch zahlreiche Spiele für den Π , die mit der Paketverwaltung (siehe oben) geladen werden
können. Beispiele: frozen-bubble (Speicherbedarf: 27 MB) quadrapassel (entspricht Tetris, Speicherbedarf: 12,2 MB) und gmchess (chinesisches Schach, Speicherbedarf: 7,5 MB). Zum
23
Schachspielen kann man knights (Schachbrett, Speicherbedarf: 166 MB) und gnuchess
(Schach-"Engine") installieren, zur Schach-Analyse scid und scid-data (Speicherbedarf: zusammen
229 MB).
Steuerung der GPIOs über das Betriebssystem
Digitale Ein- und Ausgaben über die GPIOs werden vom Betriebssystem-Kernel gesteuert, der mit
Anwenderprogrammen über Dateien im Verzeichnis /sys/class/gpio/ kommunizieren kann. Lesen
und Schreiben dieser Dateien ist mit einer beliebigen Programmiersprache möglich, ohne dass
besondere Hilfsprogramme oder Programmbibliotheken nötig wären. Im folgenden Beispiel wird
GPIO 23 (Pin 16 von P1) über die Shell angesprochen. Eine passende elektronische Schaltung wird
in Experiment 1 beschrieben; zunächst soll hier die Handhabung der Dateien erläutet werden.
Um GPIO 23 zu nutzen und gleichzeitig für andere Programme zu sperren, legen wir zunächst eine
neue Schnittstelle in Form von Dateien an. In der Shell geht dies über den Befehl
echo 23 > /sys/class/gpio/export
Damit wird ein Verzeichnis namens /sys/class/gpio/gpio23 eingerichtet, das (unter anderem) vier
Textdateien enthält, die jeweils einen Wert (als Zahl oder Wort) enthalten, nämlich (Standardwert in
Klammern, der bei erster Verwendung des GPIOs nach dem Booten gesetzt wird): active_low ( 0 )
direction ( in ), edge ( none ) und value ( 0 ). Nach dem Wert enthält die Datei noch ein
Zeilenvorschub-Zeichen.
Durch Lesen und Schreiben der in diesen Dateien gespeicherten Werte wird der GPIO gesteuert. Ob
der GPIO als Ein- oder Ausgang bertrieben wird, legt der Wert in der Datei direction fest. Mögliche
Werte sind in und out . Der logische Zustand des GPIOs ( 0 oder 1 ) steht in der Datei value .
Wenn der GPIO als Eingang definiert wurde, liest man den Wert in Datei value ; mit GPIO als
Ausgang schreibt man ihn. Die Datei active_low enthält den Wert 0 oder 1, welcher die Spannungswerte festlegt, die den logischen Zuständen des GPIO entsprechen. Bei 0 in active_low wird der
logische Zustand 0 der Spannung 0 V und 1 der Spannung 3,3 V zugeordnet; bei 1 in active_low ist
es umgekehrt. Der Wert in active_low muss gesetzt sein, bevor Datei value gelesen oder geschrieben wird. Folgende Befehle definieren GPIO 23 als Ausgang und geben den Spannungswert 3,3 V
(als logischen Zustand 1) aus:
echo 23 > /sys/class/gpio/export
echo out > /sys/class/gpio/gpio23/direction
echo 0 >/sys/class/gpio/gpio23/active_low
echo 1 >/sys/class/gpio/gpio23/value
Die erste Zeile scheibt man nur einmal, um GPIO 23 zur weiteren Verwendung zu belegen. Die
zweite Zeile ist hier überflüssig, da der Wert in Datei active_low mit 0 vorbelegt ist (siehe oben).
Nach der Verwendung im eigenen Programm sollte man die GPIOs wieder freigeben, so dass
andere Programme darauf zugreifen können. Im Beispiel mit GPIO 23 geschieht dies durch
echo 23 > /sys/class/gpio/unexport
24
In manchen Anwendungen wird ein GPIO als Eingang geschaltet und ändert zum Beispiel seinen
Wert, wenn ein Taster gedrückt wird. In einem Programm, das auf die Änderung des Eingangssignals (Drücken des Tasters) reagiert, könnte man fortlaufend in einer Schleife den Wert des
GPIOs einlesen und prüfen ( Polling ). Aber das ist nicht effektiv, denn der Prozessor wird unnötig
stark belastet. Alternativ kann man den Prozessor beauftragen, die Wertänderung eines GPIOs in
Form eines Interrupts mitzuteilen. Der Prozessor macht dies effektiver als eine Polling-Schleife.
Der Interrupt kann ausgelöst werden, wenn sich der GPIO-Zustand von 0 auf 1 ändert ( rising ), von
1 auf 0 ändert ( falling ) oder eins von beiden ( both ) geschieht. Dafür wird in die Datei edge der
entsprechende Wert ( none , rising , falling oder both ) geschrieben. Das Auffangen und die Verarbeitung eines Interrupts hängt dann allerdings von der Programmiersprache ab. In Python kann
man die Module select oder selectors verwenden.
Wer GPIOs in einem Python-Programm ansteuern will, kann auch das Modul RPi.GPIO benutzen
(siehe Abschnitt Modul RPi.GPIO zur Steuerung der GPIOs ).
25
Gnuplot und Mathematica (mit Aufgaben 1 und 2)
Gnuplot (dazu: Aufgabe 1)
Zur graphischen Darstellung von Messdaten oder mathematischen Funktionen gibt es das Programm gnuplot, das mit Textanweisungen von der Konsole oder aus einem anderen Programm
heraus gesteuert wird. Weitere Information findet man auf der gnuplot homepage .
Wir installieren, wie oben beschrieben, Gnuplot (Paket gnuplot, oder alternativ Paket gnuplot-x11,
Specherbedarf jeweils 4 MB) und starten dann das Programm in der Konsole mit dem Befehl
gnuplot
Variablen können definiert werden,
a = 2.5
ebenso Funktionen. Die üblichen mathematische Funktionen (zum Beispiel sqrt() für die Wurzelfunktion und exp() für die Exponentialfunktion zur Basis e) und Operatoren (wobei mit ** potenziert wird) können verwendet werden. Als Beispiel für eine Funktionsdefinition schreiben wir
f(x) = a*sin(x)
und mit dem Befehl plot , abgekürzt p , wird damit eine zweidimensionale Graphik erzeugt:
p f(x)
Information zu einem Gnuplot-Befehl erhält man mit help , kurz h , gefolgt vom Befehl; Beispiel:
h plot
Dreidimensionale Graphiken werden mit dem Befehl splot erzeugt, Beispiel:
splot 3*sin(x)*exp(y/30)
Mit der Maus lässt sich die Grafik drehen.
Zum Beenden des Programms dient der Befehl quit oder abgekürzt einfach
q
Wir schauen uns nun einige wichtige Gnuplot-Befehle an:
Die Verwendung des westeuropäischen Zeichensatzes ISO 8859-1 wird mit
set encoding iso_8859_1
festgelegt. Der Titel einer Graphik kann mit
set title "Titel"
bestimmt werden. Für die Klammerung von Zeichenketten kann man in Gnuplot entweder (wie im
vorigen Beispiel) doppelte Anführungszeichen verwenden oder einfache3, wie hier:
set title 'ein "wichtiges" Ereignis'
3
Es gibt Ausnahmen, in denen nur doppelte Anführungszeichen verwendet werden können. Zum Beispiel in dem
Befehl set format x "%H : %M\nUhrzeit" , in dem bei der x-Achsenbeschriftung \n für eine neue Zeile sorgen soll.
26
Die doppelten Anführungszeichen ( " ) sind in obigem Beispiel Teil der Zeichenkette ein "wichtiges"
Ereignis , die von einfachen Anführungszeichen ( ' ) begrenzt wird.
Die Beschriftung von x- und y-Achsen erfolgt mit
set xlabel "Zeit [\265s]"
set ylabel "Temperatur [\260C]"
wobei \265 im Zeichensatz ISO 8859-1 für μ und \260 für ° steht. Mit
unset logscale xy
legt man fest, dass x- und y-Achse nicht logarithmisch, sondern linear sein sollen. Mit
set logscale x
wird die x-Achse dagegen logarithmisch geteilt (und Entsprechendes gilt für die y-Achse). Anfang
und Ende der Achsen werden automatisch bestimmt, wenn nicht, zum Beispiel mit
set xrange [0:pi]
ein Intervall für die x-Achse (und entsprechend für die y-Achse) festgelegt wird. Dabei bedeutet pi
die mathematische Konstante π (≈ 3,14). Mit
set pointsize 3
kann man die Größe der gezeichneten Punkte ändern (hier auf den dreifachen Standardwert). Mit
set time
werden Datum und Zeit am linken unteren Rand der Graphik vermerkt (Zeitstempel).
In einer Datei f.dat gespeicherte Daten können ebenfalls mit plot dargestellt werden, wobei die Datenspalten (für x- und y-Werte) durch Leerzeichen, nicht Kommata, getrennt sein sollen. Beispiel:
plot "f.dat" with linespoints title "Messwerte"
Wenn die Datei in einer dritten Spalte Fehlerbalken enthält, kann man die Darstellung der (durch
eine Linie verbundenen) Messwerte mit einer Zeichnung der Fehlerbalken überlagern. Beispiel:
plot "f.dat" w l title "", "f.dat" w err t "MW \261 StA"
Hier steht w abgekürzt für with , l für lines, err für errorbars , t für title und \261 im Zeichensatz
ISO 8859-1 für ± . (Die Abkürzung StA könnte hier Standardabweichung bedeuten, wenn die in der
dritten Spalte gespeicherten Werte die Fehlerbalken als Standardabweichung enthalten.)
Erzeugte Graphiken können auch in Bilddateien exportiert werden. Zum Beispiel wird mit
set terminal pngcairo mono
set output "m.png"
eine Ausgabe im png-Bidformat vorbereitet und der Name der Bilddatei festgelegt. Die Option
mono bewirkt, dass die Graphik schwarz/weiß (ohne Farben) gezeichnet wird. Mit
27
replot
wird eine zuvor erzeugte Graphik nochmals gezeichnet, diesmal aber (wie vorher festgelegt) als
png-Bild, das in der Datei m.png gespeichert wird.
Befehlsfolgen können auch in einer Textdatei batch.txt gespeichert werden. In Gnuplot wird mit
load "/home/pi/p/batch.txt"
die in der Datei batch.txt , welche im Verzeichnis /home/pi/p liegt, gespeicherte Befehlsfolge
ausgeführt. Wenn batch.txt im aktuellen Verzeichnis ist, braucht man /home/pi/p/ vor batch.txt nicht.
Wenn Gnuplot mit
gnuplot -e "dateiname='m.png'" batch.txt
gestartet wird, arbeitet Gnuplot zunächst den nach -e in Anführungszeichen gesetzten Befehl (hier
die Zuweisung dateiname='m.png' ) ab, danach die Befehlsfolge in batch.txt und endet schließlich.
Gnuplot kann auch Zeitangaben verarbeiten. Als Beispiel
11.02.14/14:58:53 23.45
nehmen wir den nebenstehenden Inhalt einer Datei namens
11.02.14/14:59:23 24.90
bsp.dat . In der linken (1.) Spalte sind Datum und Uhrzeit
11.02.14/14:59:53 25.19
in einem bestimmten Format angegeben, in der rechten (2.)
11.02.14/15:60:23 23.82
Spalte irgendwelche Messdaten als Dezimalzahlen. Die
beiden Spalten werden durch ein Leerzeichen getrennt. Das Format der Zeitangaben beinhaltet
jeweils zweistellige Angaben für Tag, Monat, Jahr, Stunde, Minute und Sekunde. Zwischen diesen
Angaben stehen verschiedene Trennzeichen ( . / : ). Leerzeichen sollte man nicht als Trennzeichen zwischen Zeitangaben verwenden, da Leerzeichen zur Trennung von Datenspalten dienen.
Um die Messdaten der zweiten Spalte als Funktion der Zeitangaben in der ersten Spalte als Graphik
darzustellen gehen wir folgendermaßen vor. Der Gnuplot-Befehl
set xdata time
teilt Gnuplot mit, dass für die x-Achse Zeitangaben erwartet werden. Mit set timefmt wird
dann ein Format für die Zeitangaben bestimmt, zum Beispiel so:
set timefmt '%d.%m.%y/%H:%M:%S'
Dabei repräsentiert %d den Tag (01 ... 31), %m den Monat (01 ... 12), %y das Jahr (mit zwei
Ziffern), %H die Stunde (00 ... 23), %M die Minute (00 ... 59) und %S die Sekunde (00 ... 59). Die
Trennzeichen ( . / : ) müssen genau so zwischen den Zeitangaben stehen, wie im Format
angegeben. Die Darstellung der Zeit auf der x-Achse wird beispielsweise mit einem Befehl
set format x "%H:%M\n %S s"
bestimmt, so dass Stunde und Minute, getrennt von einem Doppelpunkt, angegeben werden und in
einer neuen Zeile darunter, nach einem Leerzeichen, die Sekunden, gefolgt einem Leerzeichen und
dem Buchstaben s . Das Zeichenpaar \ n ist eine sogenannte Escape-Sequenz, welche einen Zeilenvorschub (neue Zeile) bewirkt. Mit
28
plot "bsp.dat" using 1:2 with lines title ""
werden die Messdaten (2. Spalte) als Funktion der Zeit (1. Spalte) gezeichnet. Wenn Zeitangaben in
einer Datei stehen, muss (bei einigen Gnuplot-Versionen) explizit festgelegt werden, welche Spalte
der Datei für die x-Werte und welche für die y-Werte verwendet werden soll. Hier wird mit using
1:2 festgelegt, dass die erste Spalte (mit den Zeitangabe) für die x-Achse und die zweite Spalte für
die y-Achse verwendet werden soll.
Gnuplot kann vorgegebene Funktionen durch Veränderung von Parametern optimal an eine Messpunktmenge anpassen (fitten). Gehen wir von einer linearen Funktion (Geraden)
f(x) = a*x+b
aus, die an Daten in der Datei f.dat (mit x- und y-Werten) angepasst werden soll, schreiben wir
fit f(x) "f.dat" via a,b
um den Fit durchzuführen und zeichnen das Ergebnis mit
plot "f.dat" with points title "", f(x) with l title "fit"
Wenn man aktuelle Werte von Variablen in eine Zeichenkette einfügen will, kann man die Funktion
sprintf() benutzen. So zum Beispiel:
set title sprintf("Fit mit f(x) = %.3f x + %.3f", a, b)
Damit werden die aktuellen Werte der Variablen a und b als Gleitkommazahlen mit drei Nachkommastellen in den Text des Titels eingefügt, was zum Beispiel nach einem Fit sinnvoll sein kann.
Aufgabe 1
Schreiben Sie die Messpunkte aus nebenstehender Tabelle in eine
Textdatei namens m, wobei die x-Werte in der ersten und die y-Werte
in der zweiten Spalte stehen sollen. In jeder Zeile sollen x- und y-Wert
durch ein Leerzeichen getrennt sein.
Mit Gnuplot soll eine Funktion f(x) = a · e b · x + c an die Daten angepasst (gefittet) und die Parameter a, b und c bestimmt werden. Die
Messwerte und die angepasste Funktion sollen in einer Graphik
gezeichnet werden, die als Bilddatei (Format png) gepeichert wird.
x
y
0,5
0,5
3
5
5,5
10
7
20
9,5
50
29
Mathematica (dazu: Aufgabe 2)
Mit dem Betriebssystem Raspbian wird Mathematica kostenlos bereitgestellt, ein mächtiges Werkzeug für computergestütztes wissenschaftliches Rechnen (Scientific Computing). Version 1 wurde
1988 von Stephen Wolfram und seiner Firma Wolfram Research veröffentlicht. Es wird seitdem
ständig erweitert, so dass es heute für viele natur- und ingenieurwissenschaftliche Bereiche
besondere Unterprogrammpakete (packages) gibt. Nachteilig sind hohe Lizenzkosten und die
gewöhnungsbedürftige Art des Programmierens. Andererseits verfügt Mathematica über sehr starke
Befehle, mit denen schwierige Probleme schnell gelöst und graphisch dargestellt werden können.
Allerdings ist die Ausführung vom des umfangreichen Programms auf dem Raspberry langsam.
In Mathematica werden Dokumente angelegt und bearbeitet, die formatierten Text und Bilder
enthalten können und insbesondere Berechnungen durchführen können. Ein solches Dokument
heißt in Mathematica ein Notebook und wird in einer Datei mit der Endung .nb gespeichert. Jedes
Notebook besteht aus nacheinander oder ineinander verschachtelt angeordneten Abschnitten. Ein
solcher Abschnitt heißt Cell. Um das Notebook leicht lesbar zu halten, kann der Inhalt von Cells,
die zum Beispiel eine Zwischenrechnung enthalten, ausgeblendet werden. Die Dokumentenstruktur,
das heisst der Aufbau aus Cells, wird am rechten Rand des Dokuments gezeigt. Ausgeblendete Cells
können bei Bedarf eingeblendet werden. Es ist auch möglich Hyperlinks einzubauen, die den
Sprung von einer Cell zu einer anderen im gleichen oder einem anderen Dokument ermöglichen.
Mathematica besteht aus einem Kernel genannten Kernprogramm, das Berechnungen durchführt,
und einer Benutzeroberfläche, dem Front End. Das Front End verfügt über die übliche
Menüsteuerung. Spezielle aufrufbare Fenster (Palettes) erlauben das Einfügen von Sonderzeichen.
Nach Aufruf eines neuen Notebooks (Doppelklick auf das Mathematica-Symbol des Desktops) wird
eine Input Cell bereitgestellt, in die man Befehlszeilen schreibt. Drückt man Shift-Enter, wird das
Programm abgearbeitet und das Ergebnis in einer automatisch erzeugten Output Cell ausgegeben.
Nach Starten von Mathematica geben wir in eine Eingabe-Zelle die Zeile
4.5*(2^2-2)/(3+7.4/Pi)
ein und drücken Shift-Enter. Das Ergebnis (1.68052) erscheint in einer Ausgabe-Zelle. Übliche
arithmetische Operatoren ^ * / + - ( ) werden verwendet und Ganzzahlen (zum Beispiel 2 oder 3)
von Fließkommazahlen (zum Beispiel 4.5 oder 7.4) unterschieden. ^ steht für "hoch" (Exponent)
und Pi für die mathematische Konstante π. Ein Leerzeichen kann, wie in der mathematischen
Schreibweise üblich, den Multiplikationsoperator * ersetzen. Funktionen erhalten ihre Argumente in
eckigen Klammern. Die Wurzel von x schreibt man in Mathematica als Sqrt[x] und die Quadratwurzel aus 2 ist daher
Sqrt[2]
Wird dies in eine Eingabe-Zelle geschrieben und Shift-Enter gedrückt, erhält man als Ausgabe-Zelle
√2
Da keine numerische Näherung verlangt wurde, gibt Mathematica das Ergebnis symbolisch aus.
30
Eine numerische Näherung ( 1.41421 ) wird ausgegeben, wenn der Ausdruck in der Eingabe-Zelle
mit //N abgeschlossen wird
Sqrt[2]//N
und damit Argument der Funktion N ist ( N[ Sqrt[ 2 ] ] ) . Wir schreiben nun in eine Eingabe-Zelle
x = E Log[10,1000]
und erhalten, nach Drücken von Shift-Enter, in einer Ausgabe-Zelle
3 ℮
Das Zeichen E in der Eingabe-Zelle (℮ in der Ausgabe-Zelle) steht für die Eulersche Zahl. Die
Funktion Log[a,b] bildet den Logarithmus von b zur Basis a. Das Gleichheitszeichen weist der
Variablen x einen Wert zu (Zuweisungsoperator).
Als Beispiel für die Programmierung der graphischen Ausgabe einer Funktion tippen wir folgende
Zeilen in das Mathematica-Notebook:
t1 = {{-2, 10}, {0, 3}, {2, 2}}
g1 = ListPlot[t1, Prolog -> AbsolutePointSize[3]]
t2 = Table[{n, n*n - 3 n + 3}, {n, -3, 3, 0.1}]
g2 = ListPlot[t2, Joined -> True]
g3 = Show[g2, g1]
Dann starten wir die Berechnung (Shift-Enter) und erhalten das Ergebnis in einer Output Cell. Die
erste Befehlszeile erzeugt eine Tabelle mit Messwertpaaren. Die zweite Zeile zeichnet diese Tabelle
(Liste) als Punkte im Koordinatensystem. Die dritte Zeile tabelliert die Funktion f(n) = n2 – 3 · n +3,
wobei der Definitionsbereich das Intervall [-3, 3] ist. Die vierte Zeile zeichnet die Tabelle (Liste)
der Funktion und verbindet die Punkte. Die fünfte Zeile zeichnet beide Einzelgraphiken in einer
neuen Graphik (g3), siehe Abbildung unten rechts, wobei der Bereich der x-Achse von der erstgenannten Einzelgraphik (g2) stammt.
Nun klicken wir mit der rechten Maustaste
auf die Graphik g3, wählen Save Graphic As
… , und speichern die Graphik im Format
png unter dem Namen math_1.png im
Verzeichnis /home/pi/p . Ein Dopppelklick
auf die Datei math_1.png zeigt diese im
Standard-Bildbetrachtungsprogramm.
Aufgabe 2
Tabellieren und zeichnen Sie mit
Mathematica die Funktion √(n!), das heißt: Wurzel aus n Fakultät, im Definitionsbereich [1,10] !
31
Programmieren mit Python
Erstes Programm: "Hallo!", Beispielprogramm (Zeit, Rundung, formatierte Ausgabe)
Python ist die Programmiersprache, welcher der Π seinen Namen verdankt. Sie ist mit dem
Betriebssystem Raspbian Jessie in zwei Versionen installiert, nämlich 2.7.9 und 3.4.2 . Wir
verwenden grundsätzlich Python 3, aber die meisten Programme laufen auch mit Python 2 .
Verfügbar ist auch die integrierte Entwicklungsumgebung IDLE . Sie hat jedoch einige Schwächen
und wird in den später beschriebenen Projekten nicht benutzt. Man kann jedoch mit IDLE leicht
einzelne Pythonbefehle ausprobieren oder kurze Programme testen und sollte das Programm dafür
beim Lernen der Programmiersprache verwenden. Daher wollen wir es uns kurz ansehen:
Im Menü, unter Entwicklung , klicken wir auf Python 3 (IDLE) und es öffnet sich ein Fenster für
IDLE3 mit dem Namen Python Shell . Nach dem Prompt >>> blinkt ein Cursor an der Stelle, wo
wir einen Python-Befehl eingeben können. Wir schreiben
print("Hallo Welt!")
und drücken die Eingabetaste. In der Zeile darunter erscheint das Ergebnis. In diesem Fall wurde
der Text, welcher der Funktion print übergeben wurde, auf dem Bildschirm angezeigt. Die Bestandteile eines Befehls und das Ergebnis werden durch verschiedene Farben (zum Beispiel grün für
Zeichenketten) gekennzeichnet. Man kann IDLE wieder verlassen, indem man im Reiter File auf
die Option Exit klickt. Eine (englische) Dokumentation für IDLE findet man hier .
In der Konsole kann mit dem Befehl
sudo idle3
IDLE (für Python 3) mit Root-Rechten gestartet werden.
Wir schreiben im Folgenden alle Programme mit dem einfachen Texteditor Leafpad, welcher Teil
der LXDE Desktop-Umgebung ist. Unser erstes Programm ist:
#!/usr/bin/python3
print("Hallo!")
Es ist hilfreich, wenn die Zeilennummern angezeigt werden. Dazu klickt man im Leafpad-Menü, im
Reiter Optionen, auf Zeilennummern .
Die erste Zeile des Programms, Shebang genannt, weist das Betriebssystem an, die Datei, die
unseren Python-Code enthält, mit dem Programm python3 auszuführen, welches im Ordner /usr/bin
liegt.4
4
Allgemein gilt: Beim Aufruf einer auszuführenden Datei (die zum Beispiel Python-Code oder ein Shell-Skript
enthalten kann) in der Konsole wird der Aufrufbefehl zunächst von der Standard-Shell analysiert. Wird das
Programm, mit dem die Datei ausgeführt werden soll, zum Beispiel Python3 oder ein bestimmter Shell-Typ, im
Aufrufbefehl genannt, dann wird es gestartet und die auszuführende Datei als Argument übergeben. Wenn das
Programm, mit dem die Datei ausgeführt werden soll, nicht im Aufrufbefehl genannt wird, liest die Shell die erste
Zeile der auszuführenden Datei (also die Shebang-Zeile). Steht am Zeilenanfang #! , dann wird das danach
genannte Programm gestartet und diesem die auszuführende Datei als Argument übergeben.
32
Die zweite Zeile soll die Zeichenkette Hallo! auf dem Monitor ausgeben. Wir speichern das
Programm im Ordner p unter dem Namen hallo.py . Dann öffnen wir eine Konsole, bewegen
uns mit dem Befehl
cd p
in den Ordner p und geben den Konsolenbefehl
chmod a+x hallo.py
ein, welcher die Erlaubnis zur Ausführung (englisch: execution) der Datei hallo.py erteilt.5 Mit
./hallo.py
beginnt die Ausführung und in der Konsole sollte der Text Hallo! ausgegeben werden.
Wir erweitern das obige Programm nun derart, dass vor dem Hallo! angezeigt wird, welche PythonVersion installiert ist. Dies ist bedeutsam, weil die Syntax mit neuen Versionen verändert wird.
#!/usr/bin/python3
import sys # bindet Modul sys mittels einer import-Anweisung ein
print("\nPython Version") # schreibt Zeichenkette Python Version
print(sys.version) # schreibt die aktuelle Python-Versionsnummer
print("\nHallo!\n") # schreibt Zeichenkette Hallo, \n neue Zeile
Wir führen das Programm in gleicher Weise aus wie zuvor.
Die Anweisung import sys bindet das Modul sys aus der Standardbibliothek ein. Dies Modul stellt
Informationen über den Python-Interpreter zur Verfügung. Wenn man mit mathematischen Funktionen arbeiten will, muss man entsprechend das Modul math einbinden.
# leitet einen einzeiligen Kommentar in Python ein (entspricht // in der Programmiersprache C).
Mit dem Zeichenpaar \ n erzeugt man ein Steuerzeichen, welches die Textausgabe in eine neue Zeile
weiterrücken lässt. Damit wird die Textausgabe, insbesondere in der Konsole, lesbarer gestaltet.
Allgemein werden Steuerzeichen oft über sogenannte Escape-Sequenzen dargestellt, die im Quelltext eines Computerprogramms mit einem Backslash ( \ ) eingeleitet werden. Will man verhindern,
dass ein Zeichenpaar \ n in einer Zeichenkette als Steuerzeichen gedeutet wird, muss man den Backslash mit einem zweiten Backslash maskieren. Man schreibt dann also \ \ n .
Führen Sie folgendes Python-Programm in gewohnter Weise aus.
#!/usr/bin/python3
# -*-coding: utf-8 -*import time
s = time.time()
print(s)
5
Dem Befehl chmod folgt eine Zeichenkette, in der zunächst Benutzertypen einbuchstabig angegeben werden (u =
Besitzer der Datei, g = Gruppe, o = andere, a = alle Benutzer), dann mit + oder - bestimmt wird, ob Rechte erteilt
oder entzogen werden sollen, und schließlich die betreffenden Rechte einbuchstabig benannt werden (r = lesen, w =
schreiben, x = ausführen). chmod a+x erteilt allen Benutzern das Ausführungsrecht.
33
time.sleep(3)
s = time.time()
print(s)
text1 = time.strftime("%d.%m.%y/%H%:M:%S")
a=round(3.453,2)
b=round(13.001,2)
print(a)
print(b)
text1 = "Es sind %.0f Sekunden seit dem 1. 1. 1970 vergangen." % s
text2 = "a = %5.2f °C" % a
text3 = "b = %5.2f °C" % b
print(text1)
print(text2)
print(text3)
Mit der Zeile # -*- coding: utf-8 -*- gibt man einen Zeichensatz vor, so dass (nicht nur AsciiZeichen, sondern unter anderem auch) das Grad-Zeichen ° verwendet werden kann.
Mit import time wird das Modul time eingebunden. Damit stehen unter anderem die Funktionen
time() , strftime() und sleep() zur Verfügung. Die Funktion time() des Moduls time liefert die Anzahl
der Sekunden, die seit dem 1. Januar 1970 (ein willkürlich gesetzter Nullpunkt) vergangen sind, als
Gleitkommazahl. Mit time.sleep(3) wird die Ausführung des Programms für 3 s angehalten. Statt
einer 3 kann eine andere ganze Zahl oder eine Gleitkommazahl eingesetzt werden.
Die Funktion strftime(format) liefert das aktuelle Datum und die aktuelle Uhrzeit in der von der
Zeichenkette format bestimmten Weise (ähnlich wie bei Gnuplot, siehe oben). Dabei steht %H für
die Stunde (00 ... 23), %M die Minute (00 ... 59), %S die Sekunde (00 ... 59), %d für den Tag (01 ...
31), %m den Monat (01 ... 12), %y das Jahr mit zwei Ziffern (00 ... 99) und %Y das Jahr mit vier
Ziffern (0000 ... 9999). Übrigens kann die Funktion strftime(format) auch mit einem zweiten
Argument aufgerufen werden, welches einen Zeitstempel enthält, der dann (statt der aktuellen Zeit)
formatiert ausgegeben wird.
Die Funktion round rundet die Zahl, die im ersten Argument übergeben wird mit der Anzahl an
Nachkommastellen (hier: 2), die im zweiten Argument übergeben wird.
Obiges Beispiel zeigt auch, wie man eine bestimmte Formatierung bei der Ausgabe von Zahlen
mittels print zu erreicht. Jede auszugebende Zahl wird in der Zeichenkette durch %format ersetzt,
wobei format die Formatierung angibt. Nach der Zeichenkette folgen, nach dem %-Zeichen, die
Variablen, welche die zu formatierenden Zahlen enthalten.
In format kann vor dem Punkt die Anzahl der Zeichen zur Darstellung der Zahl, nach dem Punkt die
Anzahl der Nachkommastellen angegeben werden. Der Buchstabe am Ende von format bestimmt
die Darstellungsart: d oder i zeigen nur den ganzzahligen Teil, f zeigt eine Dezimalzahl (Gleitkommazahl ohne Exponent) und e oder E zeigt eine Gleitkommazahl in Exponentialschreibweise.
Als Dezimalzeichen dient bei Python ein Punkt (wie bei anderen Programmiersprachen) statt eines
34
Kommas (wie bei deutscher Darstellung). Mit einer solchen Formatierung können Zahlen in einer
Spalte untereinander ausgegeben werden.
.0f bedeutet, dass eine Gleitkommazahl (float) ohne (0) Nachkommastellenausgegeben wird. 5.2f
bedeutet, dass 5 Zeichen zur Darstellung einer Gleitkommazahl ausgeben werden, einschließlich
Dezimalpunkt und zweier Nachkommastellen. Vor dem Dezimalpunkt können also höchstens noch
zwei Stellen stehen.
GUI mit Python, Modul tkinter
In der Programmiersprache Python 2 ist das Modul Tkinter, in Python 3 entsprechend tkinter (kleingeschrieben) enthalten. Damit kann man eine grafische Benutzeroberfläche, kurz GUI (englisch:
Graphical User Interface) erstellen.
Grafische Elemente, Widgets genannt, sind Window (Fenster) und darin enthalten, zum Beispiel
Label (Feld mit formatiertem Text) und Button (beschriftete Schaltfläche, auf der ein Mausklick die
Ausführung einer Prozedur auslöst). Die Aktionen eines Fenster-Objekts werden mit der Methode
mainloop gestartet.
Als Beispiel schreiben wir folgendes Programm:
#!/usr/bin/python3
# -*- coding: utf-8 -*# Datei gui.py (oder gui_py.txt) mit einem Python-Programm, das
# eine grafische Benutzeroberfläche mithilfe von tkinter erzeugt
#
from tkinter import * # bindet alle Teile des Moduls tKinter ein
def minus(): # Ereignisverarbeitungsprozedur (nach Klick auf b1)
l.config(text=str("nimmer!")) # text ist Attribut von Label l
def null(): # Ereignisverarbeitungsprozedur (nach Klick auf b2)
l.config(text=str(1949)) # str() wandelt Zahl in Zeichenkette
def plus(): # Ereignisverarbeitungsprozedur (nach Klick auf b3)
wort=l.cget('text') # weist den Wert des Attributs text zu
if (wort=="immer") or (wort=="nimmer!"): # keine Zahl in wort
l.config(text="immer") # config ist Methode von l
else: # wort enthält keine Zeichenkette, sondern eine Zahl
zahl=int(wort) + 1 # int wandelt Zeichenkette in Zahl um
if (zahl>1990): # Den Sozialismus in seinem Lauf
zahl=1990 # halten weder Ochs noch Esel auf.
l.config(text=str(zahl)) # setzt Attributwert von text
w=Tk() # erzeugt ein window, in das widgets eingefügt werden
w.title('was zählt') # Titel, der oben im window gezeigt wird
w.geometry('245x125') # Breite mal Höhe vom window, Einheit: Pixel
l=Label(master=w, text='1949', bg='ivory', font=('FreeMono', 32))
l.place(x=5, y=5, width=235, height=80) # positioniert Label l
35
b1=Button(master=w, text='rückwärts', bg='tan', command=minus)
b1.place(x=5, y=90, width=75, height=30) # platziert button b1
b2=Button(master=w, text='Aufbau', bg='gold', command=null)
b2.place(x=85, y=90, width=75, height=30) # platziert button b2
b3=Button(master=w, text='vorwärts', bg='pink', command=plus)
b3.place(x=165, y=90, width=75, height=30) # platziert button b3
w.mainloop() # Endlosschleife zur Reaktion auf Ereignisse (events)
Die Zeile # -*- coding: utf-8 -*- gibt einen Zeichensatz vor, so dass auch Umlaute (ä, ö, ü) verwendet werden können. Wir speichern das Programm im Ordner p unter dem Namen gui.py , öffnen
eine Konsole, bewegen uns in den Ordner p und führen das Programm mit folgenden Befehlen aus:
chmod a+x gui.py
./gui.py
Die graphische Oberfläche X11 (X Window System) des Π kann bestimmte Farbnamen erkennen, so
dass diese Farben zum Beispiel in einem Programm benannt werden können (hier zum Beispiel
ivory , tan , gold und pink ). Die beim Π verfügbaren Farbnamen sind in der Datei
/usr/share/x11/rgb.txt aufgelistet.
In tkinter gibt es für widgets (zum Beispiel Label) die Methode after , welche nach einer bestimmten Zeit die Ausführung einer Prozedur (oder Funktion) veranlasst. Wenn die Methode after innerhalb dieser Prozedur steht, entsteht ein wiederholter Aufruf der Prozedur. Damit lassen sich periodisch ablaufende Prozeduren erstellen, ohne dass die Abarbeitung der mainloop unterbrochen wird.
Als Beispiel führen Sie bitte folgendes Python-Programm in gewohnter Weise aus.
#!/usr/bin/python3
# Datei zaehler.py (oder zaehler_py.txt) mit einem Python# Programm, das die Verwendung der tkinter-Methode after zeigt
#
from tkinter import *
zahl = 0
def inc():
global zahl
zahl = zahl + 1
l.config(text=str(zahl))
l.after(1000,inc)
w=Tk()
w.geometry('100x50')
l=Label(master=w, text='str(zahl)')
l.place(x=5, y=5, width=90, height=40)
inc()
w.mainloop()
In tkinter sollte die Methode sleep (siehe unten) nicht verwendet werden, da damit die Abarbeitung
36
der mainloop unterbrochen wird. Das Programm reagiert dann nicht mehr auf Ereignisse und nicht
einmal die Größe des Fensters kann verändert werden.
37
Modul RPi.GPIO zur Steuerung der GPIOs
Die GPIOs können von einem Pythonprogramm (unter anderem) über das Modul RPi.GPIO
angesprochen werden, das mit dem Betriebssystem Raspbian bereits installiert ist. Es ist üblich,
dem Modul beim Einbinden im Programm den Namen GPIO zu geben:
import RPi.GPIO as GPIO
und wir werden es im folgenden auch so halten. In früheren Versionen des Betriebssystems
Raspbian mussten einige Methoden des Moduls mit Root-Rechten ausgeführt werden. Das ist mit
Raspbian Jessie nicht mehr nötig. Die Version des benutzen Moduls ist in der Konstanten
GPIO.VERSION gespeichert und kann mit der print-Funktion angezeigt werden:
print("GPIO-Version: "+GPIO.VERSION)
Für die GPIOs gibt es verschiedene Namensschemata: GPIOs können über die Nummer des Pins
auf der Stiftleiste P1 angesprochen werden oder über die BCM-Kanalnamen des System-on-a-Chip .
Festgelegt wird dies mit der Methode setmode , welche die Konstante GPIO.BOARD (mit dem Wert
10) oder GPIO.BCM (mit dem Wert 11) als Argument bekommen kann. Wir werden im Folgenden
stets die BCM-Kanalnamen verwenden:
GPIO.setmode(GPIO.BCM)
Es ist bei den Methoden des Moduls üblich, die Namen der Konstanten (zum Beispiel GPIO.BCM)
und nicht direkt deren Wert (zum Beispiel 11) zu übergeben, da dadurch der Programmcode für den
Nutzer leichter lesbar ist.
Bei der Nutzung des Moduls RPi.GPIO gibt der Python Interpreter möglicherweise Warnhinweise
aus, die beim Testen nützlich, im fertigen Programm aber stören können. Mit dem Befehl
GPIO.setwarnings(False)
kann man Warnhinweise des Interpreters (nicht aber RuntimeWarnings) unterdrücken.
Jeder GPIO kann entweder zur digitalen Eingabe (input) oder Ausgabe (output) benutzt werden. Die
Methode setup legt für einen GPIO (erstes Argument der Methode) den Modus (zweites Argument
der Methode) fest. Der Modus Eingabe wird durch die Konstante GPIO.IN (Wert 1), der Modus
Ausgabe durch GPIO.OUT (Wert 0) festgelegt. Folgende Befehle bestimmen GPIO 22 zur Eingabe
und GPIO 23 zur Ausgabe:
GPIO.setup(22, GPIO.IN)
GPIO.setup(23, GPIO.OUT)
Man sollte nicht unnötig GPIOs mit Sonderfunktion benutzen. GPIOs 2 und 3 können (zusammen)
für einen I2C Datenbus verwendet werden und haben jeweils einen, nicht abschaltbaren, internen
1,8 kΩ Pullup-Widerstand (siehe oben, Abschnitt Digitale Anschlusspunkte: GPIOs). Wenn GPIO 4
für einen Eindraht-Bus konfiguriert wurde, ist seine Nutzung für einfache Ein- oder Ausgabefunktionen eingeschränkt (siehe Fußnote im Abschnitt Experiment 3: Temperatursensor am
Eindraht-Bus).
38
Digitale Ausgabe bedeutet, dass eine logische 0 (0 V) oder 1 (3,3 V) an den GPIO gegeben wird.
Der Ausgabewert kann durch eine Konstante GPIO.LOW (oder 0 oder False) oder GPIO.HIGH
(oder 1 oder True) angeben werden. Folgendes setzt GPIO 23 auf logisch 1 (high):
GPIO.output(23, GPIO.HIGH)
Es ist auch möglich, mit einem output-Befehl mehrere GPIO-Ausgänge zu schalten, indem im
ersten Argument eine Liste von GPIOs und im zweiten Argument ein Tupel mit denzugehörigen
Ausgabewerten übergeben wird. Zum Beispiel schaltet der Befehl
GPIO.output( [23,24], (0,1) )
GPIO 23 auf logisch 0 (low) und GPIO 24 logisch 1 (high).
Ein anfänglicher Ausgabewert kann auch schon mit der Methode setup bestimmt werden, indem
nach den zwei oben beschriebenen Parametern noch der Schlüsselwortparameter initial mit einem
Wert (GPIO.LOW oder GPIO.HIGH) als Argument übergeben wird. Beispiel:
GPIO.setup(23, GPIO.OUT, initial=GPIO.LOW)
Bei der digitalen Eingabe wird das Potential am GPIO (siehe oben, Abschnitt Digitale Anschlusspunkte: GPIOs) in die Zahl 0 oder 1 übersetzt. In Python wird die Zahl 0 dem logischen Wert False
und 1 dem dem logischen Wert True zugeordnet. In folgendem Beispiel erfolgt eine Ausgabe in
Abhängigkeit vom Wert des, als Eingang geschalteten, GPIO 22 :
if GPIO.input(22):
print("GPIO 22 ist high")
Für digitale Eingänge kann ein interner Pullup- oder Pulldown-Widerstand sinnvoll sein. Ein
Pullup- oder Pulldown-Widerstand wird beim Aufruf der Methode setup angefordert, indem nach
den beiden ersten Parametern noch der Schlüsselwortparameter pull_up_down mit einem Wert
(GPIO.PUD_OFF, GPIO.PUD_UP oder GPIO.PUD_DOWN) als Argument übergeben wird. Zum
Beispiel wird mit dem Befehl
GPIO.setup(22, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO 22 in den Modus Eingabe gesetzt und ein Pulldown-Widerstand (mit einem Wert zwischen 50
und 65 kΩ, siehe Abschnitt Digitale Anschlusspunkte: GPIOs) zugeschaltet. Wenn der Schlüsselwertparameter pull_up_down nicht benutzt wird, ist kein Pullup- oder Pulldown-Widerstand
zugeschaltet (GPIO.PUD_OFF).
Am Ende eines Programms, das GPIOs ansteuert, sollten die GPIOs in den Standardzustand
(Eingabe-Modus ohne Pullup- oder Pulldown-Widerstand) zurückgesetzt werden, in dem die
irrtümliche Verbindung eines GPIOs mit Masse (GND), 3,3 V oder einem anderen GPIO
ungefährlich ist. Außerdem sollte dem Betriebssystem mitgeteilt werden, dass die GPIOs nicht mehr
benutzt (freigegeben) werden. Dies alles geschieht mit der Methode cleanup :
GPIO.cleanup()
Es ist aber meistens unschädlich, wenn der Aufruf von cleanup unterbleibt.
39
GPIOs werden oft verwendet, um die Ausführung eines Programms durch einen Schalter (oder
Taster) zu beeinflussen. Dafür muss der Zustand eines GPIOs im Eingabe-Modus abgefragt werden.
Um schnell auf eine Zustandsänderungen des Schalters reagieren zu können, kann man die input
Methode in kurzen Zeitabständen periodisch aufrufen und das Ergebnis auswerten. Dieses, Polling
genannte Verfahren, wird im Abschnitt Daten eingeben mit Python-Programm verwendet.
Nachteilig ist dabei die starke Belastung des Prozessors, so dass sich dieser wenig um andere
Prozesse kümmern kann, die gleichzeitig (parallel) ablaufen.
Als Alternative, die den Prozessor nur wenig belastet, kann man im Programm den Prozessor
beauftragen, selbst auf bestimmte Ereignisse zu achten. Ein Ereignis (event) bedeutet in diesem
Zusammenhang, dass ein bestimmter GPIO seinen Zustand von low auf high wechselt (rising edge)
oder von high auf low wechselt (falling edge). Den entsprechenden Methoden, welche Ereignisse
erkennen sollen, wird als Argument entweder GPIO.RISING , GPIO.FALLING oder GPIO.BOTH
übergeben. Das letzte bedeutet, dass die Methode sowohl auf eine rising edge als auch auf eine
falling edge reagieren soll. Wenn das Ereignis eintritt, wird der gerade laufende Prozess unterbrochen (Interrupt) und die Information über das Ereignis gespeichert (und danach der Programmablauf fortgesetzt) oder sofort eine Funktion aufgerufen, die auf das Ereignis reagiert.
Wenn die Ausführung eines Programms solange unterbrochen werden soll, bis ein Ereignis eintritt,
kann man die Methode wait_for_edge verwenden.6 Während der Wartezeit des Programms können
andere Prozesse vom Betriebssystem weitergeführt werden. Im folgenden Beispiel wartet ein
Programm auf das Einschalten von GPIO 22 :
GPIO.setmode(GPIO.BCM)
GPIO.setup(22, GPIO.IN)
GPIO.wait_for_edge(22, GPIO.RISING)
print("GPIO 22 hat von low auf high gewechselt.")
Wenn ein Programm in einer Schleife verschiedene Dinge tut und dabei auch auf ein vergangenes
Ereignis reagieren soll, kann man folgendermaßen vorgehen:
GPIO.setmode(GPIO.BCM)
GPIO.setup(22, GPIO.IN)
GPIO.add_event_detect(22, GPIO.RISING)
while True:
print("Immer wieder wird dieser langweilige Satz ausgegeben.")
if GPIO.event_detected(22)
print("GPIO 22 hat von low auf high gewechselt.")
In obigem Beispiel legt die Methode add_event_detect fest, auf welches Ereignis reagiert werden
soll. Die Methode event_detected prüft, ob das Ereignis in der Vergangenheit, aber nach der letzten
Prüfung (sofern es bereits eine gab), eingetreten ist.
6
Die Ereignisverarbeitungsmethoden (zum Beispiel wait_for_edge) können bei GPIOs mit Sonderfunktion (zum
Beispiel GPIO 4, nachdem der Eindraht-Bus aktiviert wurde, siehe Abschnitt Temperaturmessung von der Konsole)
zu einer Fehlermeldung führen. Am einfachsten vermeidet man diese durch Nutzung anderer GPIOs.
40
Mit der Zeile while True: wird eine Endlosschleife eingeleitet. Normalerweise enthält der
Schleifenkörper von Enlosschleifen eine Abbruchbedingung, aber in obigem Beispiel wurde, der
Kürze halber, darauf verzichtet. In der Schleife wird wiederholt der "langweilige Satz" ausgegeben. Nachdem GPIO 22 eingeschaltet wurde, wird zusätzlich (einmal) der Satz "GPIO 22 hat von
low auf high gewechselt." ausgegeben. Anders als bei einer Umsetzung mit Polling sorgt der
Prozessor hier dafür, dass das Einschalten von GPIO 22 nicht verpasst wird.
Wenn der Zustand eines GPIO Eingangs mit einem Taster oder Schalter verändert wird, kann das
Prellen Probleme bereiten. Dagegen hilft das Festlegen einer Zeitdauer bouncetime , die bestimmt
wie lange nach einem Ereignis gewartet wird, bis ein gleichartiges Ereignis erneut registriert wird.
In obigem Beispiel kann der Aufruf der Methode add_event_detect so abgeändert werden :
GPIO.add_event_detect(22, GPIO.RISING, bouncetime=100)
Damit wird die bouncetime auf 100 ms festgelegt.
In obigem Beispiel reagiert das Programm auf das Ereignis erst beim Aufruf der Methode
event_detected und das kann, abhängig von den anderen Anweisungen in der Schleife, lange nach
dem Ereignis geschehen. Will man dagegen schnell auf ein Ereignis reagieren, kann mit den
Methoden add_event_detect und add_event_callback auch ein eigener Thread gestartet werden, in
welchem eine Rückruffunktion (callback function) sofort auf das Ereignis reagiert.
Die Methode remove_event_detect erlaubt es, die Ereignisverarbeitung wieder abzuschalten. Zum
Beispiel für GPIO 22 mit folgendem Befehl :
GPIO.remove_event_detect(22)
Die Ereignisverarbeitung mit dem Modul RPi.GPIO funktioniert oft gut, aber in manchen Programmen treten Laufzeitfehler auf, die von Fehlern des Moduls herrühren. Man sollte daher die Funktionalität der Ereignisverarbeitung bei der Programmentwicklung schrittweise prüfen.
41
Experiment 1: LED ein- und ausschalten
Schaltung 1 (LED) und Steuerung der GPIOs von der Konsole
Um mit einem GPIO eine LeuchtBauteil-Liste
diode an- und auszuschalten, kann
Steckbrett, Kabel, Drahtbrücken
man folgender Weise vorgehen. Der
2 Standard-LEDs, rot und grün
Leuchtdiodenschaltkreis besteht aus
Widerstände: 100 Ω, 330 Ω, 1 kΩ, 10 kΩ
der Reihenschaltung einer LeuchtMultimeter (zur Messung von Spandiode (Standard-LED) und eines
nung und Widerstand in Aufgabe 3)
passenden Vorwiderstands R (zum
Beispiel 330 Ω oder 470 Ω). Die
Anode der Leuchtdiode (siehe Bild rechts, A , langes Beinchen) wird mit GPIO 23
(Pin 16 der Stiftleiste P1) verbunden, die Kathode ( B , kurzes Beinchen) mit einem
Ende des Widerstands. Das andere Ende des Widerstands wird mit GND (Pin 9 von
P1) verbunden.
A K
(+ ‒)
100 Ω
220 Ω
330 Ω
330 Ω
470 Ω
1 kΩ
10 k Ω
Pin 16
von P1
GPIO 23
Pin 9
von P1
GND
Widerstände können mit einem Farbcode versehen sein. Beim Farbcode aus vier farbigen Ringen
zeigen die ersten drei Ringe den nominellen Widerstandswert (Sollwert) und der vierte die Toleranzklasse. Letztere gibt die erlaubte Abweichung des tatsächlichen Widerstandswerts vom nominellen Wert an. Bei oben gezeigten Widerständen beträgt die Toleranz 5 % (goldener vierter Ring).
Man sollte den gewünschten Widerstand anhand
des Farbcodes heraussuchen, aber vor der
Verwendung des Widerstands seinen Wert mit
einem Multimeter auch einmal messen.
Der Leuchtdiodenschaltkreis wird auf einer
Steckplatine aufgebaut (siehe Bild rechts).
42
Schematisch kann man den experimentellen Aufbau
auch mithilfe des Programms Fritzing darstellen
(siehe Bild rechts), das man auf der Webseite des
Fritzing Projekts für verschiedene Betriebssysteme
kostenlos erhalten kann. Einige Linux-Distributionen (zum Beispiel Raspbian und openSUSE)
bieten Fritzing über die Paketverwaltung an.
Mit einem Computerprogramm kann GPIO 23 als
Datenausgang geschaltet werden. Wenn das Programm eine logische 0 ausgibt, liegt 0 V an GPIO
23; wenn es eine logische 1 ausgibt, liegt 3,3 V an
GPIO 23 und die Leuchtdiode leuchtet.
Am einfachsten kann man die Steuerbefehle von
einer Konsole (auch Kommandozeile oder Terminal
genannt) aus geben.
Mit Raspbian Jessie können GPIOs ohne Root-Zugriffsrechte angesteuert werden (siehe oben,
Abschnitt Steuerung der GPIOs über das Betriebssystem). Der früher angewandte Befehl sudo su
zur Erlangung von Root-Rechten entfällt. Zunächst wechselt man in der Konsole mit dem Befehl cd
in das Verzeichnis gpio
cd /sys/class/gpio
und schreibt 23 (die Nummer des GPIO, den wir benutzen wollen) in die Datei export .
echo 23 > export
Der Befehl echo schreibt die nachfolgende Zeichenkette (hier 23) auf den Monitor (Standardausgabe), wenn keine Umleitung erfolgt. Die Zeichenkette kann, muss aber nicht in einfachen (')
oder doppelten Anführungszeichen ( " ) eingefasst werden. Automatisch wird ein Zeilenumbruch
angefügt (sofern er nicht mit der Option ­n unterdrückt wird). In obigem Befehl wird aber mit dem
"größer als"-Zeichen > die Ausgabe umgeleitet und in die Datei export geschrieben.
Dann wechselt man mit dem Befehl cd in das Verzeichnis gpio23 (das automatisch angelegt wurde),
cd gpio23
schreibt out in die Datei direction und 1 in die Datei value
echo out > direction
echo 1 > value
Die Leuchtdiode sollte nun leuchten, Um sie auszuschalten, schreibt man
echo 0 > value
43
Damit GPIO 23 wieder von anderen Programmen angesprochen werden kann, gehen wir in das
übergeordnete Verzeichnis ( /sys/class/gpio ) zurück und geben GPIO 23 frei mit den Befehlen
cd ..
echo "23" > /sys/class/gpio/unexport
Weiteres zu diesem Thema findet man im WWW zum Beispiel hier .
Alternativ könnte man statt einer einfachen Standard-LED auch eine zweifarbige Duo-LED verwenden. Sie besteht aus zwei, in einem Gehäuse
zusammengefassten, LED-Teilen verschiedener Farbe, zum Beispiel rot und
grün. Eine solche Duo-LED kann rot, grün oder gelb leuchten; letzteres wenn
roter und grüner Teil gleichzeitig leuchten. Die Ansteuerung erfolgt meist über
drei Anschlüsse, mit gemeinsamer Kathode oder gemeinsamer Anode. Im Bild
oben rechts wird eine Duo-LED mit gemeinsamer Kathode ( K ) und je einer
Anode für grün ( AG ) und rot ( AR ) gezeigt.
Für beide LED-Teile wird ein Vorwiderstand (zum Beispiel 330 Ω) benötigt,
also je einer vor AG und vor AR . Die beiden Teile werden dann (wie zwei
einzelne LEDs) mit zwei GPIOs (zum Beispiel GPIO 23 und GPIO 24) an- und
ausgeschaltet.
AG K A R
Blinken und Dimmen mit Python-Programmen
Wir benutzen den gleichen Leuchtdiodenschaltkreis und schreiben folgendes Python-Programm.
#!/usr/bin/python3
import RPi.GPIO as GPIO # importiere RPi.GPIO und nenne es GPIO
import time # importiere das Modul time (mit der Funktion sleep)
GPIO.setmode(GPIO.BCM) # benutze GPIO-Namen (statt Pin-Nummern)
g = 23 # speichere die Nummer des GPIO-Ausgangs in Variable g
GPIO.setup(g, GPIO.OUT) # setze GPIO g als Ausgang (OUT)
x = int(input("\nWie oft blinken? ")) # Tastatureingabe von x
text1="\nDie LED sollte jetzt "+str(x)+"-mal blinken.\n"
print(text1) # (ab Python-Version 3 ist print eine Funktion)
n = 0 # speichere, wie oft die LED geblinkt hat, in Variable n
try: # Folgendes normalerweise, ohne Druecken von Ctrl-C
for i in range(0,x): # Schleife, die x mal durchlaufen wird
GPIO.output(g,GPIO.HIGH) # schalte den GPIO g ein (HIGH)
n=i+1 # es hat wieder geblinkt
time.sleep(0.2) # warte 0,2 Sekunden
GPIO.output(g,GPIO.LOW) # schalte den GPIO g aus (LOW)
time.sleep(0.3) # warte 0,3 Sekunden
except KeyboardInterrupt: # Folgendes nach Druecken von Ctrl-C
GPIO.output(g,GPIO.LOW) # schalte den GPIO g aus (LOW)
text2="\nAbbruch durch Ctrl-C nach "+str(n)+"-mal blinken.\n"
44
print(text2) # (ab Python-Version 3 ist print eine Funktion)
GPIO.cleanup() # setzt GPIOs in den Standard-Zustand zurueck
Wir speichern das Programm wird im Ordner p unter dem Namen blink.py , öffnen eine Konsole,
bewegen uns in den Ordner p und geben die Konsolenbefehle
chmod a+x blink.py
./blink.py
ein, worauf gefragt wird, wie oft die LED blinken soll. Wir geben über die Tastatur eine Zahl, zum
Beispiel 10 , ein. Dann erscheint der Text Die LED sollte jetzt 10 mal blinken.
und die LED sollte zehnmal aufleuchten. Um das Programm nochmal zu starten, genügt
./blink.py
Die Anweisung import import RPi.GPIO as GPIO bindet das Modul RPi.GPIO ein. Damit kann
man in Python-Programmen die GPIOs ansteuern.7 Der Zusatz as GPIO bewirkt, dass der Name des
Moduls von RPi.GPIO in (das kürzere) GPIO geändert wird, um im Folgenden Schreibarbeit
einzusparen. Die Methoden des Moduls RPi.GPIO wurden oben, im Abschnitt Modul RPi.GPIO
zur Steuerung der GPIOs beschrieben.
Die Ausführung des Programms soll durch Drücken der Tastenkombination STRG und C abgebrochen werden. Der Programmteil nach try: wird ausgeführt, solange keine "Exception geworfen"
wird, also kein Fehler und kein Abbruchbefehl (allgemein: Ausnahme, englisch exception) auftritt.
Die Tastenkombination STRG und C bewirkt eine Exception, die ohne weitere Maßnahme zum
sofortigen Programmabruch führen würde. Hier jedoch wird eine geworfene Exception mit der
Zeile except KeyboardInterrupt: except "gefangen". Das Programm läuft dann mit dem
Anweisungsblock nach der Zeile except KeyboardInterrupt: weiter. Ohne Exception wird dieser
Anweisungsblock nicht durchlaufen.
Ohne Vorgabe eines Zeichensatzes (siehe oben, Abschnitt Erstes Programm: "Hallo!", Beispielprogramm (Zeit, Rundung, formatierte Ausgabe) ) sollte man keine deutschen Sonderzeichen, wie
zum den Umlaut ü, verwenden. Daher wird im Kommentar der letzten Programmzeile zurueck statt
zurück geschrieben.
7
In ähnlicher Weise kann man mit Hilfe des Programms WiringPi die Ein- und Ausgabe von Daten über die GPIOs
in C und C++-Programmen steuern.
45
Wir wollen nun die Helligkeit der LED vom Programm verändern lassen (Dimmen). Dies kann
nicht durch Veränderung des Durchlassstroms der Diode geschehen, da der GPIO eine feste
Ausgangsspannung von 3,3 V liefert und der Wert des Vorwiderstands sich auch nicht vom
Programm verändern lässt. Die mittlere Helligkeit der LED kann man aber verringern, indem man
sie abwechselnd ein- und ausschaltet. Das Schalten soll nun so schnell erfolgen, dass unser Auge es
nicht bemerkt. Diese Methode heißt Dimmen durch Pulsweitenmodulation.
Wir benutzen wieder den gleichen LED-Schaltkreis und schreiben folgendes Python-Programm.
#!/usr/bin/python3
import RPi.GPIO as GPIO
import time
#
def leuchte():
global f
po.ChangeFrequency(f)
for i in range(0,101,25):
po.ChangeDutyCycle(i)
print("f = %3.0f Hz, Tastgrad = %4.2f" % (f,float(i)/100))
time.sleep(5)
#
g = 23
f = 10
GPIO.setmode(GPIO.BCM)
GPIO.setup(g, GPIO.OUT)
po = GPIO.PWM(g, f)
po.start(0)
leuchte()
#
f = 100
leuchte()
#
po.stop()
GPIO.cleanup()
Nach dem Speichern im Ordner p, unter dem Namen pwm.py , öffnen wir eine Konsole, bewegen
uns in den Ordner p und starten die Programmausführung mit den Konsolenbefehlen
chmod a+x pwm.py
./pwm.py
Die LED wird nun mit einem pulsbreitenmodulierten (PWM) periodischen Rechteck-Signal betrieben, welches vom Modul RPi.GPIO ausgegeben wird. Das PWM Rechteck-Signal besteht aus
einem Wechsel von logischer 0 ( 0 V ) und logischer 1 ( 3,3 V ) mit Zeitdauern von taus beziehungsweise tein . Die Periodendauer des Signals ist T = ( tein + taus ) und die Grundfrequenz f ergibt sich
46
damit als f = 1 / T = 1 / ( tein + taus ) . Der Tastgrad (englisch: duty cycle) ist tein / ( tein + taus ) .
Man kann die Signalform betrachten, indem der Zeitverlauf des Spannungsabfalls am Vorwiderstand R der LED auf einem Oszilloskop sichtbar gemacht wird.
Der Befehl po=GPIO.PWM(g, f) erzeugt eine Instanz namens po des PWM-Objekts zur Ausgabe
auf dem GPIO namens g (hier: GPIO 23) mit der Grundfrequenz f . Die Ausgabe wird mit dem
Befehl po.start(0) begonnen, wobei der Tastgrad zunächst 0 ist (und die LED daher noch dunkel
ist). Mit f = 10 wird der gewünschte Wert der Grundfrequenz auf 10 Hz gesetzt.
In der Prozedur leuchte() erfolgt eine Veränderung des PWM Signals. Der neue Frequenzwert wird
mit dem Befehl po.ChangeFrequency(f) übergeben. Der Tastgrad wird in einer Schleife mit dem
Befehl po.ChangeDutyCycle(i) stufenweise erhöht. Frequenz und Tastgrad werden auf dem
Bildschirm formatiert ausgegeben und die Programmausführung wird dann mit time.sleep(5) für 5 s
angehalten. Währenddessen leuchtet die LED mit dem eingestellten PWM Signal. Bei einer
Frequenz von 10 Hz flackert die LED periodisch; diese Frequenz ist also zu niedrig für das
Dimmen.
Mit f = 100 wird die Grundfrequenz auf 100 Hz gesetzt und die Prozedur leuchte() wird erneut aufgerufen. Man erkennt, dass bei dieser Frequenz kein periodisches Flackern auftritt. Dies liegt am
Überschreiten der Verschmelzungsfrequenz für die visuelle Wahrnehmung.
Der Befehl po.stop() beendet die Ausgabe des PWM Signals.
Bei genauer Betrachtung fällt aber doch ein unregelmäßiges Flackern auch bei f = 100 Hz auf. Dies
liegt an Unregelmäßigkeiten der vom Modul RPi.GPIO erzeugten, programmgesteuerten Modulation. Die Arbeit des Moduls wird nämlich unregelmäßig durch Aktivitäten des Betriebssystems
unterbrochen, zum Beispiel für Garbage Collection . Es gibt Programme, welche PWM Signale
unter Umgehung des Betriebssystems auf den GPIOs ausgeben können, zum Beispiel pi-blaster .
Damit ist dann auch ein Dimmen ohne unregelmäßiges Flackern möglich.
47
Schaltung 2 (LED und Transistor)
Eine entsprechende Schaltung wird rechts gezeigt.
GPIO 24 liefert im
high Zustand ( logische 1 = 3,3 V ) einen
kleinen Steuerstrom
IBE zur Basis B des
Transistors, welcher
zur Signalmasse am
Emitter E abfließt.
Damit wird ein
großer Laststrom ICE
zwischen Collector
C und Emitter E
eingeschaltet, der
von der 5 V
Spannung der
Energieversorgung
gespeist wird.
330 Ω
Pin 4
von P1
5V
Bauteil-Liste
Steckbrett, Kabel, Drahtbrücken
1 npn - Kleinsignaltransistor ( BC547 )
1 Standard-LEDs, rot oder grün
Widerstände: ≈ 330 Ω , ≈ 10 k Ω
Multimeter ( zur Strommessung )
C
E
B
10 k Ω
Der Laststrom, den die GPIOs liefern können, ist (wie
oben beschrieben) beschränkt und daher ist es besser, sie
nur zum Steuern (Ein- und Ausschalten) zu benutzen.
Die elektrische Leistung für die Last (hier: eine LED)
sollte von der Energieversorgung abgenommen werden.
Pin 6
von P1
GND
Pin 18
von P1
GPIO 24
Wir verwenden den einen Transistor vom Typ BC547 oder (falls dieser nicht vorhanden ist, einen
anderen npn - Kleinsignaltransistor). Es gibt ihn in unterschiedlichen Subtypen (BC547A, BC547B
und BC547C), die sich in der Stromverstärkung unterscheiden. Da es keinen nennenswerten
Preisunterschied bei den Subtypen gibt und hier, wie meistens, eine höhere Stromverstärkung
vorteilhaft ist, wählen wir (sofern wir die Wahl haben) den Subtyp BC547C8 mit der höchsten
Stromverstärkung. Um den Transistor in die Steckplatine einstecken können, wählen wir eine
Ausführung im Kunststoffgehäuse TO-92 und nicht im SMD Gehäuse. Der BC547 besteht aus
Silizium (erkennbar am ersten Buchstaben B der Bezeichnung) und wird meistens bei Signalen
kleiner Leistung und niedriger Frequenzen verwendet (erkennbar am zweiten Buchstaben C der
Bezeichnung).
Ausgehend vom BC547C wollen wir mithilfe des Datenblatts sicherstellen, dass der Transistor in
unserer Schaltung nicht überfordert wird: Im Datenblatt finden wir unter absolute maximum ratings
(Ta9 = 25 °C) die maximal zulässige Spannung zwischen Kollektor und Emitter (collector emitter
8
9
Statt mit BC547C kann der Transistot auch (kürzer) mit C547C beschriftet sein.
Ta steht für ambient temperature, zu Deutsch Umgebungstemperatur. Für diese gelten die Angaben im Datenblatt.
48
voltage) VCE von 45 V. Da wir in unserer Transistorschaltung nur eine Spannung von 5 V schalten,
ist VCE ≤ 5 V und damit deutlich unter der maximal zulässigen VCE . Der maximal zulässige fortdauernde (nicht nur kurzzeitg anliegende) Kollektorstrom (continuous collector current) IC beträgt
100 mA. Dies liegt deutlich unter den höchstens IC = 20 mA, mit denen wir eine LED im Kollektorstromkreis betreiben. Beim vollständig leitenden (gesättigten) Transistor beträgt, mit IC = 20 mA ,
der Spannungsabfall zwischen Kollektor und Emitter (collector emitter saturation voltage), VCE (sat)
, 0,3 V oder weniger. Das ergibt eine (den Transistor erwärmende) Verlustleistung von höchstens
VCE (sat) · IC = 0,3 V · 20 mA = 6 mW. Da dies der Hauptbeitrag zur gesamten Verlustleistung des
Transistors (power dissipation) ist, bleibt man deutlich unter der maximal zulässigen Verlustleistung
von 0,5 W.
Schaut man auf die flache (beschriftete) Seite eines BC47 im Kunststoffgehäuse TO-92, so ist der
linke Anschluss der Kollektor C, rechts der Emitter E und in der Mitte die Basis B. Hier wird eine
Emitterschaltung des Transistors verwendet.
Um die LED über den Transistor blinken zu lassen, nehmen wir das gleiche Python-Programm wie
bei Schaltung 1, mit dem einzigen Unterschied, dass GPIO 24 statt GPIO 23 verwendet wird. Wir
müssen also die Zuweisung g = 23 durch g = 24 ersetzen.
Aufgabe 3
a) Wir verwenden nun vier verschiedene Vorwiderstände, um Punkte der Kennlinie einer roten und
einer grünen Standard-LED aufzunehmen. Die Vorwiderstände sollen nach Herstellerangabe
folgende Werte aufweisen (RSoll): 100 Ω, 330 Ω, 1 k Ω, 10 k Ω (oder, falls nicht vorhanden, ähnliche
Werte). Zunächst messen wir mit einem Widerstandsmessgerät (oder einem Multimeter) die
tatsächlichen Widerstandswerte, RIst .
Danach ergänzen wir die Schaltung 1, indem wir zwischen Leuchtdiode und Vorwiderstand R ein
Amperemeter einfügen (Messbereich zwischen 0,1 mA und 20 mA). Wenn ein Multimeter verwendet wird, sollte es vor Einfügung in den Schaltkreis auf Strommessung eingestellt sein. Als
Leuchtdiode soll zunächst eine rote Standard-LED dienen. Nach dem Einschalten der LED (wie
zuvor) fließt ein Strom Irot . Wir messen Irot für alle vier Vorwiderstände.
Dann ersetzen wir die rote durch eine grüne Standard-LED und messen wieder den Strom, Igrün , der
durch die eingeschaltete LED fließt für alle vier Vorwiderstände.
Die Ströme liegen deutlich unterhalb von 16 mA, dem maximalen Strom, der durch einen GPIO
fließen darf. Die Ströme liegen erst recht unter dem Strom von 20 mA, für den Standard-LEDs
ausgelegt sind.
Der Spannungsabfall an der LED, die Durchflussspannung (Flussspannung, englisch: forward
voltage), ergibt nach dem Ohmschen Gesetz aus
Uf,rot = 3,3 V – R · Irot und Uf,grün = 3,3 V – R · Igrün .
Die Durchlassspannung Uf steigt mit dem Strom I .
49
Tragen Sie die gemessenen Ströme und berechneten Spannungen in folgende Tabelle ein.
Vorwiderstand
RSoll (Ω)
RIst (Ω)
rote LED
Irot (mA)
grüne LED
Uf,rot (V)
Igrün (mA)
Uf,grün (V)
100
330
1k
10 k
Verschiedenfarbige LEDs enthalten unterschiedliches Halbleitermaterial. Daher hängt die Durchlassspannung LEDs von deren Farbe ab. Je kurzwelliger das abgegebene Licht ist, desto größer ist
die Energie der Photonen und dies erfordert eine größere Energiedifferenz (Bandabstand) im Halbleiter. Außerdem ist die Kennlinie von LEDs temperaturabhängig.
b) Lassen Sie mit Schaltung 2 die LED über den Transistor blinken. Verlängern Sie die Leuchtdauer, indem Sie die Zeile
time.sleep(0.2) # warte 0,2 Sekunden
durch
time.sleep(10) # warte 10 Sekunden
ersetzen.
Messen Sie den Steuerstrom IBE in die Transistorbasis,
indem Sie ein Amperemeter zwischen GPIO 24 und dem
10 k Ω Widerstand einfügen. Messen Sie den Laststrom
ICE durch die LED, indem Sie ein Amperemeter zwischen
Pin 4 von P1 (5 V) und dem 330 Ω Widerstand einfügen.
Ergebnis:
IBE =
ICE =
ICE / IBE =
50
Experiment 2: Schalter auslesen
Schaltung 3 (Schalter)
Als erstes Beispiel für digitale Dateneingabe über die GPIOs
soll die Stellung eines Schalters ( ein oder aus ) in einem
Programm bestimmt werden. Wir benutzen die nebenstehende Schaltung. Der Schalter soll die Spannung UGPIO an
einem GPIO (hier: GPIO 22, Pin 15 von P1) verändern. Im
offenen Zustand soll UGPIO bei 0 V liegen (logische 0) und im
geschlossenen Zustand bei 3,3 V (logische 1).
Bauteil-Liste
Steckbrett, Kabel, Drahtbrücken
Schalter (einpolig Ein-Aus)
Standard-LED, rot oder grün
Widerstände: 330 Ω, 1 kΩ, 10 kΩ
Pin 17
von P1
3,3 V
Der GPIO muss auf die Betriebsart (Modus)
Eingabe gesetzt werden. Dann ist die Spannung
am Eingang des GPIO unbestimmt, solange
von außen keine Spannung zugeführt wird.
Um bei offenem Schalter die Spannung am
GPIO-Eingang auf 0 V zu ziehen, verbinden
wir diesen über einen Widerstand (hier 10 kΩ
und 1 kΩ in Serie) mit der Signalmasse, (GND,
Pin 20 von P1).
Bei geschlossenem Schalter wird eine Spannungsquelle (3,3 V, Pin 17 von P1) über den
1 kΩ-Widerstand mit dem GPIO-Eingang
verbunden.
Den 10 kΩ-Widerstand, über den bei geöffnetem Schalter den GPIO-Eingang auf 0 V
heruntergezogen wird, nennt man PulldownWiderstand. Entsprechend hiesse ein
Widerstand, der die Signalleitung auf ein
höhere Spannung zieht, ein Pullup-Widerstand.
Pin 15
von P1
GPIO 22
10 k Ω
So liegt bei beiden Schalterstellungen (aus oder
ein) jeweils eine bestimmte Spannung ( 0 V
oder 3,3 V ) am GPIO-Eingang.
1 kΩ
Pin 20
von P1
GND
Bei geschlossenem Schalter fließt ein Strom von der Spannungsquelle (3,3 V) nach GND. Aufgrund
des großen Werts des Pulldown-Widerstands beträgt dieser Strom nur 3,3 V / 10 kΩ = 330 μA . Der
GPIO hat, in der Betriebsart Eingabe, einen so hohen Eingangswiderstand, so dass kein bedeutsamer Strom in oder aus dem GPIO fließt.
Der Widerstand vor dem Eingang (1 kΩ) ist bei richtigem Betrieb des GPIO nicht nötig. Er soll den
GPIO vor Überlastung schützen, für den Fall, dass der GPIO fälschlich auf die Betriebsart Ausgabe
51
gesetzt wurde. (In diesem Fall würde die GPIO-Ausgabe einer logischen 0 bei geschlossenem
Schalter zu einem Kurzschluss zwischen 3,3 V und Signalmasse führen.) Der 1 kΩ-Widerstand ist
also ein strombegrenzender Schutzwiderstand.
Daten eingeben mit Python-Programm
Nach dem Aufbau der Schaltung mit dem Schalter schreiben wir folgendes Python-Programm.
#!/usr/bin/python3
import RPi.GPIO as GPIO # importiere RPi.GPIO und nenne es GPIO
from time import sleep # importiere sleep-Funktion vom Modul time
g1 = 22 # speichere die Nummer des GPIO-Eingangs in Variable g1
GPIO.setmode(GPIO.BCM) # benutze GPIO-Namen (statt Pin-Nummern)
GPIO.setup(g1, GPIO.IN) # setze GPIO g1 als Eingang (IN)
#
try: # Folgendes normalerweise, ohne Druecken von Ctrl-C
while True: # Endlosschleife
ein = GPIO.input(g1) # weist ein entweder 0 oder 1 zu
if ein: # wenn ein = 1 ist, True / wenn ein = 0, False
print("Schalter EIN")
else:
print("Schalter AUS")
sleep(0.5) # warte 0,5 Sekunden
except KeyboardInterrupt: # Folgendes nach Druecken von Ctrl-C
print("\nAbbruch durch Ctrl-C.\n")
GPIO.cleanup() # setzt GPIOs in den Standard-Zustand zurueck
Nach dem Speichern im Ordner p , unter dem Namen schalter.py , öffnen wir eine Konsole, bewegen
uns in den Ordner p und starten die Programmausführung mit den Konsolenbefehlen
chmod a+x schalter.py
./schalter.py
Je nach Schalterstellung wird fortlaufend (in Abständen von etwas mehr als ½ s) entweder Schalter
AUS oder Schalter EIN in eine Zeile der Konsole gesschrieben. Die Ausführung des Programms
kann durch Ctrl-C (Drücken der Taste C , während bereits die Taste Ctrl oder Strg gedrückt ist)
angehalten werden. Um das Programm nochmal zu starten, genügt
./schalter.py
Beim Einschalten kann es zum Prellen kommen, das heißt, der Schalter schwingt mehrfach zwischen Ein und Aus, bevor er im Ein-Zustand bleibt (beziehungsweise umgekehrt beim Ausschalten).
Da jedoch die Schalterstellung in Zeitabständen von etwas mehr als ½ s abgefragt wird, fällt das
Prellen, welches typischerweise nur wenige ms dauert, bei der Programmausführung nicht auf.
52
Desktop Shortcut für unser Programm
Das Programm schalter.py soll, einschließlich Konsole, auch mit einem Desktop Shortcut (siehe
oben, Abschnitt Boot, Betriebssystem und Konfiguration) gestartet werden können. Dazu schreiben
wir folgende Zeilen im Editor Leafpad:
[Desktop Entry]
Name = SOS
Comment = LED blinkt (mit Schalter)
Icon = /usr/share/pixmaps/openbox.xpm
Exec = lxterminal -e "/home/pi/p/schalter.py"
Type = Application
Encoding = UTF-8
Wir speichern dies im Ordner /home/pi/Desktop unter dem Namen blinker.desktop .
Nun kann das Programm mit einem Doppelklick auf ein Icon auf dem Desktop gestartet werden.
Ein Desktop Shortcut enthält nach der Kopfzeile ( [Desktop Entry] ) noch mehrere Zeilen, die
jeweils mit einem Schlüsselwort ( key ) beginnen. Nach dem key folgen ein Gleichheitszeichen
(davor und danach darf ein Leerzeichen stehen) und der Wert ( value ). Mit Name= bestimmt man
den Text, der unter dem Icon auf dem Desktop steht. Comment= erlaubt es, eine Erklärung zum
diesem Desktop Shortcut anzugeben. Mit Icon= gibt man den Pfad zu einer Bilddatei für das Icon
an. Nach Exec= folgt der Pfad zu einer ausführbaren Datei (hier: lxterminal für das LXTerminal),
die mit dem Desktop Shortcut gestartet werden kann. Man kann der Datei auch Optionen und
Parameter übergeben. Mit Type= wird der Typ der auszuführenden Datei angegeben; im
allgemeinen Application (oder Link für einen Verweis auf eine Webseite oder Directory
für einen Verweis auf einen Ordner).
Optionen zum Befehl lxterminal werden erklärt, wenn man man in der Konsole
man lxterminal
eingibt. Der Konsolenbefehl man gibt eine Beschreibung für einen Befehl aus.
Statt der Zeile
Exec = lxterminal -e "/home/pi/p/schalter.py"
kann man auch die beiden Zeilen
Exec = /home/pi/p/schalter.py
Terminal = true
schreiben. Mit Terminal = true wird angegeben, dass das nach Exec= genannte ausführbare
Programm in einer Konsole (hier: LXTerminal) laufen soll.
53
Aufgabe 4
a) Vereinen Sie Schaltung 1 und 3 in einem Aufbau und verändern Sie das Programm schalter.py so,
dass der Schalter nicht eine unterschiedliche Textausgabe in der Konsole bewirkt, sondern die LED
ein- und ausschaltet.
b) Verändern Sie das Programm so, dass die LED bei geschlossenem Schalter blinkt, so wie oben
im Abschnitt Blinken und Dimmen mit Python-Programmen beschrieben.
c) Verändern Sie das Programm so, dass die LED bei geschlossenem Schalter fortlaufend das Notzeichen SOS blinkt (SOS-Anruf dreimal: ...|||... ...|||... ...|||... , Pause, dann wieder vorne beginnen).
54
Experiment 3: Temperatursensor am Eindraht-Bus
Schaltung 4 (Temperatursensor DS18S20)
GPIOs können auch DatenBauteil-Liste
ströme senden oder empfanSteckbrett, Kabel, Drahtbrücken
gen. Im folgenden sollen die
Temperatursensor DS18S20
digitalen Daten eines
Widerstand: 4,7 kΩ
Temperatursensors über
einen Eindraht-Bus (1-Wire)
von einem einzelnen GPIO empfangen werden.
Als Temperatursensor wird der DS18S20 der Firma
Maxim/Dallas (ein Nachfolgemodell des Temperatursensors
DS1820) verwendet, welcher Temperatur zunächst in eine
analoge elektrische Spannung und dann mithilfe eines ADWandlers in digitale Signale wandelt, die über einen Eindraht-Bus
(1-Wire) 10 gesendet werden können. Der experimentelle Aufbau
kann in ähnlicher Weise wie in Experiment 1 (siehe oben)
erfolgen.
Da der Sensor auf einer Steckplatine
aufgebaut werden soll, wird die Bauform
TO-92 mit drei Anschlussbeinchen (Pins)
benutzt. Der TO-92-DS18S20 ist von
vielen Elektronikbauteilehändlern erhältlich
(Preis: 2 – 5 €) und das zugehörige
Datenblatt findet man auch leicht im
Internet.
Pin 1 des DS18S20 wird mit GND (Pin 9
der Stiftleiste P1) verbunden, Pin 2 des TO92-DS18S20 mit GPIO 4 (Pin 7 von P1)
und Pin 3 des TO-92-DS18S20 mit einer
Spannungsquelle (hier 3,3 V von Pin 1 der
Stiftleiste P1) .
DS18S20
DS18S20
1 2 3
Temperatursensor, Gehäuse TO-92
( digitaler
Ausgang )
die ebene
Seite ist
uns zugewandt
Pin 1 GND (Masse)
Pin 2 DQ (Daten)
Pin 3 VDD (Power)
DS18S20
1 2 3
4,7 kΩ
Pin 9
von P1
GND
Pin 7
von P1
GPIO 4
Pin 1
von P1
3,3 V
10 Für einfache Datenübertragungsaufgaben gibt es verschiedene serielle Bussysteme, die zum Teil von Π und
Raspbian unterstützt werden. Dazu gehört der Eindraht-Bus (1-Wire) , der die Daten seriell (nacheinander),
asynchron (ohne zusätzliches Taktsignal) über nur zwei oder drei Leitungen mit einer Geschwindigkeit von
normalerweise 15,4 kbps über Entfernungen bis etwa 100 m überträgt. Es gibt dabei eine Master-Station (hier: der
Π) und eine oder mehrere Slave-Stationen (hier: ein oder mehrere Sensoren); jede Slave-Station hat eine eindeutige,
vom Hersteller vorgegebene Identifikationsnummer. Wenn der Bus mit drei Leitungen gebaut wird, gibt es neben
der Masseleitung eine Datenleitung und eine für die Versorgungsspannung (zwischen 3 V und 5,5 V). Beim Aufbau
mit zwei Leitungen entfällt die Versorgungsspannungsleitung und die Slave-Station (Sensor) gewinnt die
notwendige Energie "parasitär" aus der Datenleitung. Der Betrieb mit drei Leitungen ist stabiler, und wird hier
daher vorgezogen, aber man braucht eine Leitung mehr. Der Name des Eindraht-Bus (1-Wire) stammt vom Aufbau
mit zwei Leitungen, da dann zusätzlich zur Masse nur eine weitere Leitung gebraucht wird.
55
Über Pin 2 des DS18S20 werden binäre Daten empfangen oder gesendet. Die beiden logischen
Zustände werden hier durch die Spannungen 0 V (logisch LOW) und 3,3 V (logisch HIGH) vermittelt. Ein 4,7 kΩ Widerstand wird zwischen Pin 2 und Pin 3 des TO-92-DS18S20 gesteckt.11
Der Treiber w1-gpio (siehe unten) verwendet GPIO 4 für den 1wire-Bus, wenn bei der Konfiguration des Gerätebaums (siehe unten) dem 1wire-Bus kein anderer GPIO zugeordnet wurde.
Temperaturmessung von der Konsole mit DS18S20
Für die Temperaturabfrage vom Sensor kann man Steuerbefehle für die Konsole in ähnlicher Weise
wie in Experiment 1 benutzen. Das Betriebssystem Raspbian Jessie spricht den Eindraht-Bus (1Wire) über einen sogenannten Gerätebaum (device tree) an, nachdem der Eindraht-Bus im Gerätebaum aktiviert wurde. (Ältere Beschreibungen des Eindraht-Busses, die von Betriebssystemvarianten vor Raspbian Wheezy ausgehen, funktionieren daher nicht ohne weiteres.12)
Dazu wird die Datei config.txt im Verzeichnis boot ergänzt. Zunächst wird diese Datei mit dem
Editor nano geöffnet
sudo nano /boot/config.txt
und dann werden folgende Zeilen am Ende der Datei angefügt, gespeichert und die Datei wieder
geschlossen. Der Befehl sudo wird vorgesetzt, weil die Bearbeitung der Datei nur als Root möglich
ist. Statt nano kann man natürlich auch den Editor leafpad benutzen.
# activate 1-wire and debugging
dtoverlay=w1-gpio
dtdebug=on
Die Änderung wird erst nach erneutem Booten des Rechners wirksam. Mit dtoverlay=w1-gpio
sollten nun die Treiber für den Eindraht-Bus (w1-gpio und w1-therm) zur Verfügung stehen.13 Die
Zeile dtdebug=on bewirkt, dass die Konfiguration des Gerätebaums (und Störungen) protokolliert
und, nach Neustart des Rechners, mit dem Befehl sudo vcdbg log msg angezeigt werden.
11 Der Transistorausgang von Pin 2 des DS18S20 hat eine Open-Drain-Schaltung (so genannt bei Feldeffekttransistoren, bei Bipolartransistoren entspricht dies einer Open-Collector-Schaltung) und nimmt daher die Zustände 0 V
oder Offen an. Offen bedeutet, dass der Transistor intern idealerweise vom Ausgang getrennt ist, real über einen
großen Widerstand (hochohmig). Um im Offen-Zustand die Spannung 3,3 V bereitzustellen, wird der Ausgang über
einen sogenannten Pullup-Widerstand mit der 3,3 V Versorgungsspannung verbunden. Wenn der Transistor durchschaltet, also der Ausgang auf 0 V gesetzt wird, fließt Strom durch den Widerstand; aber da der Transistorausgang
niederohmig mit 0 V (Masse) verbunden ist, bleibt die Spannung nahe 0 V.
12 In früheren Betriebssystemvarianten wurden die Treiber für den Eindraht-Bus mit dem Befehl modprobe zur
Verfügung gestellt (also durch sudo modprobe w1-gpio und sudo modprobe w1-thermx).
13 Dadurch ist allerdings die Nutzung von GPIO 4 eingeschränkt und zum Beispiel die Ansteuerung einer LED (siehe
Experiment 1) an GPIO 4 vielleicht nicht mehr möglich. Will man GPIO 4 wieder für einfache Ein- oder Ausgabefunktionen nutzen, muss man die Einbindung des Eindraht-Busses im Gerätebaum rückgängig machen. Dafür
löscht man in der Datei config.txt die vorher eingefügten Zeilen oder kommentiert sie aus, indem ein Doppelkreuzzeichen vorangestellt wird:
# activate 1-wire and debugging
# dtoverlay=w1-gpio
# dtdebug=on
56
Um zu prüfen, ob die Treiber geladen wurden, kann man folgenden Befehl ausführen:
lsmod
Wenn die Treiber geladen sind, wird mit dem Befehl cd in das Verzeichnis devices gewechselt
cd /sys/bus/w1/devices/
dann lässt man sich mit dem Befehl ls den Inhalt des Verzeichnisses devices anzeigen
ls
Es gibt dort ein Verzeichnis, dessen Name der Seriennummer des Sensors entspricht. In dieses
Verzeichnis wechselt man mit dem Befehl cd
cd Name
und gibt den Inhalt der Sensor-Datei w1_slave mit dem Befehl cat auf dem Monitor aus
cat w1_slave
Es werden zwei Zeilen ausgegeben. In der zweiten steht nach t= eine Zahl. Fügt man nach den
beiden ersten Ziffern in Gedanken ein Dezimalkomma ein, erhält man die Temperatur in ºC. Wenn
man den Sensor mit zwei Fingern anfasst, erwärmt er sich und ein erneuter Befehl
cat w1_slave
sollte eine höhere Temperatur anzeigen.
Ergänzender Hinweis: Statt des Temperatursensors DS18S20 kann auch der neuere Typ DS18B20
verwendet werden, welcher die Temperatur mit höherer Auflösung (12 bit) ausgibt.
Python-Programm zur Temperaturmessung mit DS18S20 (mit Aufgabe 5)
Wir benutzen den gleichen Temperatursensor-Schaltkreis und schreiben folgendes Python-Programm. Dabei muss, in der vierten Zeile, für Name der Name des verwendeten Temperatursensors
eingesetzt werden, welcher oben (Abschnitt Temperaturmessung von der Konsole mit DS18S20)
gefunden wurde.
#!/usr/bin/python3
import sys
import time
sensor= "Name" # Name des Temperatursensors
pfad = "/sys/bus/w1/devices/"+sensor+"/w1_slave"
print("\nPython Version "+sys.version)
text1="\nTemperatur am Sensor "+sensor+", Abbruch durch Ctrl-C"
text2="**********************************************************"
print(text1) # schreibe die Ueberschrift der Messungen
print(text2) # (print ist, ab Python-Version 3, Funktion)
try: # Folgendes normalerweise, ohne Druecken von Ctrl-C
while 1: # Endlosschleife zur Temperaturmessung alle 3 s
57
zeit = time.strftime("%H:%M:%S") # Uhrzeit in zeit
sd = open(pfad,"r") # oeffne Sensor-Datei
daten = sd.read() # Sensor-Inhalt in daten
sd.close() # schliesse Sensor-Datei
# folgende 4 Befehle entnehmen daten den Temperaturwert
zeile = daten.split("\n")[1] # daten aufteilen, 2. Zeile
wort = zeile.split(" ")[9] # zehntes Wort der 2. Zeile
temp = wort[2:] # wort ohne die ersten beiden Zeichen
T = float(temp)/1000 # Zeichenkette zu Zahl, durch 1000
text3 = zeit+": T = "+str(T)+" Grad C" # Ausgabetext
print(text3) # schreibe den Ausgabetext (Messungen)
time.sleep(3) # warte 3 Sekunden
except KeyboardInterrupt: # Folgendes nach Druecken von Ctrl-C
print("\n- Messung beendet -\n") # Ende des Programms
Das Programm wird im Ordner p unter dem Namen temp.py gespeichert. Wir öffnen eine Konsole,
bewegen uns in den Ordner p und geben die Konsolenbefehle
chmod a+x temp.py
./temp.py
ein. Das Programm kann (mit dem Betriebssystem Raspbian Jessie) ohne Root-Rechte ausgeführt
werden. Die Ausführung kann durch Ctrl-C angehalten und durch ./temp.py erneut gestartet
werden.
Aufgabe 5
a) Ändern Sie das oben angegebene Python-Programm zur Temperaturmessung so, dass der gerundete Temperaturwert mit einer Nachkommastelle ausgegeben wird (siehe oben, Abschnitt Beispielprogramm (Zeit, Rundung, formatierte Ausgabe) ).
b) Außerdem soll statt des Wortes Grad das Symbol ° erscheinen. Dafür muss, wie oben beschrieben, ein Zeichensatz vorgegeben werden.
c) Schreiben Sie ein neues Programm zur Temperaturmessung, in dem Ein- und Ausgaben über eine GUI
erfolgen (siehe Abbildung rechts). Als Layout-Vorlage
soll das oben (im Abschnitt GUI mit Python, Modul
Tkinter) beschriebene GUI dienen.
Statt einer automatisch fortlaufenden Messung beschränken wir uns zunächst auf Einzelmessungen, die mit einem
Klick auf den Button b1 (measure) ausgelöst werden. Das
Messergebnis soll im Textfeld (label) angezeigt werden.
Ein Klick auf den zweiten Button, b2 (-> °F), soll die Anzeige von °C auf °F umstellen (und b2
58
erhält dann die Aufschrift -> °C); ein weiterer Klick soll die Anzeige von °F auf °C zurückstellen.
Ein Klick auf den dritten Button, b3 (quit) soll das GUI-Programm beenden. Wenn w die Variable
ist, welche das Fensterobjekt (window) enthält, kann dies durch Aufruf einer Prozedur wie
def qt():
w.destroy() # beende das GUI-Programm, schliesse Fenster
geschehen. Damit verschwindet das window und das Programm wird beendet.
d) Ergänzen Sie das neue Programm zur Temperaturmessung mit einem wiederholten Aufruf der
Prozedur, welche die Messung vornimmt und für die Erneuerung der Anzeige sorgt. Damit sollte,
durch einen Klick auf den Button b1 (measure), eine automatisch fortlaufende Temperaturmessung
ausgelöst werden. Die vorher festgelegten Ereignisse für Button b2 (-> °F / -> °C) und Button b3
(quit) sollen wie zuvor wirken.
e) Fügen Sie dem neuen Temperaturmessprogramm die Speicherung in einer Datei hinzu.
Um jede Messung in einer neuen Datei mit eigenem Namen zu speichern, soll der Dateiname vom
Programm erzeugt werden und das aktuelle Datum und die aktuelle Uhrzeit enthalten. Dies kann
mit Hilfe der Funktion strftime() des Moduls time geschehen. Zum Beispiel könnte eine am 30. 11.
2014 um 12:01:05 Uhr erzeugte Datei den Namen T_141130120105.dat tragen. Wenn die größeren
Zeiteinheiten vor den kleineren stehen (Jahr > Monat > Tag > Stunde > Minute > Sekunde) werden
die Dateien bei einer alphabetischen Sortierung auch chronologisch geordnet. Der Dateiname soll in
einer Variablen namens dat_name gespeichert werden. Die Datei muss am Programmbeginn geöffnet werden, zum Beispiel so:
td = open(dat_name,'w') # oeffne Datei, td enthält Dateiobjekt
Nach jeder Messung soll eine Zeichenkette
time.strftime("%d.%m.%y/%H:%M:%S")+' '+'%6.2f' % round(T,1) + '\n'
in die Datei geschrieben werden, wobei die Variable T den Temperaturwert in °C enthält. Diese
Zeichenkette enthält eine formatierte Zeitangabe, eine Lücke als Trennzeichen und den Temperaturwert als Dezimalzahl mit zwei Nachkommastellen.
Am Ende des Programms, vor w.destroy() , soll die Datei geschlossen werden, zum Beispiel so:
def qt():
global td
# mache Variable td (Dateiobjekt) bekannt
td.close()
# schliesse Temperatur-Datei
w.destroy()
# beende das GUI-Programm, schliesse Fenster
f) Ergänzen Sie das neue Temperaturmessprogramm um die Erzeugung, Speicherung und Anzeige
einer Temperaturverlaufsgraphik mit Hilfe von Gnuplot, zum Beispiel durch Erweiterung der
Funktion qt() in folgender Weise:
def qt():
global dat_name, sensor, td, z # mache Variablen bekannt
td.close()
# schliesse Temperatur-Datei
59
pd = "T_"+z+".png" # Name der Graphikdatei (png-Format)
td = open("batch.txt",'w')
# oeffne Gnuplot-Datei
aus = "# Gnuplotbefehle ..."
# Hier müssen Sie etwas ergänzen!
td.write(aus)
# schreibe in Gnuplot-Datei
td.close()
# schliesse Gnuplot-Datei
os.system('gnuplot batch.txt')
# fuehre die Gnuplot-Datei aus
os.system('display.im6 '+pd)
# zeige die Graphik-Datei an
w.destroy() # beende das GUI-Programm, schliesse Fenster
Den Inhalt der Variablen aus (eine Zeichenkette) müssen Sie ergänzen!
60
Experiment 4: Temperatursensor am I2C Bus
Wir wollen nun einen weiteren Datenbus kennenlernen, den
I2C Bus, mit dem viele verschiedenene Geräte an den Π angeschlossen werden können. Hier soll ein Temperatursensor vom
Typ LM75, und zwar der Subtyp mit 3,3V Betriebsspannung
angeschlossen werden. Er wandelt (ähnlich wie der in
Experiment 3 verwendete DS18S20) Temperatur zunächst
in eine analoge elektrische Spannung und dann mithilfe
eines AD-Wandlers in digitale Signale, die über einen
seriellen Datenbus zum Π gesendet werden. Der Schaltplan
oben rechts zeigt, dass im einfachsten Fall neben dem
LM75 keine weiteren elektronischen Bauteile benötigt
werden.
Bauteil-Liste
Temperatursensor LM75, auf
einer Leiterplatte befestigt, mit
vier Anschlussleitungen zum Π
3-poliger DIP-Schalter
Widerstände: 3 Stück à 10 kΩ
3,3 V
GPIO 2
GPIO 3
GND
1
AHG
SDA
2
SCL
3
OS
4
GND
LM75
Schaltung 5 (Temperatursensor LM75)
+VS
8
A0
7
A1
6
A2
5
Temperatursensor
Nachteilig ist jedoch, dass der LM75 in der Regel nur in der SMD Bauform angeboten wird. Die
acht Anschlussbeine (Pins) sind kurz, eng benachbart und brechen leicht ab. Daher ist es schwierig,
ihn direkt mit Anschlussleitungen zu versehen oder ihn mit einer Steckplatine zu verbinden. Am
einfachsten ist es wohl, den LM75 auf eine SO-8 Adapterplatine zu löten. Mit Geschick kann man
den L75 auch auf eine normale Lochrasterplatine (oder eine andere Leiterplatte) kleben und
Anschlussleitungen zugentlastet (über Lötaugen) zum Π führen.
Vier der LM75 Pins (SDA, SCL, GND, +VS) führen zu Pins der Stiftleiste P1 des Π. Drei Pins des
LM75 (A0, A1 und A2) werden im einfachsten Fall direkt mit Masse (GND) verbunden; der achte
Pin (OS) wird hier nicht verwendet. Der Π stellt für den I2C Bus die GPIOs 2 und 3 bereit, welche
(im Gegensatz zu anderen GPIOs) mit einem internen 1,8 kΩ Pullup-Widerstand versehen sind, um
die Beschaltung des I2C Busses zu vereinfachen. Die Verbindung von LM75 und Π erfolgt gemäß
dem obigem Schaltplan und nachfolgender Tabelle.
LM75
Π
Pin 1
SDA
Pin 2
SCL
P1, Pin 3 P1, Pin 5
GPIO 2 GPIO 3
Pin 3
OS
Pin 4
GND
Pin 5
+VS
Pin 6
A0
Pin 7
A1
Pin 8
A2
P1, Pin 9 P1, Pin 1 P1, Pin 9 P1, Pin 9 P1, Pin 9
GND
3,3 V
GND
GND
GND
Temperaturmessung von der Konsole mit LM75
Um den I2C Bus nutzen zu können, müssen entsprechende Module im Gerätebaum zur Verfügung
gestellt werden. Dies geschieht am einfachsten, indem bei der Konfiguration des Π mit Raspberry
Pi Configuration oder raspi-config die Option I2C: Enabled gewählt wurde (siehe oben, Abschnitt
Boot, Betriebssystem und Konfiguration). Man kann dies prüfen, indem man in der Konsole den
Befehl
61
lsmod | grep i2c
eingibt. Der Befehl lsmod gibt eine Liste aller geladenen Module aus. Der Ausgabedatenstrom wird
mit dem |-Zeichens (das eine Pipe erzeugt; es ist meistens auf der Tastatur vorhanden) als Eingabe
des Befehls grep i2c verwendet, der alle Zeilen ausgibt, welche die Zeichenkette i2c enthalten. Im
Ergebnis sollten zwei Zeilen am Bildschirm erscheinen, die mit i2c beginnen. Geschieht dies nicht,
müssen die Module noch in den Gerätebaum eingefügt werden, indem man Raspberry Pi Configuration nochmals startet und nun die Option I2C: Enabled wählt (siehe oben, Abschnitt Boot,
Betriebssystem und Konfiguration).
Bei Raspbian Jessie steht in der Datei /etc/modules bereits die Zeile i2c­dev . (Im früheren
Betriebssystem Raspbian Wheezy musste man, mit Root-Rechten, diese Zeile noch selbst ergänzen
und den Rechner dann erneut booten.) Mit
sudo apt-get update
führen wir ein Update durch (siehe oben, Abschnitt Kommandozeile (Konsole) und Paketverwaltung) und installieren ein Paket mit Hilfsprogrammen sowie ein Python3-Modul für den I2C Bus:
sudo apt-get install i2c-tools python3-smbus
Mit i2ctools kann man den I2C Bus von der Konsole ansprechen und das Modul smbus stellt eine
Klasse bereit, mit der man den I2C Bus aus einem Python-Programm ansprechen kann.
Um den I2C Bus als normaler Benutzer ohne Root-Zugriffsrechte aufrufen zu können, fügen wir uns
(den aktuellen Benutzer $USER ) der Gruppe i2c hinzu, welche den I2C Bus benutzen darf:
sudo adduser $USER i2c
Möglicherweise ist der aktuelle Benutzer ( pi ) allerdings schon Mitglied der Guppe i2c . Damit
obige Änderungen wirksam werden, starten wir den Π neu.
Danach lassen wir uns mit dem Befehl
lsmod
die geladenen Module anzeigen. Darunter sollte auch i2c_bcm2708 für den I2C Bus sein. Den oder
die I2C-Kanäle bekommen wir mit dem Befehl
ls -l /dev/i2c*
genannt. Hier sollte /dev/i2c-1 erscheinen. Nun wollen wir sehen, welche Geräte am I2C-Kanal 1
angeschlossen sind. Dies geschieht mit dem Befehl
i2cdetect -y 1
Die Option -y dient zur Unterdrückung eines Warnhinweises und einer Rückfrage, die 1 steht für die
Kanalnummer des I2C Busses. Wenn der LM75 mit dem I2C Bus verbunden wurde, sollte jetzt in
der mehrzeiligen Antwort des Programms eine 48 in einer mit 40 beginnenden Zeile enthalten sein.
Die 48 bedeutet, dass der LM75 am die Adresse 0x48 hat. Die Adresse wird als Hexadezimalzahl
angegeben, erkennbar am Präfix 0x . Hexadezimal 48 entspricht dezimal 4 · 16 + 8 = 72 .
62
An einem I2C Bus gibt es ein Kontrollgerät, Master genannt, an dem mehrere, davon kontrollierte
Geräte, die Slaves, angeschlossen werden können. Der Master kommuniziert mit einem bestimmten
Slave, indem er ihn über die Adresse anspricht. Die Adresse des LM75 können wir, innerhalb eines
vorgegebenen Wertebereichs, mit Hilfe der Pins 6 (A0), 7 (A1) und 8 (A2) des LM75 festlegen. Da
wir diese Pins mit Masse (GND) verbunden haben, ist die Adresse 0x48.
Eine Abfrage von Rohdaten (codierte Daten, wie sie vom LM75 geliefert werden) geschieht mit
i2cget -y 1 0x48 0x00 w
und wir erhalten eine Antwort, welche in codierter Form den Temperaturwert angibt, zum Beispiel
0xf718 . Diese Antwort besteht aus einer vierstelligen hexadezimalen Zahl (Präfix 0x). Die beiden
letzten Stellen, hier 18 , ergeben dezimal den ganzzahligen Anteil (ohne Nachkommastelle) des
Temperaturwerts, hier 1 · 16 + 8 = 24 . Für die aktuelle Temperatur T gilt also 24 °C ≤ T < 25 °C .
Eine vollständige Auswertung der Rohdaten vom LM75 wollen wir mit einem Python-Programm
vornehmen.
Python-Programm zur Temperaturmessung mit LM75
Für die Temperaturmessung mit oben gezeigtem Schaltkreis schreiben wir folgendes Python-Programm :
#!/usr/bin/python3
from subprocess import Popen, PIPE
from time import sleep
#
def T(wert):
# Funktion T wandelt Rohdaten in Temperaturwert und gibt ihn aus
grad = wert & 0xFF
# grad wird unteres Byte des Rohdatenwerts zugewiesen
gradnachkomma = wert >> 15
if (grad & 0x80) == 0x80:
# gradnachkomma wird oberes Byte zugewiesen
# (hoechstwertiges Bit = 1)
grad = -((~grad & 0xFF) + 1)
temp = grad + gradnachkomma * 0.5
=>
(grad ist negativ)
# bilde negatives Zweierkomplement von grad
# addiere Vor- und Nachkommatemperaturzahl
print(str(temp)+' Grad C') # schreibe Ausgabetext (Temperatur, 0.5 Grad genau)
#
print("\nTemperatur am LM75 Sensor, Abbruch durch Ctrl-C")
print("***********************************************")
#
try:
# Folgendes vor Druecken von Ctrl-C
while True:
# eine Endlosschleife liest Rohdaten ein und ruft Funktion T auf
p = Popen([ 'i2cget' , '-y' , '1' , '0x48' , '0x00' , 'w' ] , stdout=PIPE)
#
Methode Popen fuehrt Shell-Befehl i2cget aus und speichert die Antwort (String)
T( int(p.stdout.read(), 16) )
sleep(1)
# ruft Funktion T mit Rohdaten-Ganzzahl auf
# warte 1 Sekunde (Intervall zwischen zwei Temperatur-Ausgaben)
except KeyboardInterrupt:
# Folgendes nach Druecken von Ctrl-C (Programm-Abbruch)
print ("\n- Messung beendet -\n")
# Ende des Programms
63
Das Programm wird im Ordner p unter dem Namen lm75.py gespeichert. Wir öffnen eine Konsole,
bewegen uns in den Ordner p und geben folgende Konsolenbefehle ein:
chmod a+x lm75.py
./lm75.py
Die Ausführung kann durch Ctrl-C angehalten und durch ./lm75.py erneut gestartet werden.
Obiges Programm benutzt den Konsolenbefehl i2cget , um über den I2C Bus vom Temperatursensor
ein Datenwort (2 Byte) auszulesen. Im folgenden Programm wird die Klasse smbus verwendet:
#!/usr/bin/python3
import smbus
from time import sleep
#
def T(wert):
# Funktion T wandelt Rohdaten in Temperaturwert und gibt ihn aus
grad = wert & 0xFF
# grad wird unteres Byte des Rohdatenwerts zugewiesen
gradnachkomma = wert >> 15
if (grad & 0x80) == 0x80:
# gradnachkomma wird oberes Byte zugewiesen
# (hoechstwertiges Bit = 1)
grad = -((~grad & 0xFF) + 1)
temp = grad + gradnachkomma * 0.5
=>
(grad ist negativ)
# bilde negatives Zweierkomplement von grad
# addiere Vor- und Nachkommatemperaturzahl
print(str(temp)+' Grad C') # schreibe Ausgabetext (Temperatur, 0.5 Grad genau)
#
i2cbus=smbus.SMBus(1)
# Instanz i2cbus fuer den I2c Bus 1 bilden
#
print("\nTemperatur am LM75 Sensor, Abbruch durch Ctrl-C")
print("***********************************************")
#
try:
# Folgendes vor Druecken von Ctrl-C
while True:
# eine Endlosschleife liest Rohdaten ein und ruft Funktion T auf
daten = i2cbus.read_word_data(0x48, 0x00)
# hole Wort (2 Byte) vom Sensor
T(daten)
# ruft Funktion T mit Datenwort (= Rohdaten-Ganzzahl) auf
sleep(1)
# warte 1 Sekunde (Intervall zwischen zwei Temperatur-Ausgaben)
except KeyboardInterrupt:
# Folgendes nach Druecken von Ctrl-C (Programm-Abbruch)
print ("\n- Messung beendet -\n")
# Ende des Programms
Werden mehrere Geräte am I2C Bus angeschlossen, müssen sie unterschiedliche Adressen haben.
64
Aufgabe 6
AHG
SDA
2
SCL
3
OS
4
GND
+VS
8
A0
7
A1
6
A2
5
1
2
3
DIP-Schalter
10 k Ω
Temperatursensor
10 k Ω
GND
1
10 k Ω
3,3 V
GPIO 2
GPIO 3
LM75
Über Pins 6 bis 8 des LM75 kann man die
Bus-Adresse des Temperatursensors im
Wertebereich 0x48 (Pins 6 bis 8 alle auf
low) bis 0x4F (Pins 6 bis 8 auf high) einstellen. Erweitern Sie die Schaltung für
den LM75 um einen DIP-Schalter und drei
Pulldown-Widerstände (jeweils 10 kΩ)
gemäß des nebenstehenden Schaltplans.
Stellen Sie die Adresse 0x4A mit Hilfe des
DIP-Schalters ein und ändern Sie das
Programm entsprechend.
PulldownWiderstände
65
Experiment 5: A/D-Wandler am SPI Bus
Schaltung 6 (A/D-Wandler MCP3208) und das Treibermodul für den SPI Bus
Und noch einen Datenbus können wir mit dem Π kennenlernen, nämlich das Serial Peripheral Interface (SPI). Auch
hier gibt es ein Kontrollgerät (Master) und einen oder mehrere
davon kontrollierte Geräte (Slaves).
Bauteil-Liste
Steckbrett, Kabel, Drahtbrücken
A/D-Wandler MCP3208,
Potentiometer: ≈ 10 kΩ
sowie, falls vorhanden:
Voltmeter ( Bereich 0 - 3,3 V )
Keramikkondensator: 0,1 - 1 μF
Die Auswahl des Slaves geschieht beim SPI Bus, indem eine
besondere Datenleitung zu einem Slave, chip select oder kurz
CS (machmal auch slave select = SS genannt), durch den
Master von high (inaktiv) auf low (aktiv) gesetzt wird. Da
low, nicht high, einen Slave aktiviert, wird CS oft auch mit einem Überstrich (als Zeichen der
Negation) geschrieben.
Der Datenaustausch zwischen Master und Slave vollzieht sich Bit für Bit im Takt, der auf der SCLK
Signalleitung vom Master als Rechteckschwingung vorgegeben wird, also synchron.
Potentiometer
AHG
1
CH0
2
CH1
3
4
CH3
CLK
13
5
CH4
DOUT
12
6
CH5
7
CH6
8
VDD
16
VREF
15
CH2 AGND
14
MCP3208
Außerdem braucht der MCP3208 (Slave)
vom Π (Master) zumindest eine
Masseverbindung (GND) und eine
Versorgungsspannung VDD, die
allgemein typischerweise zwischen 2,7
und 5,5 V liegen könnte, in unserer
Schaltung (siehe Bild rechts) aber
aufgrund der Vorgabe des GPIOSignalpegels 3,3 V betragen muss.
10 k Ω
Es werden, gleichzeitig auf zwei Leitungen, Daten vom Master zum Slave (MOSI, Master Out
Slave In) und Daten vom Slave zum Master gesendet (MISO, Master In Slave Out). Diese
Betriebsart nennt man Vollduplex (full-duplex).
DIN
CS
CH7 DGND
11
10
9
GND
GPIO 8
GPIO 10
GPIO 9
GPIO 11
3,3 V
Insgesamt hat der MCP3208 sechzehn
Pins. Pins 1 bis 8 stellen die Eingänge
für die messenden Analogspannungen
dar und werden mit CH0 bis CH7
bezeichnet. Die Verbindung von MCP3208 und Π erfolgt gemäß Schaltplan und folgender Tabelle.
MCP
3208
Π
SPI
Pin 9
DGND
Pin 10
CS
Pin 11
DIN
Pin 12
DOUT
Pin 13
CLK
Pin 14
AGND
Pin 15
VREF
Pin 16
VDD
P1, Pin 20 P1, Pin 24 P1, Pin 19 P1, Pin 21 P1, Pin 23 P1, Pin 20 P1, Pin 17 P1, Pin 17
GND
GPIO 8 GPIO 10 GPIO 9 GPIO 11
GND
3,3 V
3,3 V
CS
MOSI
MISO
SCLK
Pin 9 des MCP3208 heißt DGND (digital ground) und erhält die Masseverbindung vom Π (GND).
66
Die analogen Eingangsspannungen werden bezüglich Pin 14 des MCP3208 (AGND, analog
ground) gemessen, den wir in unserer Schaltung mit Pin 9 (DGND) verbunden haben. Die obere
Grenze des Messbereichs wird durch Pin 15 des MCP3208 (VREF) festgelegt, den wir mit Pin 16
(VDD) verbunden haben. Diese Pins (15 und 16) erhalten die Versorgungsspannung vom Π (3,3 V).
Pins 10 (CS mit Überstrich) und 13 des MCP3208 (CLK) werden mit GPIO 8, welcher das CS
Signal ausgibt, und GPIO 11 des Π, welcher das SCLK Signal ausgibt, verbunden. Pins 11 (DIN)
und 12 des MCP3208 (DOUT) werden mit GPIO 10 des Π, welcher das MOSI Signal ausgibt,
beziehungsweise GPIO 9, welcher das MISO Signal ausgibt, verbunden.
Um Störungen und Rauschen der Versorgungspannung VDD zu minimieren, sollte zwischen Pins 14
(AGND) und 16 (VDD) des MCP3208 ein Abblockkondensator von 1 µF gesetzt werden (im minimalistischen Schaltplan oben nicht eingezeichnet, denn es geht - mit mehr Rauschen - auch ohne
ihn). Er wird möglichst nah an den Pins platziert. Geeignet sind insbesondere Keramikkondensatoren, während zum Beispiel gewickelte Kondensatoren wegen ihrer Induktivität weniger geeignet
sind. Da 1 µF Keramikkondensatoren selten sind, kann man einen 100 nF Keramikkondensator nah
an den Pins, und parallel dazu einen 1 bis 10 µF (wenn möglich, flachen, nicht gewickelten) Folienkondensator, setzen (keinen Elektrolytkondensator).
Zur Erzeugung einer veränderlichen analogen Eingangsspannung
wird ein Potentiometer (etwa 10 kΩ) als Spannungsteiler zwischen
Masse (GND) und 3,3 V geschaltet und die Teilspannung vom
Mittelabgriff des Potentiometers auf einen Eingang des MCP3208
gelegt. Hierfür wurde willkürlich Pin 3 des MCP3208 (CH2) gewählt. Die Analogspannung kann mit einem Voltmeter angezeigt
werden. Da die Schaltung nur die Funktionsweise des AD-Wandlers
und seine Steuerung über den SPI Bus zeigen soll, können wir hier
auf weitere Bauelemente verzichten.
Für den SPI Bus braucht man das Treibermodul (spi_bcm2835 oder ähnlich), das über den
Gerätebaum zur Verfügung gestellt wird, wenn bei der Konfiguration des Π mit Raspberry Pi
Configuration oder raspi-config die Option zur Aktivierung und Laden des SPI interface gewählt
wurde (siehe oben, Abschnitt Boot, Betriebssystem und Konfiguration). Man kann dies prüfen,
indem man in der Konsole den Befehl
lsmod | grep spi
eingibt. Der Befehl lsmod gibt eine Liste aller geladenen Module aus. Der Ausgabedatenstrom kann
mithilfe des |-Zeichens (das eine Pipe erzeugt; es ist meistens auf der Tastatur vorhanden) als
Eingabe für den Befehl grep spi verwendet werden, der alle Zeilen ausgibt, welche die Zeichenkette
spi enthalten. Im Ergebnis sollte eine Zeile am Bildschirm ausgegeben werden, die mit spi_bcm
beginnt. Geschieht dies nicht, muss das Modul noch in den Gerätebaum eingefügt werden, indem
man Raspberry Pi Configuration nochmals startet und nun die Option SPI: Enabled wählt (siehe
oben, Abschnitt Boot, Betriebssystem und Konfiguration).
67
Mit
sudo apt-get update
führen wir ein Update durch (siehe oben, Abschnitt Kommandozeile (Konsole) und Paketverwaltung). Wir wollen nun das Pythonmodul spidev installieren. Dafür wird das Paket python3-dev
gebraucht; falls es fehlt, wird es jetzt installiert (siehe oben, Abschnitt Editor, Browser und weitere
Programme). In einer Konsole führen wir dann folgende Befehle aus:
git clone git://github.com/doceme/py-spidev
cd py-spidev
sudo python3 setup.py install
Damit sollte das Modul spidev in Python3 zur Verfügung stehen.
Python-Programm zur Spannungsmessung mit MCP3208
Zur Demonstration der Funktionsfähigkeit unserer Schaltung messen wir mit folgendem PythonProgramm die Spannung am Eingang CH2 und geben das Ergebnis einmal pro Sekunde auf dem
Bildschim aus. Das Programm kann ohne Root-Rechte ausgeführt werden. Drücken von Ctrl-C
beendet das Programm.
#!/usr/bin/python3
import spidev
from time import sleep
# Variablendeklaration und Oeffung des SPI-Busses
SPI_Bus = 0
# Auswahl des SPI_Busses, hier nur 0 moeglich
CS = 0
# Slave, der mit CS-Signal angesprochen wird
f = 20000
# Frequenz in Hz fuer das SCLK-Signal (clock)
Uref = 3.3
# Referenzspannung in V an Pin 15 des MCP3208
Uiv = Uref / 4096
# Spannungsintervall digitaler Wert-Einheiten
Kanal = 2
# Kanalnummer (Bereich 0 - 7) des AD-Wandlers
Pausendauer = 1
# Pausendauer zwischen Messsungen in Sekunden
spi = spidev.SpiDev() # Erzeugung eines SpiDev-Objekts namens spi
spi.open(SPI_Bus, CS) # Oeffnung von SPI-Bus SPI_Bus fuer Slave CS
spi.max_speed_hz = f
# Vorgabe der maximalen SPI-Bus-Taktfrequenz
try: # Folgendes normalerweise, ohne Druecken von Ctrl-C
# Schleife zur Spannungsmessung und Ausgabe des Wertes
while True: # Endlosschleife
adc = spi.xfer2([6 + (Kanal >> 2), Kanal << 6, 0]) # Messung
# gleichzeitig je 3 Bytes senden (MOSI) und empfangen (MISO)
Wert = ((adc[1]&15) << 8) + adc[2] # 12 Bit zur Zahl wandeln
U = Uiv * Wert + Uiv/2
# digitaler Wert -> analoge Spannung
print("Kanal {0:1d}: Spannung = {1:4.2f} V".format(Kanal,U))
sleep(Pausendauer)
except KeyboardInterrupt:
# Pause zwischen zwei Messungen
# Folgendes nach Druecken von Ctrl-C
68
spi.close()
# trennt das SpiDev-Objekt spi vom SPI-Bus
print("\n- Messung beendet -\n")
# Ende des Programms
Schauen wir uns den Programmcode der Reihe nach an: Nach Einbindung der notwendigen Module
(spidev, time) werden zunächst einige Werte in Variablen gespeichert, auf die wir später zurückgreifen. Grundsätzlich wäre es möglich, mehrere SPI Busse am Π zu betreiben, die (beginnend mit
0) durchnummeriert werden. Hier gibt es nur den SPI Bus mit der Nummer 0, dessen Nutzung in
der Zeile SPI_Bus = 0 festgelegt wird.
Der SPI Bus 0 könnte verschiedene Slaves über jeweils eine CS Datenleitung ansprechen. Hier wird
nur der Slave MCP3208 über die erste CS Datenleitung mit der Nummer 0 angesprochen, was in
der Zeile CS = 0 festgelegt wird.
Der SPI Bus kann mit unterschiedlichen Taktfrequenzen betrieben werden und die meisten der
angeschlossenen Geräte (Slaves) können mit unterschiedlichen, auch wechselnden Taktfrequenzen
(und sogar Änderungen im Tastgrad) arbeiten. Bei dem hier betrachteten AD-Wandler wird der
Frequenzbereich beschränkt durch die Wandlungdauer, die 12 Takte umfasst. Die höchste mögliche
Frequenz liegt unter optimalen Bedingungen bei 2 MHz, so dass maximal 100 000 Messwerte / s
erfasst werden können, wenn der Master dies auch schafft. Es gibt aber auch eine Höchstdauer für
die sichere Zwischenspeicherung des analogen Spannungswerts in einem internen Kondensator
während der Wandlung von etwa 1,2 ms unter ungünstigen Bedingungen. Aus letzterem ergibt sich
eine Frequenz von mindestens 10 kHz. Da in obigem Programm keine besonders schnelle
Datenerfassung notwendig ist, wird die maximale Taktfrequenz in Hz (siehe unten) mit f =
20000 vorgegeben. Man kann die Taktfrequenz auf der SCLK Signalleitung mit Hilfe eines
Oszilloskops sichtbar machen.
Der Spannungsbereich, in dem vom MCP3208 gemessen und gewandelt wird, liegt zwischen 0V
und VREF. Die Referenzspannung VREF kann höchstens so groß wie die Versorgungsspannung VDD
sein und beträgt in obiger Schaltung 3,3 V. Dies wird mit der Zeile Uref = 3.3 angegeben.
Der MCP3208 ist ein 12-Bit Wandler. Der Messspannungsbereich wird in 2 12 = 4096 gleich lange
Einzelintervalle zerlegt, die von 0 bis 4095 durchnummeriert werden. Die Länge eines Einzelintervalls beträgt VREF / 4096 . Dieser Wert wird mit der Zeile Uiv = Uref / 4096 in der
Variablen Uiv gespeichert.
Die acht Eingangskanäle sind von 0 bis 7 nummeriert. Mit der Zeile Kanal = 2 wird der
Eingangskanal 2 oder CH2 festgelegt.
Da wir eine Messung pro Sekunde durchführen wollen, wird mit der Zeile Pausendauer = 1
ein Wert von 1 für die Dauer zwischen Messungen in Sekunden, festgelegt.
Das Modul spidev enthält eine Klasse SpiDev und mit der Zeile spi = spidev.SpiDev()
wird eine Instanz namens spi erzeugt, mit der man einen SPI Bus ansteuern kann.
In der Zeile spi.open(SPI_Bus, CS) wird mit der Methode open für die Instanz spi ein
bestimmter SPI Bus geöffnet und der anzusprechende Slave angegeben.
69
Die gewünschte maximale Taktfrequenz wird in der Zeile spi.max_speed_hz = f festgelegt. Die tatsächliche Taktfrequenz liegt nicht über dem angegebenen Wert, kann aber darunter
liegen, weil a) der SPI Bus die Frequenz nur schrittweise ändern kann und b) der Prozessor zu
langsam für die gewünschte maximale Taktfrequenz sein könnte.
Um das Programm mit Ctrl-C abbrechen und dann noch einige "Aufräumarbeiten" durchführen zu
können, werden die Zeilen try: und except KeyboardInterrupt: verwendet, ähnlich
wie in früheren Pythonprogrammen (siehe oben).
Messung und Anzeige der Analogspannung geschehen im Anweisungsblock einer Endlosschleife,
die mit der Zeile while True: eingeleitet wird.
In der Zeile adc = spi.xfer2([6 + (Kanal >> 2), Kanal << 6, 0]) wird die
Methode xfer2 des spi Objekts mit einem Argument aufgerufen, das aus einer dreiteiligen Liste
besteht, und der Rückgabewert, der ebenfalls aus einer dreiteiligen Liste besteht, wird in der
Variablen adc gespeichert.
xfer2 sorgt für die Datenübertragung zwischen Master und Slave. Sie kann nur ganzzahlige Vielfache eines Bytes vom Master zum Slave (MOSI) senden und liest gleichzeitig dieselbe Anzahl von
Bytes von der anderen Datenleitung (MISO). Da für einen Messwert mindestens 19 zusammenhängende Bitpaare (Paar bedeutet: 1 Bit auf MOSI und 1 Bit auf MISO) übertragen werden müssen
(siehe unten), sind drei Byte-Paare (24 Bitpaare) notwendig, denn zwei Byte-Paare (16 Bitpaare)
wären zu wenig. Daher enthalten beide Listen der Methode xfer (Argument und Rückgabewert)
jeweils drei Byte.
19 Bitpaare für eine Messwertabfrage
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 15 17 18 19
Befehl vom Master an den Slave
S UKKK
MOSI, 1. Byte
0 0 0 0 0 1 1 0
1 0 0 0 0 0 0 0
MOSI, 2. Byte
0 0 0 0 0 0 0 0
MOSI, 3. Byte
MISO, 1. Byte
1 1 1 1
MISO 2. Byte
1 1 1 1 1 1 1 1
MISO, 3. Byte
Datenwort, das den Messwert darstellt
19 Bitpaare für eine Messwertabfrage
1 1 1 1 1 1 1 1 1 1 1 1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 15 17 18 19
Die 19 Bitpaare für eine Messwertabfrage bestehen aus einem Befehl vom Master an den Slave (5
Bits auf der MOSI / DIN Leitung), einer Pause zum Einlesen eines Messwerts (2 Bits) und dem
70
Datenwort, das den Messwert darstellt, welches vom Slave zum Master gesendet wird (12 Bits auf
der DOUT / MISO Leitung). Die 5 Bits des Befehls bestehen aus einem Startbit, S (1 = high), einem
Bit zur Festlegung der Messart, U (1 = high für unipolar oder 0 = low für bipolar, hier: 1) und drei
Bits zur Angabe des Messkanals, K K K (hier: binär 010 = dezimal 2).Zur Auffüllung auf 3 BytePaare werden bei der Messwertabfrage den 19 Bits auf der MOSI Leitung fünf Bits vorangestellt,
die nur low = 0 enthalten. Die Abfolge der Bits auf den MOSI und MISO Leitungen wird in obigem
Diagramm veranschaulicht.
Die ersten 12 Bits auf der MISO Leitung (welche dem 12 Bit-Datenwort vorausgehen) sind
unwichtig (werden nicht ausgewertet) und wurden daher im Diagramm nicht angegeben. Das
Datenwort besteht in diesem Beispiel aus der Bitfolge 111111111111 , was dezimal der Zahl
4095 entspricht.
Die Methode xfer2 erwartet als Argument eine Liste von drei Bytes.
Das erste Byte (8 Bits) bekommt an der 8. Stelle (LSB) das höchstwertige Bit der Kanalnummer.
Dies geschieht, indem von den drei Bits, welche die Kanalnummer (dezimal zwischen 0 und 7)
repräsentieren (hier: 010), mit der Operation Kanal >> 2 die beiden letzten Bits entfernt
werden und das erste Bit (hier: 0) an die niederwertwertigste Stelle rückt. Dann werden durch
Addition von 6 = 4 + 2 die 6. Stelle (dezimal 4) und die 7. Stelle (dezimal 2) jeweis mit einer 1
besetzt, so dass hier das Byte 00000110 entsteht.
Das zweite Byte bekommt an der 1. Stelle (MSB) und der 2. Stelle das zweite (hier: 1) beziehungsweise dritte Bit der Kanalnummer (hier: 0). Dies geschieht, indem von den drei Bits, welche die
Kanalnummer repräsentieren (hier: 010), mit der Operation Kanal << 6 das erste Bit entfernt
wird , das zweite Bit um sechs Stellen nach links an die 1. Stelle des Bytes, und das dritte Bit der
Kanalnummer um sechs Stellen nach links an die 2. Stelle des Bytes gerückt werden. So wird hier
das Byte 10000000 gebildet.
Das dritte Byte wird Null gesetzt, dies entspricht 00000000 .
Mit dem oben beschriebenen (durch drei Bytes repräsentierten) Befehl gibt die Methode xfer2 als
Rückgabewert eine Liste von drei Bytes (namens adc), die den Messwert enthalten.
In der Zeile Wert = ((adc[1]&15) << 8) + adc[2] wird aus der Liste adc die Variable
Wert gebildet, welche das Einzelintervall des Messspannungsbereichs des 12-Bit Wandlers bezeichnet (siehe oben). Es gilt daher 0 ≤ Wert ≤ 4095 .
Das erste Byte der zurückgegebenen Liste ( adc[0] ) wird verworfen.
Vom zweiten Byte ( adc[1] ) werden, mithilfe der Operation adc[1]&15 , die 4 niederwertigsten
Bits genommen (dezimal 15 entspricht binär 00001111 und der Operator & erzeugt eine bitweise
UND-Verknüpfung). Diese werden mithilfe der Operation << 8 , um 8 Stellen nach links
verschoben, so dass sie die ersten 4 Stellen einer zwölfstelligen Binärzahl darstellen.
Zu den ersten 4 Stellen der zwölfstelligen Binärzahl wird das dritte Byte ( adc[2] ) addiert (letzte 8
71
Stellen der zwölfstelligen Binärzahl), so dass die zwölfstelligen Binärzahl fertig ist und ihr Wert der
Variablen Wert zugewiesen werden kann.
In der Zeile U = Uiv * Wert + Uiv/2 wird aus der Variablen Wert ein analoger Spannungswert (Messwert in V) berechnet.
Der zu einem Einzelintervall Wert gehörige analoge Spannungswert liegt zwischen Wert · (VREF /
4096) und ( Wert + 1 ) · (VREF / 4096) und wir ordnen dem Einzelintervall Wert daher den Mittelwert ( Wert + Wert + 1 ) · (VREF / 4096) / 2 = Wert · (VREF / 4096) + (VREF / 4096) / 2 zu. Dies geschieht in der Zeile U = Uiv * Wert + Uiv/2 und der so gefundene analoge Spannungswert (in V) wird in der Variablen U gespeichert.
Mit print("Kanal {0:1d}: Spannung = {1:4.2f} V".format(Kanal,U))
werden die Werte der Variablen Kanal (einstellige Ganzzahl, d) und U (vierstellige Gleitkommazahl, f, mit zwei Nachkommastellen) formatiert als Teils einer Zeichenkette auf dem Bildschirm
ausgegeben. Formatnummer 0 gibt eine Ganzzahl (d) einstellig aus; Formatnummer 1 gibt eine
Gleitkommazahl (rationale Zahl, f) mit vier Zeichen aus, wovon das erste Zeichen die Vorkommazahl, das zweite den Dezimalpunkt und das dritte und vierte Zeichen zwei Nachkommastellen zeigen.
Die Zeile sleep(Pausendauer) ruft die Methode sleep der Klasse time auf, um (zwischen
zwei Messungen) die Programmausführung für Pausendauer Sekunden anzuhalten.
Nach Drücken von Ctrl-C wird mit der Zeile spi.close() der, bisher von der Instanz spi belegte, SPI Bus freigegeben.
In der letzten Zeile print("\n- Messung beendet -\n") wird eine Meldung an den
Nutzer ausgegeben.
72
Aufgabe 7
Ergänzen Sie das oben angegebene Python-Programm zur Spannungsmessung mit einer graphischen Benutzeroberfläche (GUI). Als Layout-Vorlage kann wieder das oben (im Abschnitt GUI mit
Python, Modul Tkinter) beschriebene GUI dienen. Kleine Anpassungen sind natürlich notwendig.
Das Messergebnis soll im Textfeld (label) in folgendem Format angezeigt werden: x: y.yy V ,
wobei x die einstellige Kanalnummer des Wandlers angibt und y.yy den Spannungswert (in Volt)
als Gleitkommazahl mit einer Stelle vor und zwei Stellen nach dem Dezimaltrennzeichen. Die drei
Buttons (Schaltflächen) b1, b2 und b3 sollen mit den Zeichenketten "Kanal +", "Kanal -" und
"Ende" beschriftet werden.
Nach Programmstart soll die Nummer des Eingangskanals aus einer Datei namens mcp3208.dat
gelesen werden. (Falls die Datei noch nicht existiert, wird sie erzeugt und eine 0 hineingeschrieben.) Dann soll, automatisch fortlaufend, jede Sekunde ein Messwert genommen werden.
Nach Mausklick auf den Button b1 ("Kanal +") soll die Kanalnummer um 1 erhöht werden, wenn
sie 7 nicht überschreitet. Nach Klick auf den Button b2 ("Kanal -") soll die Kanalnummer um 1
erniedrigt werden, wenn sie 0 nicht unterschreitet. Nach Klick auf Button b3 ("Ende") soll das
Programm ordentlich (mit Freigabe des SPI Busses, siehe oben) beendet werden.
73
Experiment 6: Textausgabe auf LCD-Anzeigemodul
Schaltung 7 (LCD-Modul C0802-04)
Über die GPIOs ist auch eine Datenausgabe in Form von
Zeichenketten auf einen kleinen Bildschirm (LC-Display)
möglich. Die Daten werden an einen zum Display gehörigen
elektronischen Schaltkreis, den Controller, übergeben, der die
Darstellung steuert. Das Datenformat, in dem die Zeichen
übertragen werden müssen, wird vom verwendeten Controller
bestimmt.
Hier wird das LCD-Modul C0802-04 mit einem Controller vom Typ HD47780 verwendet (siehe
Bild rechts), weil es einfach und billig (< 1 € pro Stück) erhältlich war. Es kann auf einer Anzeigefläche von 44 mm · 23 mm zwei Zeilen mit jeweils 8 Zeichen (5 mm · 3 mm) anzeigen. Bei der Ansteuerung muss ein 4-Bit-Datenbus verwendet werden (obwohl der Controller auch 8-Bit-Worte
verarbeiten könnte), weil nur vier Datenleitungen herausgeführt sind.
Nachteilig ist beim LCD-Modul C0802-04 der für Bastler schwierige
Anschluss über das 10-polige Folien-Flachbandkabel des Displays,
welches ein enges Rastermaß von 1 mm aufweist. Man kann mit einem
scharfen Messer das Kabelende auftrennen und die einzelnen, am Ende
versilberten Leiter mit einem zweiten Kabel verbinden, das zu einer
Steckplatine führt (und dort, wie bei Experiment 1 beschrieben, angeschlossen wird).14 Die Verbindung von den GPIOs zur Steckplatine erfolgt über ein Flachbandkabel; ein Ende hat eine Pfostenbuchse
(2x13polig beim Π_1B, 2x20polig beim Π_2B) für die Stiftleiste P1;
das andere Ende führt zur Steckplatine (siehe Bild rechts).
Ein Problem beim Anschluss von Displays, deren Controller mit einer Versorgungsspannung VDD
von 5 V betrieben wird, ist die kleine Signalspannung der GPIOs, die ja nur 0 V (Signal low) oder
3,3 V (Signal high) abgeben können. Das Datenblatt des Controllers vom Typ HD47780 fordert eine
Spannung (Logikpegel) zwischen 0,7 · VDD und VDD für das Signal high und die 3,3 V = 0,66 · VDD
der GPIOs sind daher eigentlich zu wenig. Glücklicherweise funktionieren jedoch die meisten 5 VCMOS-Logikschaltungen auch noch mit einer Eingangssignalhöhe von nur 3,3 V und wir gehen im
folgenden davon aus, das dies auch hier der Fall ist.
Im ungünstigen Fall, wenn die 3,3 V nicht reichen, muss man die Spannung für das Signal high mit
einer Schaltung (für jede Leitung) von 3,3 V auf 5 V anheben. Das ist mit einem IC (74HCT241,
Alternative: 2 ICs 74HCT125) möglich, soll hier aber nicht näher behandelt werden. Beschreibungen verschiedener Transistor-Anpassschaltungen findet man im Internet.
14 Zu diesem Flachkabel passende FFC/FPC-Steckverbinder (Buchsen) sind nicht bei jedem Bauteilehändler erhältlich, können aber eventuell aus verschrotteten Geräten (zum Beispiel Videorekorder) ausgebaut werden. Leider
haben sie oft eine Stiftleiste im engen Rastermaß von 1 mm, so dass es schwierig bleibt, ein Kabel anzulöten.
74
Das LCD-Modul C0802-04 wird mit insgesamt zehn Leitungen angeschlossen, davon je eine zur
Masse, (GND) zur Spannungsversorgung (VDD) und zu einer Hilfsspannung (VKontrast , die sogenannte Kontrastspannung); hinzu kommen drei Steuerleitungen (RS, RW und E) und vier Datenleitungen (D4, D5, D6 und D7). Jede Leitung geht von einem Pin auf der Platine aus. Die Reihenfolge der 10 Pins ist auf der Platine des Displays angegeben. Die Pins sind wie folgt belegt:
Pin
1
2
3
4
5
6
7
8
9
10
GND
VDD
VKontrast
RS
RW
E
D4
D5
D6
D7
Pin 1 des Displays (GND) wird mit einem Masse-Pin von P1 verbunden, also mit Pin 6, 9, 14, 20
oder 25 (die Pin-Belegung der Stiftleiste P1 wurde oben im Abschnitt Digitale Anschlusspunkte:
GPIOs beschrieben).
Pin 2 des Displays (VDD) erhält die Versorgungsspannung für das Display, 5 V, und wird mit Pin 2
oder 4 von P1 verbunden. Es sei daran erinnert, dass die GPIOs als Eingänge eine Spannung von 5
V nicht verkraften.
Pin 3 des Displays (VKontrast) steuert den
Kontrast der Anzeige über eine
geeignete Spannung, die zwischen 0
und 5 V liegt. Diese Spannung kann mit
einem 10 kΩ - Potentiometer, eingestellt
werden, dessen äußere Anschlüsse mit
0 V (GND) und 5 V verbunden sind,
und dessen Mittelabgriff an Pin 3 des
Displays liegt. (Da die beste Kontrastspannung meistens näher bei 0 V als bei
5 V liegt, kann ein Potentiometeranschluss statt an 5 V auch an 3,3 V
angeschlossen werden.)
Pin 4 des Displays (RS) teilt dem
Display mit, ob Daten (Signal high)
oder ein Befehl (Signal low) gesendet
wird. Er wird mit einem GPIO, der als
Ausgang benutzt wird, zum Beispiel
GPIO 22 (Pin 15 von P1), verbunden.
LC-Display-Modul C0802-04
GND V
VKtr RS RW E D4 D5 D6 D7
DD
1 2 3 4 5 6 7 8 9 10
Pin 13
von P1
GPIO 27
Pin 22
von P1
GPIO 25
Pin 4
von P1
5V
Pin 11
von P1
GPIO 17
10
kΩ
Pin 5 des Displays (RW) teilt dem
Display mit, ob Daten gelesen (R,
Signal high) oder geschrieben (W,
Signal low) werden sollen. Da die
Pin 18
von P1
GPIO 24
Pin 16
Pin 15
von P1
GPIO 22
von P1
GPIO 23
Pin 6
von P1
GND
75
GPIOs keine 5 V erhalten dürfen (siehe oben), wird hier nur geschrieben und Pin 5 des Displays
daher mit einem Masse-Pin von P1 verbunden.
Pin 6 des Displays (E) wird genau dann von low auf high gesetzt, wenn an den anderen Anschlüssen
die Signalpegel anliegen und ausgelesen und verarbeitet werden sollen. Er wird auch mit einem
GPIO, der als Ausgang benutzt wird, zum Beispiel GPIO 23 (Pin 16 von P1), verbunden. Vor dem
Anlegen neuer Signale an die Pins des Displays muss E wieder auf low gesetzt werden.
Pin 7 - 10 des Displays (D4, D5, D6, D7) sind die Anschlüsse, welche die Daten (oder Befehle)
übergeben. Sie werden ebenfalls mit jeweils einem GPIO, der als Ausgang benutzt wird, verbunden,
zum Beispiel mit GPIO 24 (Pin 18 von P1), GPIO 17 (Pin 11 von P1), GPIO 25 (Pin 22 von P1)
und GPIO 27 (Pin 13 von P1).
Mit den oben genannten Zuordnungen müssen vom Programm folgende sechs GPIOs im
Schreibmodus angesprochen werden, um die Anschlüsse des Displays anzusteuern:
Anschlüsse
RS
E
D4
D5
D6
D7
GPIOs
GPIO 22
GPIO 23
GPIO 24
GPIO 17
GPIO 25
GPIO 27
76
Controller vom Typ HD47780
Controller vom Typ HD47780 können auf zwei Arten (Modi) arbeiten, nämlich im 8-Bit-Modus
oder im 4-Bit-Modus. Im 8-Bit-Modus werden Daten über 8 digitale Leitungen ein- und ausgegeben, im 4-Bit-Modus über 4 digitale Leitungen. Hinzu kommen in beiden Modi drei digitale
Steuerleitungen, nämlich RS (Register Select), R/W (Read/Write) und E (Enable), sowie je eine
Leitung für Signalmasse, Versorgungsspannung ( 5 V ) und die Kontrastspannung (siehe oben).
Die digitalen Datenleitungen haben einen der beiden Zustände low (0) oder high (1). Über die
Leitungen kann man grundsätzlich entweder Daten zum Display senden (schreiben) oder vom
Display holen (lesen). Da wir jedoch die Steuerleitung R/W auf Masse (low) gelegt haben, können
wir nur zum Display senden, also schreiben.
Daten werden über alle Steuer- und Datenleitungen (parallel) gleichzeitig (synchron) während eines
bestimmten Zeitraums (Takt) übertragen. Vor der Übertragung von Daten an den Controller wird die
Steuerleitung E auf low gesetzt, dann werden die anderen Steuerleitungen (hier: RS) und
Datenleitungen (D0 - D7 im 8-Bit-Modus, D4 - D7 im 4-Bit-Modus) entsprechend der Daten
(Befehle oder Zeichen) auf low oder high gesetzt, und danach wird die Steuerleitung E auf high
gesetzt. Sobald E auf high liegt, beginnt der Controller mit der Verarbeitung der Daten. Nach dem
Takt wird die Steuerleitung E wieder auf low gesetzt, bevor – im nächsten Takt – an die anderen
Steuer- und Datenleitungen neue Daten gesandt werden.
Im 8-Bit-Modus wird in einem Takt ein Byte (8 Bits) übertragen. Im 4-Bit-Modus wird in einem
Takt ein halbes Byte oder Nibble (4 Bits) übertragen. Um im 4-Bit-Modus die gleiche Datenmenge
wie im 8-Bit-Modus zu übertragen, werden für ein Byte zwei Nibbles übertragen und dafür braucht
man zwei Takte. Im ersten Takt wird das höherwertige Nibble (die vier oberen Bits), im zweiten
Takt das niederwertige Nibble (die vier unteren Bits) übertragen. Die Übertragung im 4-Bit-Modus
ist daher langsamer als im 8-Bit-Modus, aber man spart vier Leitungen ein.
Der Controller des Displays braucht einige Zeit, um einen eingegangenen Befehl zu verarbeiten und
auszuführen. Bevor die Ausführung abgeschlossen ist, darf kein neuer Befehl gegeben werden. Ob
eine Befehl abgeschlossen wurde, könnte man vom Controller abfragen. Da wir aber keine Daten
vom Controller lesen wollen, sondern nur Daten schreiben, müssen wir so lange warten, bis die
Befehle spätestens abgearbeitet sind. Für die meisten Befehle braucht der Controller höchstens 40
μs. Die Befehle "Clear Display" und "Display & Cursor Home" brauchen aber länger, bis zu 1,7
ms. Im 4-Bit-Modus muss man auch nach Übertragung des höherwertigen Nibbles (im ersten Takt)
einige μs warten, bevor das niederwertige Nibble (im zweiten Takt) gesendet werden darf. Da wir es
beim Beschreiben des Displays nicht eilig haben, warten wir einfach stets 3 ms nach der Übertragung eines Nibbles. Wird können dann sicher sein, dass die Ausführung auch der langsameren
Befehle abgeschlossen wurde, bevor ein neuer gesendet wird.
77
Die Funktionsweise von Controller und Display wird durch binäre Variablen, sogenannte Steuerbits,
festgelegt, welche in einem internen Speicher des Controllers abgelegt sind und vom Benutzer über
Steuerbefehle verändert werden können.
Nach dem Einschalten des Displays durch Anlegen der 5 V Versorgungsspannung setzt der Controller Startwerte für die Steuerbits (Ist-Werte in unten stehender Tabelle). Dies dauert etwa 15 m s.
Da der Controller verschiedene Displays steuern könnte, passen einige dieser Startwerte oft nicht
zum Display, mit dem er verbaut ist, insbesondere nicht zum hier verwendeten des LCD-Moduls
C0802-04. Daher müssen müssen einige Startwerte des Controllers neu und richtig gesetzt werden.
Da wir zum Zeitpunkt der Nutzung des Displays nicht sicher sein können, ob die Startwerte noch
gelten (oder durch Signale auf den GPIOs verändert wurden), setzen wir vorsichtshalber alle
Steuerbits auf die richtigen Werte (Soll-Werte in unten stehender Tabelle). Dies ist Aufgabe der
Initialisierung, bevor Zeichen in das Display geschrieben werden.
Startwert
Binäre Variable ( Bit ) zur
Steuerung des Displays
Name des
Steuerbits
Ist
Soll
Bedeutung des
Sollwerts
4- oder 8-Bit Interface
DL
high
low
4-Bit Interface
1- oder 2/4-zeilige Anzeige
N
low
high
2/4-zeilige Anzeige
5×8- oder 5x10-Zeichenmatrix
F
low
low
5x8-Zeichenmatrix
Anzeige sichtbar oder nicht
D
low
high
Anzeige sichtbar
Cursor sichtbar oder nicht
C
low
low
Cursor nicht sichtbar
Cursor als Unterstrich oder Block
B
low
low
Cursor als Unterstrich
Cursor nach links oder rechts
I/D
high
high
Cursor nach rechts
Zeichenanzeige fest oder nicht
S
low
low
Zeichenanzeige fest
Bevor wir die Steuerbefehle für das Schreiben einer Zeichenkette kennenlernen, betrachten wir die
Codierung der Zeichen. Der Controller kann eine bestimmte Zeichenmenge darstellen. Jedes
Zeichen wird mit einem Byte (zwei Nibbles) codiert. Die folgende Tabelle zeigt eine Teilmenge, bei
der die Codierung dem 8-Bit ASCII Zeichensatz entspricht.
78
Zeichen
Codierung
vier obere Bits
vier untere Bits
Dez.
Hex.
DB7
DB6
DB5
DB4
DB3
DB2
DB1
DB0
32
0x20
low
low
high
low
low
low
low
low
!
33
0x21
low
low
high
low
low
low
low
high
"
34
0x22
low
low
high
low
low
low
high
low
,
44
0x2C
low
low
high
low
high
high
low
low
.
46
0x2E
low
low
high
low
high
high
high
low
/
47
0x2F
low
low
high
low
high
high
high
high
:
58
0x3A
low
low
high
high
high
low
high
low
?
63
0x3F
low
low
high
high
high
high
high
high
A
65
0x41
low
high
low
low
low
low
low
high
B
66
0x42
low
high
low
low
low
low
high
low
C
67
0x43
low
high
low
low
low
low
high
high
D
68
0x44
low
high
low
low
low
high
low
low
E
69
0x45
low
high
low
low
low
high
low
high
F
70
0x46
low
high
low
low
low
high
high
low
G
71
0x47
low
high
low
low
low
high
high
high
H
72
0x48
low
high
low
low
high
low
low
low
I
73
0x49
low
high
low
low
high
low
low
high
J
74
0x4A
low
high
low
low
high
low
high
low
K
75
0x4B
low
high
low
low
high
low
high
high
L
76
0x4C
low
high
low
low
high
high
low
low
M
77
0x4D
low
high
low
low
high
high
low
high
N
78
0x4E
low
high
low
low
high
high
high
low
O
79
0x4F
low
high
low
low
high
high
high
high
P
80
0x50
low
high
low
high
low
low
low
low
Q
81
0x51
low
high
low
high
low
low
low
high
R
82
0x52
low
high
low
high
low
low
high
low
S
83
0x53
low
high
low
high
low
low
high
high
T
84
0x54
low
high
low
high
low
high
low
low
U
85
0x55
low
high
low
high
low
high
low
high
V
86
0x56
low
high
low
high
low
high
high
low
W
87
0x57
low
high
low
high
low
high
high
high
X
88
0x58
low
high
low
high
high
low
low
low
Y
89
0x59
low
high
low
high
high
low
low
high
Z
90
0x5A
low
high
low
high
high
low
high
low
79
Beschreiben der Anzeige
Das LCD-Modul C0802-04 hat vier Datenleitungen und der eingebaute Controller kann daher nur
im 4-Bit-Modus betrieben werden. Da der Controller aber auch für den 8-Bit-Modus ausgelegt ist,
muss ihm zu Beginn der Datenübertragung mitgeteilt werden, dass der 4-Bit-Modus verwendet
wird. Das ist nicht einfach, wenn der Zustand des Controllers unbekannt ist.
Zum Zeitpunkt der Nutzung des Displays könnte der Controller a) im 8-Bit-Modus sein (zum
Beispiel nach Anlegen der Versorgungsspannung, siehe oben), b) im 4-Bit-Modus sein, und auf den
ersten Takt mit dem höherwertigen Nibble warten, c) im 4-Bit-Modus sein, und auf den zweiten
Takt mit dem niederwertigen Nibble warten, nachdem im ersten Takt der Befehl zum Umschalten in
den 8-Bit-Modus erfolgte, oder d) im 4-Bit-Modus sein, und auf den zweiten Takt mit dem
niederwertigen Nibble warten, ohne dass im ersten Takt der Befehl zum Umschalten in den 8-BitModus erfolgte. Die folgenden Befehle stellen sicher, dass der Controller in jedem dieser Fälle in
den 4-Bit-Modus versetzt wird:
8-Bit-Modus
einschalten
E
RS
D7
D6
D5
D4
low
low
low
low
high
high
high
"
"
"
"
"
3 ms warten (danach wird E auf low gesetzt, um den Befehl abzuschließen)
8-Bit-Modus
einschalten
low
low
low
low
high
high
high
"
"
"
"
"
3 ms warten (danach wird E auf low gesetzt, um den Befehl abzuschließen)
8-Bit-Modus
einschalten
low
low
low
low
high
high
high
"
"
"
"
"
3 ms warten (danach wird E auf low gesetzt, um den Befehl abzuschließen)
4-Bit-Modus
einschalten
low
low
low
low
high
low
high
"
"
"
"
"
3 ms warten (danach wird E auf low gesetzt, um den Befehl abzuschließen)
Dabei bedeutet " , dass der vorherige Wert (Zeile oberhalb) unverändert bleibt. Nach dem Setzen des
4-Bit-Modus muss jeder Befehl in zwei Schritten gesendet werden, um alle 8 Bits eines Befehls zu
übertragen.
Das LCD-Modul C0802-04 hat eine zweizeilige Anzeige mit 5x8-Zeichenmatrix15. Wir wollen die
geschriebenen Zeichen stets sehen und verzichten im Folgenden auf das Ein- und Ausblenden der
Anzeige. Wenn der Cursor sichtbar ist, wird er nach dem letzten Zeichen angezeigt, also an der
Position, an der das nächste Zeichen geschrieben werden kann. Man kann den Cursor mit dem hier
15 Bei der 5 x 8-Zeichenmatrix stehen 5 x 7 Pixel (horizontal x vertikal) zur Darstellung eines Zeichens zur Verfügung
und die unterste Zeile (5 x 1 Pixel) dient nur zur Darstellung des Cursors, wenn dieser gezeigt wird.
80
verwendeten Display verwenden, aber in den folgenden Beispielen bleibt er ausgeschaltet. Der
Cursor kann als Unterstrich oder blinkender Block dargestellt werden. Bei nicht sichtbarem Cursor
ist das natürlich unbedeutend. Der Controller enthält einen Zeichenspeicher, welcher mehr als die
sichtbaren Zeichen speichern kann. Bei fester Zeichenanzeige nutzt man nur den ersten Teil des
Zeichenspeichers für die Anzeige; dies ist einfacher. Da Deutsch und Englisch von links nach rechts
geschrieben wird, sollte der Cursor nach dem Schreiben eines Zeichens nach rechts rücken.
Folgende Befehle setzen die Steuerbits richtig, löschen die Anzeige und setzen den Cursor an den
Anfang, sodass danach Zeichen geschrieben werden können. * bedeutet, dass der Wert egal ist.
E
RS
D7
D6
D5
D4
Steuerbits
low
low
low
low
high
low
1. Nibble,
D4:
DL = low,
2. Nibble,
D7 - D6:
N = high
F = low
high
"
"
"
"
"
Steuerbits
2. Nibble,
D6 - D4:
D = high
C = low
B = low
3 ms warten (danach wird E auf low gesetzt, um den Befehl abzuschließen)
low
low
high
low
*
*
high
"
"
"
"
"
3 ms warten (danach wird E auf low gesetzt, um den Befehl abzuschließen)
low
low
low
low
low
low
high
"
"
"
"
"
3 ms warten (danach wird E auf low gesetzt, um den Befehl abzuschließen)
low
low
high
high
low
low
high
"
"
"
"
"
3 ms warten (danach wird E auf low gesetzt, um den Befehl abzuschließen)
Steuerbits
2. Nibble,
D5 - D4:
I / D = high
S = low
low
low
low
low
low
low
high
"
"
"
"
"
3 ms warten (danach wird E auf low gesetzt, um den Befehl abzuschließen)
low
low
low
high
high
low
high
"
"
"
"
"
3 ms warten (danach wird E auf low gesetzt, um den Befehl abzuschließen)
Anzeige
löschen
und
Cursor
an den
Anfang
setzen
low
low
low
low
low
low
high
"
"
"
"
"
3 ms warten (danach wird E auf low gesetzt, um den Befehl abzuschließen)
low
low
low
low
low
high
high
"
"
"
"
"
3 ms warten (danach wird E auf low gesetzt, um den Befehl abzuschließen)
81
Mit folgender Befehlsfolge kann man nun das Zeichenpaar OK auf dem Display schreiben.
schreibt den
Buchstaben
O
(und rückt
dann den
unsichtbaren
Cursor
nach rechts)
schreibt den
Buchstaben
K
(und rückt
dann den
unsichtbaren
Cursor
nach rechts)
Befehlsende
E
RS
D7
D6
D5
D4
low
high
low
high
low
low
high
"
"
"
"
"
3 ms warten (danach wird E auf low gesetzt, um den Befehl abzuschließen)
low
high
high
high
high
high
high
"
"
"
"
"
3 ms warten (danach wird E auf low gesetzt, um den Befehl abzuschließen)
low
high
low
high
low
low
high
"
"
"
"
"
3 ms warten (danach wird E auf low gesetzt, um den Befehl abzuschließen)
low
high
high
low
high
high
high
"
"
"
"
"
3 ms warten (danach wird E auf low gesetzt, um den Befehl abzuschließen)
low
"
"
"
"
"
Allgemein gilt bei der Übertragung einer Zeichenkette an den Controller: Die ersten 8 Zeichen, die
an den Controller gesandt werden, ergeben die obere Zeile (eventuell mit Leerzeichen). Das 41. bis
48. an den Controller gesandte Zeichen wird in der unteren Zeile gezeigt. Nach dem 8. Zeichen der
oberen Zeile muss man also 32 Leerzeichen (oder beliebige andere Zeichen) senden und erst danach
die Zeichenkette für die untere Zeile. Dies merkwürdige Verfahren rührt daher, dass der Controller
nicht nur den vorliegenden Typ mit 8 Zeichen pro Zeile versorgen kann, sondern auch Displays mit
40 Zeichen pro Zeile.
Aufgabe 8
a) Schreiben Sie ein Python-Programm, das OK auf dem Display schreibt !
b) Schreiben Sie ein Python-Programm, das in der oberen Zeile des Displays HALLO und in der
unteren Zeile des Displays WELT! schreibt !
82
Anhang
Internetradio- und Internetfernsehsender und ihre URLs
Radiosender im mp3-Format, die mit dem Mediaplayer omxplayer abgespielt werden können:
afk M94.5
Bayern 1
http://stream.m945.mwn.de:80/m945-hq.ogg
http://br-mp3-bayern1muc-s.akacast.akamaistream.net/7/487/142690/v1/gnl.akacast.akamaistream.net/br_mp3_bayern1muc_s
Bayern 2
http://br-mp3-bayern2sued-s.akacast.akamaistream.net/7/717/256282/v1/gnl.akacast.akamaistream.net/br_mp3_bayern2sued_s
BR-Klassik
http://br-mp3-br-klassik-s.akacast.akamaistream.net/7/150/142693/v1/gnl.akacast.akamaistream.net/br_mp3_br-klassik_s
B5 aktuell
http://br-mp3-b5aktuell-s.akacast.akamaistream.net/7/773/142694/v1/gnl.akacast.akamaistream.net/br_mp3_b5aktuell_s
BBC World Service
Berliner Rundfunk 91.4
Bremen Eins
http://bbcwssc.ic.llnwd.net/stream/bbcwssc_mp1_ws-eieuk
http://stream.berliner-rundfunk.de/brf/mp3-128/internetradio
http://rb-mp3-m-bremeneins.akacast.akamaistream.net/7/716/234436/v1/gnl.akacast.akamaistream.net/rb-mp3-m-bremeneins
Deutschlandfunk
http://dradio_mp3_dlf_s.akacast.akamaistream.net/7/251/142684/v1/gnl.akacast.akamaistream.net/dradio_mp3_dlf_s
DRadio Wissen
http://dradio_mp3_dwissen_s.akacast.akamaistream.net/7/698/142684/v1/gnl.akacast.akamaistream.net/dradio_mp3_dwissen_s
France Musique
http://audio.scdn.arkena.com/11012/francemusique-midfi128.mp3
Hoerspielprojekt
http://stream.laut.fm:80/hoerspiel
Klassik Radio
http://stream.klassikradio.de/live/mp3-128/www.klassikradio.de/
Klassik Radio - Barock
http://stream.klassikradio.de/barock/mp3-128
Klassik Radio - Pure Bach
http://stream.klassikradio.de/purebach/mp3-128
Klassik Radio - Pure Mozart
http://stream.klassikradio.de/puremozart/mp3-128
KACU
http://stream1.kacu.org:8012/live
KPFK
http://ic1.mainstreamnetwork.com/kpfk-fm.mp3
LBC
http://media-ice.musicradio.com/LBCUKMP3Low
MDR Figarino
http://c22033-l.i.core.cdn.streamfarm.net/22033mdr/live/3087mdr_figaro/ch_figarino_128.mp3
MDR Sputnik
http://d85195728.i.tis.core005.cdn.streamfarm.net:80/22005mdrsputnik/live/3087mdr_sputnik_live/de_96.mp3
Radio Blau (Leipzig)
http://stream.radioblau.de
Radio Klasika Bratislava
http://live-icy.gss.dr.dk:8000/A/A04H.mp3
Radio1920
http://stream.laut.fm/radio1920
RBB Inforadio
http://inforadio.de/livemp3
RBB Kulturradio
http://kulturradio.de/livemp3
Sport1.fm
http://stream.sport1.fm/api/livestream-redirect/SPORT1FM_24_7.mp3
SRF 2 Kultur http://stream.srg-ssr.ch/m/drs2/mp3_128
SRF 4 News http://stream.srg-ssr.ch/m/drs4news/mp3_128
StadtRadio Göttingen
http://stream.stadtradio-goettingen.de:8000/stadtradio.mp3
Rai Radio 5 Classica
http://icestreaming.rai.it/5.mp3
Sputnik Deutschland
http://audio1.video.ria.ru/voiceger
Sputnik US / China
http://audio2.video.ria.ru/voiceeng / http://audio1.video.ria.ru/voicechi
UK 1940s Radio Station
http://1940sradio1.co.uk:8100/1
Vermont Public Radio
http://vpr.streamguys.net/vpr96.mp3
WDR 5
http://wdr-5.akacast.akamaistream.net/7/41/119439/v1/gnl.akacast.akamaistream.net/wdr-5
WEKU
http://pubint.ic.llnwd.net/stream/pubint_weku
WMBR MIT campus http://stream.wmbr.org:8000/hi
WNPV http://162.244.80.33:8700/;stream.mp3
1000 Oldies
http://streaming.radionomy.com/1000Oldies
1920s Radio Network
http://kara.fast-serv.com:8358/
83
Shell-Skript für ein einfaches Web-Radio, das den omxplayer verwendet
Wenn man das folgende Skript unter dem Namen radio1 speichert und (mit dem Konsolenbefehl
chmod a+x radio1) das Ausführungsrecht gibt, kann man es mit ./radio1 starten.
#!/bin/bash
# radio1
# einfaches Web-Radio, das den omxplayer verwendet
PS3="Auswahl (9 = ausschalten): "
select eingabe in "Bayern 2" "Bayern 5 aktuell" "BBC World Service" "Bremen 1" \
"Deutschlandfunk" "RBB Kulturradio" "SRF 4 News" "WDR 5" ausschalten
do
if [[ $REPLY == [1-8] ]]; then
echo $eingabe ; echo "Tasten: - leiser, + lauter, q = beenden" ; fi
case "$eingabe" in
"Bayern 2")
omxplayer -o both http://br-mp3-bayern2sued-s.akacast.akamaistream.ne\
t/7/717/256282/v1/gnl.akacast.akamaistream.net/br_mp3_bayern2sued_s 1> /dev/null
;;
"Bayern 5 aktuell")
omxplayer -o both http://br-mp3-b5aktuell-s.akacast.akamaistream.net/7/7\
73/142694/v1/gnl.akacast.akamaistream.net/br_mp3_b5aktuell_s 1> /dev/null
;;
"BBC World Service")
omxplayer -o both http://bbcwssc.ic.llnwd.net/stream/bbcwssc_mp\
1_ws-eieuk 1> /dev/null
;;
"Bremen 1")
omxplayer -o both http://rb-mp3-m-bremeneins.akacast.akamaistream.ne\
t/7/716/234436/v1/gnl.akacast.akamaistream.net/rb-mp3-m-bremeneins 1> /dev/null
;;
"Deutschlandfunk")
omxplayer -o both
http://dradio_mp3_dlf_s.akacast.akamaistream.net/7/251/142684/v1/gnl.aka\
cast.akamaistream.net/dradio_mp3_dlf_s 1> /dev/null
;;
"RBB Kulturradio")
omxplayer -o both http://kulturradio.de/livemp3 1> /dev/null
;;
"SRF 4 News")
omxplayer -o both http://stream.srg-ssr.ch/m/drs4news/mp3_128 1> /dev/null
;;
"WDR 5")
omxplayer -o both http://wdr-5.akacast.akamai\
stream.net/7/41/119439/v1/gnl.akacast.akamaistream.net/wdr-5 1> /dev/null
;;
*)
break
;;
esac
sleep 1
done
84
Radiosender, die mit dem vlc gehört werden können:
BBC Four
http://www.radiofeeds.co.uk/bbcradio4fm.pls
BBC Radio 4 Extra
http://www.radiofeeds.co.uk/bbcradio4extra.pls
British Comedy Radio
http://listen.abacus.fm/britishcomedy.m3u
CBC Radio One
http://www.surfmusic.de/m3u/cbcv-cbc-radio-one-90-5-fm,15345.m3u
Country 95.5 FM
http://www.surfmusik.de/m3u/chlb-country-95-5,15299.m3u
Fox News Talk
http://www.surfmusic.de/m3u/fox-news-talk,18436.m3u
Guldkanalen 60-tal
http://www.guldkanalen.se/static/streamGK60/64AAC.pls
KALW San Francisco
http://live.str3am.com:2430/listen.pls
LBC
http://media-ice.musicradio.com/LBCUK.m3u
MDR Info
http://avw.mdr.de/livestreams/mdr_info_live_128.m3u
NDR Info (Nds.)
http://www.ndr.de/resources/metadaten/audio/m3u/low/ndrinfo_nds.m3u
NDR Info Spezial
http://www.ndr.de/resources/metadaten/audio/m3u/low/ndrinfo_spezial.m3u
NDR Kultur
http://www.ndr.de/resources/metadaten/audio/m3u/low/ndrkultur.m3u
NDR K. klass. unterwegs
http://www.ndr.de/resources/metadaten/audio/m3u/ndrloop4.m3u
NDR 1 (Oldenburg)
http://www.ndr.de/resources/metadaten/audio/m3u/low/ndr1niedersachsen_ol.m3u
NDR 2 (Niedersachsen)
http://www.ndr.de/resources/metadaten/audio/m3u/low/ndr2_nds.m3u
NDR 90,3
http://www.ndr.de/resources/metadaten/audio/m3u/ndr903.m3u
NewsTalkRadio 77 WABC
http://www.surfmusic.de/m3u/wabc-770-am,205.m3u
Nordwestradio
http://www.surfmusik.de/m3u/nordwestradio,8567.m3u
NPR Program Stream
http://www.npr.org/streams/mp3/nprlive24.m3u
Polish Radio
http://mp3.polskieradio.pl:8908
Radio 10 60s & 70s Hits
http://stream.radiocorp.nl/r10_6070s_mp3.m3u
R.SA Oldieclub
http://streams.rsa-sachsen.de/rsa-oldies/mp3-128/listenlive/play.m3u
Schlagertempel
http://radio-schlagertempel.de/listen.pls
Sputnik Deutschland
http://nfw.video.ria.ru/flv/audio.aspx?ID=97594110&type=mp3
WBUR Boston NPR
http://audio.wbur.org/stream/live_mp3.m3u
WCBS Newsradio 880
http://www.surfmusic.de/m3u/wcbs-880-am,6270.m3u
WDR 1 Live
http://www.wdr.de/wdrlive/media/einslive.m3u
WDR 2
http://www.wdr.de/wdrlive/media/wdr2.m3u
WDR 3
http://www.wdr.de/wdrlive/media/wdr3.m3u
WDR 4
http://www.wdr.de/wdrlive/media/wdr4.m3u
WDR 5
http://www.wdr.de/wdrlive/media/wdr5.m3u
WDR KinderRadioKanal
http://www.wdr.de/wdrlive/media/kiraka.m3u
WNYC New York
http://www.wnyc.org/stream/wnyc-fm939/aac.pls
WPR Ideas Network
http://wpr-ice.streamguys.net/wpr-ideas-mp3-64.m3u
WPR News & Classical N.
http://wpr-ice.streamguys.net/wpr-music-mp3-96.m3u
WPR All Classical Netw.
http://wpr-ice.streamguys.net/wpr-hd2-mp3-96.m3u
WPR Special Events
http://wpr-ice.streamguys.net/wpr-special-64.m3u
WQXR classical music
http://www.wnyc.org/stream/wqxr/windows.pls
24/7 News
http://www.surfmusic.de/m3u/24-7-news,18547.m3u
Zum Beispiel wird BBC Four mit folgendem Konsolenbefehl gespielt:
cvlc http://www.radiofeeds.co.uk/bbcradio4fm.pls
85
Fernsehsender, die mit omxplayer und vlc gesehen werden können:
Fernsehen über das Internet ist mit den oben genannten Programmen auf dem Π_1B kaum, auf dem
leistungsstärkeren Π_2B einigermaßen möglich. Mit vlc , oder zum Teil auch mit dem omxplayer ,
kann man verschiedene deutsche Fernsehsender wiedergeben. Das ARD-Programm über die URL
http://daserste_live-lh.akamaihd.net/i/daserste_de@91204/master.m3u8
das ZDF-Programm über
http://zdf1314-lh.akamaihd.net/i/de14_v1@392878/master.m3u8?b=0-736&dw=0&__a__=off
ZDFinfo über
http://zdf1112-lh.akamaihd.net/i/de12_v1@392882/master.m3u8?b=0-736&dw=0&__a__=off
ZDFneo über
http://zdf1314-lh.akamaihd.net/i/de13_v1@392877/master.m3u8?b=0-736&dw=0&__a__=off
ZDFkultur über
http://zdf1112-lh.akamaihd.net/i/de11_v1@392881/master.m3u8?b=0-736&dw=0&__a__=off
Bayerisches Fernsehen über
http://livestreams.br.de/i/bfssued_germany@119890/master.m3u8
NDR Fernsehen über
http://ndr_fs-lh.akamaihd.net/i/ndrfs_nds@119224/master.m3u8
rbb Fernsehen über
http://rbb_live-lh.akamaihd.net/i/rbb_berlin@108248/master.m3u8
SR Fernsehen über
http://livestream.sr-online.de/live.m3u8
WDR Fernsehen über
http://www.metafilegenerator.de/WDR/WDR_FS/m3u8/wdrfernsehen.m3u8
das sogenannte Bildungsfernsehen ARD-alpha über
http://livestreams.br.de/i/bralpha_germany@119899/master.m3u8
ARTE über
http://delive.artestras.cshls.lldns.net/artestras/contrib/delive.m3u8
und den Fernsehsender 3sat über die URL
http://zdf0910-lh.akamaihd.net/i/dach10_v1@392872/master.m3u8?dw=0
empfangen. Die staatliche Auslandssender Deutsche Welle ist auf folgender URL zu empfangen:
http://www.metafilegenerator.de/DWelle/tv/ios/master.m3u8
Die österreichischen Fernsehsender ORF 1 , 2 , 3 und ORF sport sind über die URLs
86
http://apasfiisl.apa.at/ipad/orf1_q4a/orf.sdp/playlist.m3u8
http://apasfiisl.apa.at/ipad/orf2_q4a/orf.sdp/playlist.m3u8
http://apasfiisl.apa.at/ipad/orf3_q4a/orf.sdp/playlist.m3u8
http://185.85.28.20/orfs/q8c.sdp/chunklist.m3u8
zu sehen. Allerdings ist die Wiedergabe in Deutschland eingeschränkt. Englischsprachige
Nachrichten von den US-Sendern CNN und ABC News , sowie vom russischen Sender RT erhält
man mit den URLs
http://d1hya96e2cm7qi.cloudfront.net/Live/_definst_/sweetbcha1novD177_W_150.sdp/media_7419.m3u8
hhttp://abclive.abcnews.com/i/abc_live4@136330/index_1200_av-b.m3u8
http://rt-lh.akamaihd.net/i/ch_01@325605/index_480p_av-p.m3u8
Englischsprachige Nachrichten vom französischen Sender France 24 und vom chinesischen Staatssender CCTV News erhält man mit den URLs
http://static.france24.com/live/F24_EN_LO_HLS/live_web.m3u8
http://ktv030.cdnak.ds.kylintv.net/nlds/kylin/cctv9/as/live/cctv9_4.m3u8
Chinesisch (Mandarin) wird auf den Sendern CCTV1, CCTV4, CCTV10 und CCTV13 gesprochen:
http://ktv005.cdnak.ds.kylintv.net/nlds/kylin/cctv1hd/as/live/cctv1hd_4.m3u8
http://ktv031.cdnak.ds.kylintv.net/nlds/kylin/cctv4/as/live/cctv4_4.m3u8
http://ktv012.cdnak.ds.kylintv.net/nlds/kylin/cctv10/as/live/cctv10_4.m3u8
http://ktv030.cdnak.ds.kylintv.net/nlds/kylin/cctv13/as/live/cctv13_4.m3u8
Neues von der NASA kann man auf folgender URL betrachten:
http://nasatv-lh.akamaihd.net/i/NASA_101@319270/master.m3u8
Einige Fernsehprogramme werden in einer URL bereitgestellt, die mit rtmp:// beginnt. Um diese
wiedergeben zu können, installiert man das Programm rtmpgw im Paket rtmpdump :
sudo apt-get install rtmpdump
Den Fernsehsender N24 kann man dann mit dem Konsolenbefehl
rtmpdump -r "rtmp://pssimn24livefs.fplive.net/pssimn24livelive/_definst_/stream1" --live -o - | vlc -
(der Zeilenumbruch ist drucktechnisch bedingt; nach dem - am Ende der ersten Zeile geht es ohne
Leerzeichen oder Zeilenumbruch weiter mit der zweiten Zeile) im VLC media player anschauen.
Mit dem omxplayer lässt sich N24 mit folgenden zwei Konsolenbefehlen anschauen:
mkfifo pfeife
rtmpdump -r "rtmp://pssimn24livefs.fplive.net/pssimn24livelive/_definst_/stream1" --live -o pfeife | omxplayer --win
$x1,$y1,$x2,$y2 -o hdmi pfeife
Die Zeilenumbrüche nach der zweiten und dritten Zeile sind drucktechnisch bedingt.
87
Raspbian ─ Wichtige Befehle für die Kommandozeile
Tasten für Kopieren: Shift+Strg+C , Einfügen: Shift+Strg+V ; Blättern in früheren Befehlen:  / 
Informationen
whatis / man bf kurze / lange Info zu einem Befehl bf ; apropos bf suche in man-Seiten
df -m
zeige gesamten, belegten und verfügbaren Speicherplatz in MB (Option -m)
date
zeige Datum und Uhrzeit; date +%D zeige Datum; date +%T zeige Uhrzeit
cal zeige Kalender für aktuellen Monat;
ncal -3w zeige 3 Monate, Kalenderwochen
hostname zeige Rechnername;
uname -a
zeige Betriebssystem und Rechnertyp
id
zeige uid (Nutzer-ID), gid (Gruppen-ID) und Gruppenzugehörigkeiten des aktuellen Nutzers
sudo fdisk -l zeige Info zu angeschlossenen Datenträgern (SD-Karte, eventuell USB-Stick)
Software-Verwaltung
sudo apt-get update
aktualisiere die Datenbank für die Paketverwaltung APT
sudo apt-get upgrade
aktualisiere die installierten Pakete (nach ... update anwenden)
apt-cache search "txt"
suche nach Pakten, deren Kurzbeschreibung txt enthalten
apt-cache policy pk
ob für ein installiertes Paket pk eine neue Version verfügbar ist
sudo apt-get install prg
installiere das über die APT verfügbare Paket prg
sudo apt-get purge prg
prg vollständig, einschließlich Konfigurationsdateien entfernen
Dateien (zum Beispiel d1 und d2) und Verzeichnisse (z. B. v1 und v2, Heimatverzeichnis: ~ )
ls -l
zeige Verzeichnisinhalt, -a auch versteckte ; pwd zeige Pfad zum Arbeitsverz.
cd v1
wechsle Arbeitsv. ; cd wechsle ins Heimatv.; cd .. ins übergeordnete V.
mkdir v1 Verz. anlegen ; mv v1 v2 umbenenne / verschiebe V. ; rm -r v1 lösche V.
touch d1 erzeuge Datei ; mv d1 d2 / v1 umbenenne / verschiebe D. ; rm d1 lösche D.
chmod R d1 setze (+) / lösche (-) Rechte R: u Nutzer, g Gruppe, a alle, r read, w write, x execute
cp d1 d2 kopiere Datei; cp d1 v1 k. in Verzeichnis v1 ; cp -r v1 v2 k. Verzeichnis
cat d1 zeige Datei-Inhalt; cat d1 d2 > d12 hänge Dateien aneinander (Konkatenation)
less d1
zeige Datei seitenweise,  /  / Bild / Bild Zeile oder Seite vor / zurück, q Ende
grep tx d1 zeige Zeilen in d1, welche die Zeichenkette oder Regulären Ausdruck tx enthalten
bf1 | bf2
Pipe, leitet die Standardausgabe des Befehls bf1 an die Eingabe des Befehs bf2
wc d1
zähle Zeilenumbrüche, Wörter und Bytes, -c Bytes, -l Zeilen, -m Zeichen, -w Wörter
sum / cksum / md5sum / sha256sum d1
errechne Prüfsumme / (128 / 256 bit) Hashwert
> d1 , >> d1 Ausgabe in d1 umlenken (überschreiben, anhängen); < d1 Eingabe aus d1 lesen
./d1
führe das in der Datei d1, die im aktuellen Verzeichnis liegt, gespeicherte Programm aus
Archive verarbeiten
tar cfv archiv.tar d1 d2
packe Dateien oder Ordner, -c create, -f file, -v verbose
tar xfv archiv.tar
entpacke Archiv (Tarball) einschließlich Benutzerrechte, -x extract
tar cfzv archiv.tar d1 d2
erstelle komprimiertes Archiv, -z komprimieren
tar xfvz archiv.tar.gz
Archivdatei archiv.tar.gz dekomprimieren und auspacken
Prozess-Operationen und Netzwerkbetrieb (Schnittstellen, Kabel: etho und Funk: wlan0)
ps -ef
zeige Liste aller laufenden Prozesse (Option -e) in ausführlichem Format (-f)
pgrep -l txt
zeige alle Prozesse, deren Name die Zeichenkette txt enthält
kill pid bitte Prozess pid, sich zu beenden; kill -9 pid
beende Prozess pid
pkill txt oder pkill -9 txt
bitte / zwinge Prozesse mit txt im Namen zum Ende
sleep x
mache eine Pause von x Sekunden (in Shell-Skripten zur Programmunterbrechung)
ip a zeige IP-Adressen ; sudo ip l set up / down dev eth0 schalte etho ein / aus
ping / ping6 -c n host
teste n mal, ob host (Name, IPv4- / IPv6-Adresse) erreichbar ist
88
Bash ─ Shell-Variablen
Lokale Shell-Variablen (speichern zugewiesene und andere spezielle Werte eines Shell-Skripts)
Variablen wird (ohne vorherige Deklaration) durch den Operator = ein Wert zugewiesen. Vor und
nach = dem darf kein Leerzeichen stehen. Die Befehlszeile a=42 ; a="Sinn des Lebens"
belegt die Variable a zunächst mit dem Wert "42" , danach mit dem Wert "Sinn des Lebens". Ohne
weitere Festlegungen werden alle Werte als Zeichenkette gespeichert. Zeichenketten mit Leer- oder
Sonderzeichen müssen in Anführungszeichen stehen. Um auf den Inhalt einer Variablen zuzugreifen, schreibt mn ein $ vor den Variablennamen, zum Beispiel zeigt echo a den Inhalt der Variablen a . Lokale Variablen sind zunächst nur in der Shell verfügbar, in der sie erzeugt wurden.
Durch exportieren werden sie aber auch in Subshells (Shells, die von der aktuellen Shell erzeugt
werden) verfügar. Zum Beispiel wird mit dem Befehl export a die Variable a exportiert. Eine
Ausnahme bilden Subshells, sie durch Klammerung () von Befehlen erzeugt werden; bei Ihnen
werden die wurden alle Variablen automatisch aus der Vater-Shell exportiert.
Neben nutzerdefinierten Variablen gibt es auch von der Shell erzeugte, spezielle lokale Variablen:
?
Exit-Staus des letzten Vordergrund-Prozesses [0 , wenn kein Fehler auftrat]
$
Prozess-ID der aktuellen Shell
!
Prozess-ID des zuletzt aufgerufenen Hintergrund-Prozesses
0
Programm-Name;
1 - 9
Positionsparameter (bei Aufruf eines Shell-Skripts)
#
Anzahl der Positionsparameter; * / @ Zeichenkette / Liste der Positionsparameter
Mit readonly kann man Konstanten (schreibgeschützte Variablen) definieren. Mit dem Befehl
env zeigt man Umgebungsvariablen und exportierte Variablen an und mit set alle Variablen.
Umgebungsvariablen (globale Variablen, sie speichern Infos für die Shell und andere Programme)
Umgebungsvariablen werden automatisch beim Start einer Shell auf einen bestimmten Wert gesetzt
(siehe unten) und enthalten, sofern ihr Wert nicht verändert wird, in allen Shells den gleichen Wert.
BASH
Pfad zur aktuellen Shell [bei Raspbian in der Regel: /bin/bash]
BASH_ENV Name einer Datei die beim Start einer neuen Shell statt .bashrc ausgeführt wird []
BASH_VERSION
Version der aktuellen Shell [4.3.30(1)-release (oder höher)]
EUID
effektiver Nutzer-ID des aktuellen Benutzers [1000 (nach normalem Log-in)]
HOME
Home-Verzeichnis des aktuellen Benutzers [/home/pi (nach normalem Log-in)]
HOSTNAME Rechnername [raspberrypi (wenn kein anderer Name konfiguriert wurde)]
IFS
Internal Field Separator, Trennzeichen [beliebig viele Leerzeichen, Tabs, Newlines]
LANG
länderspezifischer Zeichensatz [de_DE.UTF-8 (nach deutscher Konfiguration)]
LINENO
aktuelle Zeilennummer, die beim Debugging von Bash-Skripten nützlich sein kann
LOGNAME
Login-Name des aktuellen Benutzers [pi (nach normalem Log-in)]
MAIL
Mailbox, Name einer Datei zur Speicherung ankommender E-mails
MAILCHECK
Periodendauer (in s) für die Prüfung, ob eine E-Mail angekommen ist [60]
PATH
Liste von Pfadnamen, die durch : getrennt sind, für die Suche nach Kommandos
PPID
Prozess-ID des Vater-Prozesses, Subshells, die Shell-Kopien sind, behalten die PPID
PS3
Eingabe-Prompt von Menüs, die mit einem Shell-Skript erzeugt wurden
PWD
Pfad zum aktuellen Arbeitsverzeichnis
RANDOM ganze Zufallszahl z, 0 ≤ z ≤ 32767; Initialisierung des Generators mit RANDOM=n
REPLY
in einem Shell-Skript: gewählte Nummer in Menü oder eingelesene Zeile bei read
SECONDS
Laufzeit in Sekunden der aktuellen Shell, kann auf neuen Startwert gesetzt werden
SHLVL
shell level, Verschachtelungstiefe der Shell, zum Beispiel 1 für eine Konsolen-Shell
TERM
Terminal-Typ (dessen Bildschirmsteuersequenzen in einer Datei beschreiben werden)
UID
Nutzer-ID des aktuellen Benutzers [1000 (nach normalem Log-in)]
89
Herunterladen