Raspberry Pi - EAH-Jena
Transcription
Raspberry Pi - EAH-Jena
NERKA Noch eine Raspberry Kurzanleitung Alfred H. Gitter , Version vom 29. 9. 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 Raspberry Pi wird im Folgenden mit Π abgekürzt (Π ist der griechische Großbuchstabe Pi). Die Schrift bezieht sich auf das Modell Raspberry Pi 3 Model B, gilt aber auch für frühere B-Modelle. Es wird vorausgesetzt, dass als Betriebssystem Raspbian Jessie (Full desktop image based on Debian Jessie, vom 27. Mai 2016) installiert wird oder wurde. Sie unterscheidet sich leicht von der Vorgängerversion Wheezy und stark von früheren Raspbian-Versionen. Das Betriebssystem ist für alle drei genannten Ausgaben des Π gleich. 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 Vorwort (28. Juli 2016)....................................................................................................................3 Hardware.......................................................................................................................4 Gehäuse, Energieversorgung, Bild und Ton, Tastatur und Maus, aktiver USB-Hub.......................5 Speicherkarte, LAN und WLAN, Kontroll-LEDs, Drucker und externe Datenträger....................6 Digitale Anschlusspunkte: GPIOs...................................................................................................9 Software.......................................................................................................................12 Boot, Betriebssystem, Konfiguration, Konsole, Paketverwaltung, Cronjobs................................12 Editor, Browser und weitere Programme.......................................................................................23 Steuerung der GPIOs über a) das Betriebssystem oder b) das Programm raspi-gpio...................30 Gnuplot und Mathematica (mit Aufgaben 1 und 2).......................................................................32 Programmieren mit Python..........................................................................................38 Erstes Programm: "Hallo!", Beispielprogramm (Zeit, Rundung, formatierte Ausgabe)...............38 GUI mit Python, Modul tkinter......................................................................................................41 Modul RPi.GPIO zur Steuerung der GPIOs..................................................................................43 Noch mehr Python.........................................................................................................................47 Experiment 1: LED ein- und ausschalten....................................................................53 Schaltung 1 (LED) und Steuerung der GPIOs von der Konsole...................................................53 Blinken und Dimmen mit Python-Programmen............................................................................55 Schaltung 2 (LED und Transistor).................................................................................................59 Aufgabe 3.......................................................................................................................................60 Experiment 2: Schalter auslesen..................................................................................62 Schaltung 3 (Schalter)....................................................................................................................62 Daten eingeben mit Python-Programm..........................................................................................63 Desktop Shortcut für unser Programm..........................................................................................64 Aufgabe 4.......................................................................................................................................65 Experiment 3: Temperatursensor am Eindraht-Bus.....................................................66 Schaltung 4 (Temperatursensor DS18S20)....................................................................................66 Temperaturmessung von der Konsole mit DS18S20.....................................................................67 Python-Programm zur Temperaturmessung mit DS18S20 (mit Aufgabe 5).................................68 Experiment 4: Temperatursensor am I2C Bus.............................................................72 Schaltung 5 (Temperatursensor LM75).........................................................................................72 Temperaturmessung von der Konsole mit LM75..........................................................................72 Python-Programm zur Temperaturmessung mit LM75.................................................................74 Aufgabe 6.......................................................................................................................................76 Experiment 5: A/D-Wandler am SPI Bus....................................................................77 Schaltung 6 (A/D-Wandler MCP3208) und das Treibermodul für den SPI Bus...........................77 Python-Programm zur Spannungsmessung mit MCP3208 (mit Aufgabe 7).................................79 Experiment 6: Textausgabe auf LCD-Anzeigemodul..................................................84 Schaltung 7 (LCD-Modul C0802-04)............................................................................................84 Controller vom Typ HD47780.......................................................................................................87 Beschreiben der Anzeige...............................................................................................................90 Aufgabe 8.......................................................................................................................................92 Anhang.........................................................................................................................93 Internetradio- und Internetfernsehsender und ihre URLs..............................................................93 Raspbian ─ Wichtige Befehle für die Kommandozeile.................................................................98 Bash ─ Shell-Variablen..................................................................................................................99 2 Vorwort (28. Juli 2016) Ein Vorwort ist der Preis, den der Leser eines guten Buches gedanklich entrichtet. Der geistig geizige oder ungeduldige Leser kann es natürlich überschlagen und gleich mit der spannenden Technik beginnen. Wer hier weiterliest muss sich nun einen geschichtlichen Rückblick gefallen lassen. In einer Elektronikzeitschrift aus dem Jahre 1979 wurden Mikrocomputer zum Lernen und Basteln angeboten, die den Mikroprozessor Z80 enthielten. Diese Vorgänger des Raspberry Pi ( Π ) wurden bereits mit Tastatur und Bildschirm (Fernseher) betrieben und verfügten über digitale I/O-Ports ähnlich den GPIOs des Π. Der Preis für ein System (Platine und Tastatur) mit 2 kB ROM (für das unveränderbare Betriebssystem) und 2 kB RAM (Arbeitsspeicher) betrug etwa 1000 DM. Wer wissen will, was DM ist und wie viel 1000 DM in heutiger Währungseinheit entsprechen, soll seine Großeltern über die gute alte Zeit befragen. Gespeichert wurden Programme und Daten auf Audiokassetten in Form von binärem Piepsen. Wer wissen will, was eine Audiokassette ist, ... Im Jahr 1979 gab es noch kein Internet und schnelle Textnachrichten wurden per Telegramm versandt. Wer wissen will, was ein Telegramm ist, ... Ansonsten war es 1979 nicht viel anders als heute (2016). Die künstliche Intelligenz war kurz vor dem Durchbruch und das baldige Ende fossiler Brennstoffe beschlossene Sache. Im Juli (1979 / 2016) sandte uns eine Raumsonde der USA schöne Photos vom Jupiter. Mein Chef riet mir damals, mich für Wissenschaft und Technik zu begeistern, denn damit hätte man auch noch Spass, wenn man mal über 50 ist. Glaubt es nur ! 3 Hardware CSI-2 (Kamera) DSI (Display) Antenne 2 40 Der Raspberry Pi ( Π ) ist ein Ein1 Stiftleiste P1 (GPIOs) mit 40 Pins 39 2x platinencomputer ( Single Board Raspberry Pi 3 Model B V1.2 USB 2.0 BCM43438 (c) Raspberry Pi 2015 Computer = SBC ). Es gibt ihn in 802.11n WLAN + Bluetooth 4.1 verschiedenen Ausführungen. Wir SMSC BCM 64-Bit-CPU und GPU und USB 2.0 2x benutzen hier das Modell Raspberry 2837 ELPIDA und LAN microSD 1 GB RAM Controller USB 2.0 SoC auf der beide auf der Pi 3 Model B, im folgenden mit Rückseite Rückseite ung Π_3B abgekürzt (Bild rechts), das 3,5 mm 4-polige rg LEDs Klinkenbuchse rso B e v S seit Februar 2016 verfügbar ist. ACT gie U r RJ-45 LNK e Audio/ n kro PWR E LEDs i Video Buchse Die älteren Ausgaben, Raspberry Pi M 100 HDMI Aus( LAN ) Model B, Revision 2, im folgenden 5V ( Typ A ) gang mit Π_1B abgekürzt, und Raspberry Pi 2 Model B, im folgenden mit Schema des Raspberry Pi 3 Model B, Ansicht von oben Π_2B abgekürzt, können aber auch verwendet werden. In der Regel beschränkt sich die Darstellung auf Eigenschaften des Π, die bei den drei genannten Modellen gleich sind und die erweiterten Möglichkeiten des Π_3B werden nicht benutzt. AHG Juni 2016 Wichtigstes Bauelement des Π ist das System-on-a-Chip (SoC) der Firma Broadcom , BCM2835 beim Π_1B , BCM2836 beim Π_2B und BCM2837 beim Π_3B. Das SoC enthält zwei Mikroprozessoren: eine ARM CPU ( ARM1176JZF-S beim Π_1B , ARM Cortex-A7 beim Π_2B und ARM Cortex-A53 beim Π_3B) und eine GPU ( Grafikprozessor , VideoCore IV bei bei Π_1B , Π_2B , und Π_3B ). Der Arbeitsspeicher als SDRAM beträgt 1 GB bei Π_2B und Π_3B , und 512 MB (beziehungsweise 256 MB bis Oktober 2012) beim Π_2B . Den Arbeitsspeicher teilen sich CPU und GPU. Die Aufteilung kann beim Start des Betriebssystems festgelegt werden (siehe unten, Raspberry Pi Configuration). Ansonsten bekommt die GPU 64 MB und die CPU den Rest. Die CPUs des Π verfügen auch über kleinere, schnellere Datenspeicher (Cache) als Level 1 cache und Level 2 cache. Als Speichermedium dient eine microSD-Karte die in eine Fassung unterhalb des Boards geschoben wird. Die Ausgabe von Bild und Ton kann am besten über den eingebauten HDMI-Ausgang erfolgen. Tastatur und Maus werden über USB mit dem Π verbunden. Der Π ist mit einem internen USB-Hub ausgestattet, welcher zwei (Π_1B) beziehungsweise vier (Π_2B und Π_3B) USB-2.0-Anschlüsse bereitstellt, sowie einer Ethernet-Schnittstelle zur Einbindung in Datennetze (LAN). USB und LAN werden vom USB/LAN-Controller gesteuert. Die Aktivität der CPU und des USB/LAN-Controllers SMSC LAN9514 wird auf dem Board es Π_3B durch vier LEDs angezeigt. Der Π_3B hat außerdem bereits WLAN und Bluetooth (Chip: BCM43438) mit Antenne (in obigem Schema oben links auf dem Board zu sehen) integriert. Steckverbinder auf dem Board erlauben den Anschluss einer speziellen Kamera und eines speziellen Displays. Über 40 elektrische Anschlusspunkte, GPIOs genannt, können digitale Ein- und Ausgaben erfolgen. Die Leistungsaufnahme hängt natürlich von der Belastung durch den SoC und die Peripheriegeräte ab. Man sollte mindestens 5 W (oder 1 A bei 5 V) bereitstellen. Empfohlen wird oft sogar ein Netzteil mit 10 - 13 W Leistung (entsprechend 2 - 2,5 A). 4 Gehäuse, Energieversorgung, Bild und Ton, Tastatur und Maus, aktiver USB-Hub Gehäuse 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. Energieversorgung Die Energieversorgung 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 5 V (maximal 5,25 V) und einen Strom von mindestens 1 A (es darf mehr sein) für den Π_3B (beziehungsweise mindestens 700 mA für den Π_1B und 800 mA für den Π_2B) liefern kann. Der dem Π über die Mikro-USB-Buchse zugeführte Strom darf beim Π_3B 2,5 A nicht überschreiten, was durch eine selbstrückstellende Sicherung , kurz Polyfuse genannt, gewährleistet wird. Diese (Typ: MF-MSMF250/16X) befindet sich auf der Rückseite der Platine in der Nähe der Mikro-USBBuchse. Der Π_2B ist für eine etwas geringere Leistungsaufnahme ausgelegt und enthält daher eine 2,0 A Polyfuse. Mit Netzgeräten nicht ausreichender Leistung arbeitet der Π nicht oder fehlerhaft, insbesondere beim Anschluss weiterer Geräte über die USB-Buchsen (siehe unten). Für einen mobilen Einsatz des Π kann ein geladener Akku an die Mikro-USB-Buchse angesteckt werden. Im Auto kann der Π über eine Bordspannungssteckdose und einen Adapter, der 5 V Spannung erzeugt, betrieben werden. Bild und Ton 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 DVIEingangsbuchse 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. Π_1B mit Peripheriegeräten Ältere Monitore mit VGA-Buchse können über einen Adapter am HDMI-Ausgang oder über den analogen Videoausgang (Composite Video) des Π angeschlossen werden. Es gibt auch einen analogen Audio-Ausgang. Beim Π_2B und Π_3B beim werden die analogen Audio- und Videosignale kombiniert über eine TRRS-Buchse für vierpolige Klinkenstecker bereitgestellt. Beim Π_1B gibt es eine (gelbe) Cinch-Buchse für das Bild- und einen dreipoligen Klinkenstecker (Stereo, 3,5 mm Durchmesser) für das Tonsignal. 5 Das nebenstehende Schema zeigt die Anschlüsse eines Klinkensteckers für den 3,5 mm-Analogausgang. links rechts Tastatur und Maus links rechts Masse Video Masse Als Dateneingabegeräte dienen Tastatur und Maus, die über die USB-Buchsen des Π angeschlossen werden. Leider hat der Π_1B nur zwei USB-Buchsen. Man kann zum Beispiel eine Funktastatur mit dazu gehöriger drahtloser Maus (das Bild zeigt unter dem Π_1B ein besonders kleines Exemplar) mit einem einzelnen USBlinks: Stecker für den 3,5 mm AudioAusgang des Π_1B , rechts: Stecker Stick (wie im Bild gezeigt) anschließen. Da die für den 3,5 mm Audio/Video-Ausgang Energieversorgung der USB-Buchsen beim Π schwach des Π_2B und des Π_3B 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. Aktiver USB-Hub 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 und externe Datenträger 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 und beim Π_3B eine microSD-Karte verwendet. Ich empfehle eine Kapazität von 16 GB. Die Verbindung zu einem LAN und damit in der Regel auch zum Internet ist über die RJ-45-Buchse möglich, in die ein Patchkabel (auch Ethernet-Kabel oder LAN-Kabel genannt) mit 8-poligen RJ45-Stecker passt. Das Modell Π_3B verfügt außerdem bereits über WLAN und Blootooth. Beim Π_1B und beim Π_2B kann eine WLAN-Antenne mit einem USB-Stick 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 6 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` 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 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) Beim Π_3B befinden sich die LEDs ACT und PWR in einer Ecke der Platine und die LEDs LNK und 100 innnerhalb der RJ-45-Buchse. Die LED FDX fehlt beim Π_2B und beim Π_3B . 7 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 sudo sudo sudo apt-get apt-get apt-get usermod update upgrade install cups -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. Der reguläre Datenträger, die microSD-Karte (beziehungsweise, bei älteren Π-Modellen, die SDoder SDHC-Karte) reicht oft nicht aus. Bei ausreichender Stromversorgung des Π (siehe oben) kann ein (normal formatierter) USB-Stick direkt in eine freie USB-Buchse des Π gesteckt werden. Festplatten und DVD-Brenner, welche DVDs und CDs lesen und schreiben, können ebenfalls über USB mit dem Π verbunden werden. Falls diese Geräte nicht über eine eigene Stromversorgung verfügen, müssen sie aber über einen aktiven USB-Hub (siehe oben) angeschlossen werden. Für die meisten Modelle stellt das Π-Betriebssystem automatisch einen passenden Treiber zur Verfügung und fügt sie in das Dateisystem ein ("mounted" sie), so dass (für den Benutzer pi) die Datenträger dann in einem Unterordner des Verzeichnisses /media/pi erscheinen. Es ist jedoch ratsam, sich vor der Anschaffung eines externen Datenträgers zu erkundigen, ob der Betrieb am problemlos Π möglich ist. Allerdings sind entsprechende Daten im Internet unvollständig. Anschluss und Programme zum Betrieb einer Webcam werden unten, im Abschnitt Editor, Browser und weitere Programme , beschrieben. 8 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 hat die Stiftleiste 26 Pins und beim Π_2B und beim Π_3B hat sie 40 Pins. Die 26 Pins des Π_1B stimmen mit den entsprechenden Pins des Π_2B und im wesentlichen (siehe unten) mit denen des Π_3B ü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. 9 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 und ebenso im Anfangsteil der Stiftleiste P1 beim Π_2B und beim Π_3B . 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 und beim Π_3B 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 und Π_3B beim kommen weitere freie GPIOs auf der Stiftleiste P1 hinzu. 10 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. 11 Software Boot, Betriebssystem, Konfiguration, Konsole, Paketverwaltung, Cronjobs Boot 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ädt 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ädt 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). Betriebssystem 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 Danach sind alte Daten auf der Speicherkarte nicht mehr ohne weiteres zugänglich, obwohl sie nicht physikalisch gelöscht werden. Wenn man die Daten auf einem Speichermedium (hier: eine Speicherkarte) vor einer Neuformatierung vollständig und unumkehrbar löschen will, kann man das Speichermedium mit Nullen 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. 12 überschreiben. In Linux-Betriebssystemen kann man das mit dem Programm dd , erreichen. Das Programm dd wird im Terminal (siehe unten) mit dem Konsolenbefehl dd if=/dev/zero of=/dev/mmcblk0 bs=10240 conv=noerror aufgerufen; dabei ist mmcblk0 der Name des zu löschenden Speichermediums2. Dieser unumkehrbare Löschvorgang dauert lange, bei größeren Spreichermedien mehrere Stunden. Während des Löschens gibt es keine Meldungen über den Fortschritt des Löschvorgangs. Erst wenn dieser abgeschlossen ist, erhält man eine Meldung über die Größe des gelöschten Speichers. Falls man wissen will, wie lange der Löschvorgang dauerte, verwendet man folgende Befehlszeile: time dd if=/dev/zero of=/dev/mmcblk0 bs=10240 conv=noerror Das Löschen der Festplatte ist für die Installation des Π-Betriebssystems nicht notwendig, erzeugt aber einen leeren, unformatierten und mit Sicherheit von Schadsoftware freien Speicher. 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 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ädt 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. 2 Kennt man den Namen des zu löschenden Speichermediums nicht, kann man ihn in Linux-Betriebssystemen mit dem Konsolenbefehl sudo fdisk -l (mit "l" wie in "lallen") ermitteln (siehe unten, Abschnitt Kommandozeile (Konsole) ). Man führt den Befehl vor und nach Einstecken der Speicherkarte aus, um zu erkennen, welcher Gerätename zur Speicherkarte gehört. Zu beachten ist, dass fdisk -l die Partitionen der angeschlossenen Speichermedien unter der Überschrift Device auflistet. Eine Speicherkarte namens mmcblk0 kann zum Beispiel die zwei Partitionen mmcblk0p1 und mmcblk0p2 enthalten. In obiger Befehszeile mit dem Aufruf von dd muss jedoch der Name der Speicherkarte (hier: mmcblk0 ), nicht der Name einer Partition eingesetzt werden. 13 Im Folgenden gehen wir davon aus, dass das Betriebssystem Raspbian Jessie (Full desktop image based on Debian Jessie, vom 27. Mai 2016) installiert wurde. Konfiguration 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; dort 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 . Dann klicken wir auf Set Timezone... , wählen Area: Europe und Location: Berlin (deutsche Zeitzone) und bestätigen mit Klick auf OK . Danach klicken wir auf Set Keyboard... , wählen Germany (Deutschland) German (Deutsch) und bestätigen mit Klick auf OK. Zum Schluss klicken wir auf Set WiFi Country, wählen DE Germany und bestätigen. Die Einstellungen werden durch Klick auf OK im Fenster Raspberry Pi Configuration bestätigt. Auf die Frage Would you like to reboot now? antworten wir 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) und Auto login (angekreuzt) lassen wir unverändert. 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 Option Wait for network lassen wir deaktiviert. 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 klicken nicht auf Add to Rastrack... . Die Einstellungen werden durch Klick auf OK im Fenster Raspberry Pi Configuration bestätigt. Auf die Frage Would you like to reboot now? antworten wir Yes und der Π startet erneut. Wir öffnen erneut Raspberry Pi Configuration und wählen im Reiter Interfaces : Camera: Disable , SSH: Enable (ermöglicht den Zugriff auf den Raspberry über ein Netzwerk), SPI: Enable (wird in Experiment 5 gebraucht), I2C: Enable (wird in Experiment 4 gebraucht), Serial: Enable, 1-Wire: Disabled, Remote GPIO: Disabled. Die Einstellungen werden durch Klick auf OK im Fenster Raspberry Pi Configuration bestätigt. Auf die Frage Would you like to reboot now? antworten wir Yes und der Π startet erneut. 14 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 Ordner des Dateisystems (siehe unten) betrachten und öffnen. Im Dateisystem bekommt jeder Benutzer ein eigenes Stammverzeichnis; der Benutzer 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. Wen das Himbeer-Symbol in der Mitte des Bildschirms stört, kann es folgendermaßen entfernen: Im Menü öffnet man Einstellungen - Appearance Settings und wählt (im Bereich Desktop) nach Layout die Option No Image (statt Centre image on screen). Später werden wir häufig in der Konsole eigene Programme aufrufen, die als ausführbare Dateien 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 15 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) bzw. beim Π_3B die IPv6-Adresse. 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 und beim Π_3B) 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 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 16 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-Klinkenstecker 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 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 Shortcuts kann man entfernen, indem man sie mit rechten Maustaste anklickt und dann im Menü 17 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 . 18 Kommandozeile (Konsole) 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 19 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 (zusammenhängende Speicherbereiche mit eigenem Namen) auf Speichermedien (auch Datenträger genannt) 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. Programme, die in der Konsole laufen, können in der Konsole nur Text und keine Bilder ausgeben. Allerdings gibt es Konsolenprogramme, die mit Textzeichen einfache Schwarzweiss-Grafiken erzeugen. Wenn eine Internetverbindung besteht, kann man zum Beispiel mit der Befehlszeile curl wttr.in/jena einen anschaulichen (und sehr schnell ladenden) Wetterbericht für Jena erhalten. Statt Jena kann man natürlich auch eine andere Stadt wählen. Paketverwaltung 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) 20 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 dieses Programm nicht mehr gebraucht wird, kann man es mit dem Befehl 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 21 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 @hourly stündlich, entspricht 0 * * * * 0 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). 22 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. Bilddateien werden standardmäßig mit dem Programm gpicview geöffnet, welches im Menü des Desktops unter Zubehör mit dem Eintrag Bildbetrachter zur Verfügung steht und auch in der Konsole aufgerufen werden kann. PDF-Dokumente können mit dem Programm xpdf betrachtet werden. In der Konsole wird xpdf 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 3 (Paket midori) können über die Paketverwaltung (siehe oben) zusätzlich installiert werden, aber Epiphany ist leistungsfähiger und kann auch Videos gut 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 erhält man die oft verwendeten Liberation Fonts ; sie verbrauchen 2,2 MB Plattenplatz. Wer eine Lizenz für Microsoft Windows besitzt, kann die entsprechenden Schriftarten auf dem Π mit dem Paket ttf-mscorefonts-installer installieren. 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. Dieses Programm besitzt eine grafische Benutzeroberfläche, nimmt allerdings ganze 111 MB Speicherplatz ein. Eine deutlich kleinere Variante ohne grafische Benutzeroberfläche ist scrot, welches für Rasbian Jessie schon vorinstaliert ist. Das freie E-Book-Betrachterprogramm 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. 3 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. 23 Wenn man das Paket youtube-dl installiert hat, 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 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ört. Man kann damit spezielle Pythonmodule installieren, zum Beispiel wifi für das Arbeiten mit WLAN-Netzen: sudo pip3 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. 24 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. 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. Der omxplayer kann keine Audio-CDs von einem externen Abspielgerät (DVD-Brenner) wiedergeben. Es gibt jedoch 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 Austausch 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. vlc kann Audio-CDs von einem externen Abspielgerät (DVD-Brenner) direkt wiedergeben. Um die Wiedergabe von der Kommandozeile auslösen, gibt man cvlc cdda://sr0 25 ein. Will man nur einen Track , zum Beispiel Track 10, abspielen, gibt man cvlc cdda://sr0 --cdda-track 10 ein. Erfolgt die Wiedergabe nicht flüssig, kann man überlegen, ob die gewünschten Tracks zunächst auf der microSD-Karte (beziehungsweise, bei älteren Π-Modellen,auf der SD- oder SDHC-Karte) gespeichert werden sollten. Im Rahmen des rechtlich Erlaubten (Privatkopie von CDs ohne Kopierschutz) kann man mihilfe des vlc den Inhalt einer Audio-CD in ein anderes Audio-Format, zum Beispiel MP3 , wandeln (konvertieren) und auf einem Datenträger des Π speichern. Die gespeicherte MP3-Datei lässt sich dann problemlos mit dem omxplayer oder dem vlc wiedergeben. Startet man vlc mit graphischer Bedienoberfläche, lassen sich einzelne Tracks (Spuren) einer Audio-CD folgendermaßen konvertieren: Im Reiter Medien des vlc-Menüs wählt man die Option Konvertieren/Speichern ... und klickt danach, im Reiter Medium , die Option Audio-CD an. Im Feld Laufwerk sollte dann der Pfad zur Audio-CD erscheinen, zum Beispiel /dev/sr0 . Nach Startposition Titel wählt man die Nummer des Tracks aus ( > 1 ) , der konvertiert werden soll und klickt auf Konvertieren / Speichern . Nach Profil wählt man das gewünschte Audio-Format, zum Beispiel Audio - MP3 und in das Feld nach Ziel Zieldatei: schreibt man den Pfad zu einer neuen Datei, zum Beispiel /home/pi/Downloads/neu.mp3 , in welcher der Track gespeichert werden soll. Nach Klick auf den Button Start erfolgt die Konvertierung und Speicherung. Die Konvertierung aller Tracks in einem Arbeitsgang ist so jedoch nicht möglich. Folgendes Shell-Skript konvertiert eine Audio-CD mit 21 Tracks (siehe Variable n ) in MP3Dateien, deren Name datei_??.mp3 ist (siehe Variablen f und d ), wobei statt ?? die zweistellige Nummer des Tracks (siehe Variable x ), eventuell mit führender Null, eingesetzt wird: #!/bin/bash n=21 ; f="datei_" ; i=1 echo ; echo "Audio-CD , $n Tracks -> $n MP3-Dateien" while [ $i -le $n ] do printf -v x "%02g" $i # zweistellige Tracknummer d="/home/pi/$f$x.mp3" # MP3-Dateinamen erzeugen cvlc cdda://sr0 --cdda-track $i --sout "#transc\ ode{acodec=mp3}:std{access=file, dst=$d}" vlc://quit i=`expr $i + 1` done echo "Konvertierung und Speicherung beendet." ; echo Nachdem man es als Datei rip gespeichert und mit chmod a+x rip ausführbar gemacht hat (siehe unten) kann man es mit ./rip aufrufen. Als Audioplayer für Dateien im MP3-Format kann man auch das Programm mpg123 verwenden, welches nach der Installation weniger als 400 kB Speicherplatz verbraucht. Es wird von der Konsole, zum Beispiel mit dem Befehl mpg123 -vC datei.mp3 26 gestartet. Mit der Option -v werden mehr Informationen angezeigt und mit -C wird die Steuerung über die Tastatur ermöglicht. Beim Abspiel mit der Option -C werden durch Drücken der H-Taste die verfügbaren Tastaturbefehle aufgelistet und Q beendet das Abspielen der Datei. Statt einer Datei kann auch ein (mit seiner URL angegebener) Internet-Radiosender gehört werden. Playlists werden abgespielt, wenn die Option -@ verwendet wurde. Die Option -b 2048 puffert 2 MB Daten, um Unterbrechungen (zum Beispiel durch einen zeitweise verlangsamten Internet-Datenstrom oder kurzzeitig erhöhte CPU-Belastungen) zu vermeiden. Folgender Befehl spielt einen Radiosender (sofern eine Internetverbindung besteht): mpg123 -b 2048 -C@ http://stream3.polskieradio.pl:8908/listen.pls 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. Speziell für den Π gibt es ein Kameramodul (Camera Module), das an der CSI-2 Buchse angeschlossen wird. Alternativ kann man eine Webcam über einen USB-Port mit dem Π verbinden. Für viele Webcams hat Raspbian bereits einen passenden Treiber installiert; hier eine Liste geprüfter Webcams. Um Bilder oder Videos mit der Webcam aufnehmen zu können, muss man noch ein entsprechendes Programm installieren. Zunächst ist fswebcam zu empfehlen, denn es benötigt nur 105 kB im Speicher und wird in der Konsole aufgerufen. Der Befehl fswebcam -r 640x480 test.jpg nimmt ein Bild mit der Auflösung 640 x 480 auf und speichert es in der Datei test.jpg (die es noch nicht geben darf). Die Bildaufnahme mit fswebcam kann durch Verwendung von Optionen noch verfeinert werden. Auskunft über die Optionen gibt der Konsolenbefehl man fswebcam Man kann die gewählten Optionen in einer Konfigurationsdatei, hier /home/pi/p/bild.cfg genannt, speichern. Ihr Inhalt könnte zum Beispiel so aussehen: # fswebcam - Konfiguration device "/dev/video0" input 0 delay 1 resolution 640x480 set brightness=80% set contrast=16% skip 5 frames 1 scale 320x240 banner-colour "#FF000000" line-colour "#FF000000" 27 text-colour "#000000" title "Webcam Testbild" timestamp "%d.%m.%Y %H:%M" jpeg 90 save "/home/pi/p/bild.jpg" Um eine Bildaufnahme durchzuführen, gibt man dann den Konsolenbefehl fswebcam -c /home/pi/p/bild.cfg ein. Das Bild wird, wie in der Konfigurationsdatei bestimmt, in der Datei /home/pi/p/bild.jpg gespeichert. Falls eine Datei gleichen Namens bereits existiert, wird diese überschrieben. Wenn man in einem Python-Programm (siehe unten) ein Bild von der Webcam aufnehmen lassen will, kann man den obigen Konsolenbefehl mithilfe folgender Python-Programmzeilen ausführen lassen: from subprocess import call call(["fswebcam", "-c", "/home/pi/p/bild.cfg"]) Komfortabler als fswebcam ist das Programm camorama (Speicherbedarf: 894 kB), das mit einer grafischen Benutzeroberfläche gesteuert wird. Nach der Installation findet man camorama im Menü unter Grafik. Man kann auch cheese (Speicherbedarf: 88,2 MB) benutzen, aber das belastet den Prozessor sehr und läuft nur mit neueren Π-Modellen (insbesondere: Π_3B ) flüssig. Anwendungsbeispiel: Das QX3 Computer-Mikroskop von Intel Play ist ein altes Lernspielzeug mit Webcam. Wenn man keine weitere Webcam angeschlossen hat, liefert camorama ohne weiteres das Bild. Danach kann man mit einem der folgenden beiden Konsolenbefehle v4l2-ctl --set-ctrl=illuminator_1=1 v4l2-ctl --set-ctrl=illuminator_2=1 die untere, beziehungsweise die obere Lampe einschalten. Entsprechend werden die Lampen mit v4l2-ctl --set-ctrl=illuminator_1=0 v4l2-ctl --set-ctrl=illuminator_2=0 wieder ausgeschaltet. Wenn eine Verbindung zum Internet besteht, kann man, mithilfe eines Browsers, Nachrichten auf der Webseite eines Nachrichtenportals anschauen. Will man nur einen Überblick oder nur kurze, aber schnell verfügbare Nachrichtentexte, kann man einen Web-Feed mit einem einen Feedreader , zum Beispiel Newsbeuter , lesen. Nach der Installation von newsbeuter (Speicherbedarf: 2,2 MB) kann man das Programm in der Konsole mit dem Befehl newsbeuter starten. Zunächst erhält man allerdings eine Fehlermeldung, weil noch keine Web-Feeds eingetragen wurden. Man öffnet mit einem Editor (zum Beispiel Leafpad) die Konfigurationsdatei sudo leafpad /home/pi/.newsbeuter/urls und trägt zum Beispiel einige Nachrichten-Feeds mit den Zeilen http://www.tagesschau.de/xml/atom 28 http://www.srf.ch/news/bnf/rss/1922 http://rss.cnn.com/rss/cnn_topstories.rss https://sputniknews.com/export/rss2/archive/index.xml ein. Nach dem Schließen der Datei kann man das Programm newsbeuter benutzen. In manchen Anwendungen möchte man eine E-mail automatisch vom Π versenden lassen. Dafür benötigt man zunächst ein E-Mail-Konto mit E-Mail-Adresse (zum Beispiel: [email protected]) bei einem E-Mail-Anbieter (zum Beispiel GMX). Der Umweg über einen E-Mail-Anbieter ist notwendig, da E-Mails, welche direkt von einem privaten Rechner gesandt werden, von empfangenden E-Mail-Anbietern oft nicht angenommen werden (um Spamming zu erschweren). Dann installiert man die Pakete mailutils und ssmtp . Darauf öffnet man mit einem Editor (zum Beispiel Leafpad) die Konfigurationsdatei ssmtp.conf , sudo leafpad /etc/ssmtp/ssmtp.conf und ersetzt deren Inhalt, im Beispiel für ein E-Mail-Konto bei GMX, durch folgende Zeilen: [email protected] mailhub=mail.gmx.net:465 hostname=gmx.net UseTLS=YES [email protected] AuthPass=PASSWORT FromLineOverride=NO wobei PASSWORT das Passwort des E-Mail-Kontos ist. Nach dem Schließen dieser Datei öffnet man entsprechend die Konfigurationsdatei revaliases , sudo leafpad /etc/ssmtp/revaliases und ersetzt deren Inhalt, im Beispiel für ein E-Mail-Konto bei GMX, durch folgende Zeile: pi:[email protected]:mail.gmx.net:465 wobei pi der Name des -Benutzers ist, der E-Mails versenden darf. Nach dem Schließen der Datei kann man mit einem Konsolenbefehl eine E-mail versenden, zum Beispiel echo "Hallo" | mail -s "Test" -A anl.txt [email protected] wobei "Hallo" eine Zeichenkette ist, die den zu sendenden Text enthält. Nach der Option -s folgt eine (kurze) Zeichenkette für die Betreffzeile der E-mail (hier: "Test"). Nach der Option -A folgt der Name einer Datei (mit vollständigem Pfadnamen), hier anl.txt , die als Anlage mit der E-Mail versandt werden soll. Am Ende der Zeile steht die E-Mail-Adresse, an die gesendet werden soll (Empfänger, in obigem Beispiel: [email protected]). Ein Nachteil des beschriebenen Verfahrens ist jedoch, dass das Passwort des E-Mail-Kontos unverschlüsselt in der Konfigurationsdatei ssmtp.conf gespeichert wird. 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, Spei29 cherbedarf: 12,2 MB) und gmchess (chinesisches Schach, Speicherbedarf: 7,5 MB). Zum Schachspielen kann man knights (Schachbrett) und gnuchess (Schach-"Engine") installieren (Speicherbedarf zusammen: 166 MB), zur Schach-Analyse scid (einschließlich scid-data, Speicherbedarf zusammen: 40,7 MB). Steuerung der GPIOs über a) das Betriebssystem oder b) das Programm raspi-gpio a) Steuerung über das Verzeichnis /sys/class/gpio/ Digitale Ein- und Ausgaben über die GPIOs lassen sich mithilfe des Betriebssystem-Kernel steuern, 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. Die Steuerungsmöglichkeiten erfassen aber nicht alle Eigenschaften der GPIOs. 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 echo echo echo 23 > /sys/class/gpio/export out > /sys/class/gpio/gpio23/direction 0 >/sys/class/gpio/gpio23/active_low 1 >/sys/class/gpio/gpio23/value Die erste Zeile scheibt man nur einmal, um GPIO 23 zur weiteren Verwendung zu belegen. Die 30 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 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 ).x b) Steuerung über das Programm raspi-gpio Das Programm raspi-gpio kann ohne Root-Rechte in der Konsole ausgeführt werden. Es liefert Informationen zu normalen und alternativen Funktionen der GPIOs und es ermöglicht Input (Einlesen des digitalen Zustands) und Output (Setzen des Zustands eines GPIOs) über die GPIOs. Das Programm liest und schreibt direkt in die Register (Speicherzellen der CPU), welche die GPIOs elektronisch steuern. Es umgeht das Betriebssystem und dessen Treiberprogramme. Dies kann zu unerwarteten und unerwünschten Wechselwirkungen mit gleichzeitig aktiven Treibern führen, die ebenfalls auf die GPIOs zugreifen. Man sollte das Programm daher nur einzeln zu Testzwecken oder zur Fehlersuche einsetzen. Mehr Information zum Programm erhält man mit dem Konsolenbefehl raspi-gpio help Mit dem Programm kann man zum Beispiel GPIO 14 als Ausgang ( op ) schalten und auf logisch 0 = low ( dl ) oder logisch 1 = high ( dh ) setzen raspi-gpio set 14 op dl raspi-gpio set 14 op dh oder den Zustand von GPIO 14 auslesen, raspi-gpio get 14 oder die alternativen Funktionen von GPIO 14 abfragen: raspi-gpio funcs 14 31 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 einfache4, wie hier: set title 'ein "wichtiges" Ereignis' 4 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. 32 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 33 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 34 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 35 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. 36 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] ! 37 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. Erstes Programm: "Hallo!" 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.5 5 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 38 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.6 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 . Beispielprogramm (Zeit, Rundung, formatierte Ausgabe) Führen Sie folgendes Python-Programm in gewohnter Weise aus. #!/usr/bin/python3 # -*-coding: utf-8 -*import time s = time.time() 6 genannte Programm gestartet und diesem die auszuführende Datei als Argument übergeben. 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. 39 print(s) 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. 40 Als Dezimalzeichen dient bei Python ein Punkt (wie bei anderen Programmiersprachen) statt eines 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 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 41 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 der mainloop unterbrochen wird. Das Programm reagiert dann nicht mehr auf Ereignisse und nicht einmal die Größe des Fensters kann verändert werden. 42 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). Digitale Ausgabe bedeutet, dass eine logische 0 (0 V) oder 1 (3,3 V) an den GPIO gegeben wird. 43 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. GPIOs werden oft verwendet, um die Ausführung eines Programms durch einen Schalter (oder 44 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.7 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. Mit der Zeile while True: wird eine Endlosschleife eingeleitet. Normalerweise enthält der 7 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. 45 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. 46 Noch mehr Python In diesem Abschnitt werden Python-Module vorgestellt, die nicht bei der Durchführung der unten beschriebenen Experimente gebraucht werden, aber trotzdem nützlich sein können: feedparser, matplotlib.pyplot, shutil, statistics, urllib.request, vlc und webbrowser. Man sollte darauf achten, dass sich der Dateiname eines Pythonprogramms vom Modulnamen unterscheidet. Feedreader im Pythonprogramm: feedparser Wenn man das Modul Universal Feed Parser ( feedparser ) mittels sudo pip3 install feedparser installiert hat, kann man es für einen Feedreader in einem Pythonprogramm nutzen: #!/usr/bin/python3 # -*- coding: utf-8 -*# Python verarbeitet und zeigt WebFeeds import feedparser import time url = "http://www.welt.de/?service=Rss" f = feedparser.parse(url) # WebFeed holen t = f['feed']['title'] # Titel des WebFeeds print("\n" + t + "\n") # Feedtitel anzeigen for i in f.entries: print(i.title) # Eintrags-Title dp = i.published_parsed # Datumsobjekt d = time.strftime("%d. %B %Y", dp) # Datum d = d.replace(' 0',' ') # ohne führende 0 print(d) # Datum (Format Tag, Monat, Jahr) print(i.summary) # Eintrags-Text print(i.link) # Eintrags-Verweis print() # Leerzeile nach Eintrag Damit wird ein Webfeed der Tageszeitung Die Welt in der Konsole ausgegeben. Wissenschaftliche Grafiken: matplotlib.pyplot Daten und mathematische Funktionen kann man mithilfe des Moduls matplotlib.pyplot darstellen, nachdem dieses mit sudo apt-get install python3-matplotlib installiert wurde. Im Python-Programm importiert man das Modul üblicherweise unter dem Namen plt : import matplotlib.pyplot as plt Das folgende Beispiel ist ein Python-Programm zur Darstellung eines zweidimensionalen Liniendiagramms. Die Daten zweier Funktionen, y1(x1) und y2(x2) , werden hier als Listen vorgegeben. (Stattdessen könnte man auch eine mathematische Funktion mit dem Modul numpy numerisch bestimmen und die Werte in Form eines Arrays angeben.) Im Beispiel wird gezeigt, wie die Einzelheiten der grafischen Darstellung (zum Beispiel Liniendicken und Beschriftungen) gesteuert werden können. Gegen Ende wird ein Dateiname erzeugt, der das aktuelle Datum enthält, und die Grafik 47 darin gespeichert. Die Punktdichte wird dabei auf 300 dpi (statt des Standardwerts von 100 dpi) gesetzt. Schließlich wird die Grafik mit dem Programm gpicview angezeigt, welches Teil des Raspbian-Betriebssystems ist. #!/usr/bin/python3 # -*- coding: utf-8 -*# Modul matplot.pyplot als plt (üblicher Name) importieren import matplotlib.pyplot as plt from time import strftime from subprocess import call # Daten: Listen der x1-Werte, y1-Werte, x2-Werte, y2-Werte x1 = [-2, -1, 0, 2, 3] # Liste der x1-Werte y1 = [11.2, -2.8, -0.5, 2.5, 2.3] # Liste der y1-Werte x2 = [-1.5, -0.5, 0.5, 1.5, 2.5] # Liste der x2-Werte y2 = [-2.5, 4.0, 10.2, 8.8, 5.1] # Liste der y2-Werte # # # # # # Plot-Parameter und einige ihre möglichen Werte color c: b blau, g grün, k schwarz, r rot, y gelb, w white linewidth lw, linestyle ls linestyle ls: '-' oder '--' oder ':' oder '-.' oder 'steps' marker: 'o' oder 's' oder 'v' oder '*' oder 'x' oder '+' markersize ms, markeredgewidth mew, markerfacecolor mfc # Grafikfenster, Breite x Höhe) 8 Zoll x 6 Zoll, Auflösung 100 dpi fig = plt.figure(figsize=(8, 6), dpi=100, facecolor='w') # Überschrift ( Parameter y positioniert die Überschrift vertikal ) plt.title(r'Titel: Zwei Funktionen', color='k', size=22, y=1.05) # Erzeugung einer xy-Grafik der Funktion y1(x1) l1 = r'$\mathdefault{y_1(x_1)}$' # Text mit tiefgestellten 1en p1 = plt.plot( x1, y1, label=l1 ) # mit label l1 für Legende (s.u.) # Formatierung der Linie (line) für y1(x1) plt.setp( p1, color='r', lw=2.0, ls='-' ) # 'r' = rot # Formatierung der Datenpunkte (marker) für y1(x1) plt.setp(p1, marker='o', ms=10, mew=2, mfc='r' ) # Erzeugung einer xy-Grafik der Funktion y2(x2) l2 = r'$\mathdefault{y_2(x_2)}$' # Text mit tiefgestellten 2en p2 = plt.plot( x2, y2, label=l2 ) # mit label l2 für Legende (s.u.) # Formatierung der Linie (line) für y2(x2) plt.setp( p2, color='g', lw=2.0, ls='-' ) # 'g' = grün # Formatierung der Datenpunkte (marker) für y2(x2) plt.setp(p2, marker='s', ms=9, mew=2, mfc='g' ) # Legende (Erklärung der Bedeutung der Daten-Linien) # plt.legend( loc='best', frameon=1, borderaxespad=1.5 ) plt.legend( loc='best', frameon=1, borderaxespad=1.5, fontsize=16 ) # loc: 'best','upper left','upper right','lower left','lower right' # frameon: 0 (kein Rahmen um Legende) oder 1 (Rahmen um Legende) # borderaxespad: Abstand des Legendenrahmens von den Achsenlinien # Bereich und Formatierung der Achsen: xmin = -2.5 ; xmax = 3.5 # untere und obere Grenze der x-Achse 48 ymin = -4.0 ; ymax = 12 # untere und obere Grenze der y-Achse plt.axis( [xmin, xmax, ymin, ymax] ) # Achsenbereiche setzen plt.xlabel(u'Temp. (\u00B0C)', color='k', size=18) # x-Achsentitel plt.ylabel(u'Länge (\u00B5m)', color='k', size=18) # y-Achsentitel # u (Unicode-Symbole): ° \u00B0, micro = \u00B5, Delta = \u0394 plt.xticks(color='k', size=16) # Format der x-Achsen-Tick-Werte plt.yticks(color='k', size=16) # Format der y-Achsen-Tick-Werte plt.tick_params('both', width=2, length=10, color='k') # Tick-Striche # Achsenformatierung: Dicke und Farbe der Achsenlinien (spines) ax= plt.gca() # gca bedeutet 'get current axes' (ax = Achsenobjekt) ax.spines['left'].set_color('k') # 'k' = schwarz ax.spines['left'].set_linewidth(2) ax.spines['right'].set_color('k') # 'k' = schwarz ax.spines['right'].set_linewidth(2) ax.spines['top'].set_color('k') # 'k' = schwarz ax.spines['top'].set_linewidth(2) ax.spines['bottom'].set_color('k') # 'k' = schwarz ax.spines['bottom'].set_linewidth(2) # Rand der Grafik automatisch optimieren plt.tight_layout() # Grafik speichern (Dateiname mit Datum) und anschliessend zeigen datei = 'plt_' + strftime("%y%m%d") + '.png' # erzeuge Dateinamen plt.savefig(datei, dpi=300) # Speicherung mit 300 dpi (statt 100 dpi) plt.close() # schließe aktuelle Instanz von plt (matplotlib.pyplot) call( [ "gpicview", datei ] ) # Anzeige der Grafik Man kann dieses Beispielprogramm als Vorlage für eigene Liniendiagramme verwenden. Zugriff auf das Dateisystem: shutil Das Modul shutil erlaubt Operationen mit Dateien und Verzeichnissen. Im folgenden Beispiel wird die bestehende Datei /home/pi/p/altdatei kopiert. Der Name (einschießlich Pfad) der neuen Datei ist /home/pi/p/neudatei. Falls eine Datei diesen Namens existiert, wird sie überschrieben. #!/usr/bin/python3 # -*- coding: utf-8 -*from shutil import copy copy("/home/pi/p/altdatei", "/home/pi/p/neudatei") Man kann auch prüfen, ob ein Programm (ausführbare Datei) existiert und gegebenenfalls den Pfad zum Programm erfahren. Im folgenden Beispiel wird geprüft, ob es Programme mit dem Namen mplayer beziehungsweise mplaxer gibt und, wenn ja, der Pfad zum Programm angezeigt. #!/usr/bin/python3 # -*- coding: utf-8 -*from shutil import which l = ["mplayer", "mplaxer"] for i in l: s = which(i) if s is None: print("Programm "+i+" gibt es nicht!") 49 else: print("Pfad zum Programm "+i+": "+s) Wenn mplayer installiert wurde, wird hier der Pfad /usr/bin/mplayer ausgegeben. Einfache Statistik: statistics Einige einfache Parameter der beschreibenden Statistik (zum Beispiel Mittelwert und Standardabweichung) kann man mit dem Modul statistics berechnen: #!/usr/bin/python3 # -*- coding: utf-8 -*# Python berechnet import math, statistics dat = [11.25, 4.75, 7.0, 5.25, 12.5, 7.75] mwt = str( round( statistics.mean(dat), 1) ) med = str( round( statistics.median(dat), 1) ) ssd = str( round( statistics.stdev(dat), 1) ) sem = str( round( statistics.stdev(dat)/math.sqrt(len(dat)), 1) ) print('\nGegeben sei ein Stichprobe mit den') print("Daten: " + ", ".join(map(str,dat))) print("als Teilmenge einer unbekannten Grundgesamtheit." + "\n") print("Die Stichprobe enthält " + str(len(dat)) + " Datenpunkte.") print("\nWir schätzen für die Grundgesamtheit:") print("Arithmetischer Mittelwert = " + mwt) print("Median (Zentralwert) = " + med) print("Standardabweichung (aus der Probe) = " + ssd + "\n") print("Standardfehler des (geschätzten) Mittelwerts = " + sem + "\n") Mehr Module für statistische Berechnungen bietet die Python-Erweiterung Numpy. URL (Quellcode einer Webseite) ohne Browser öffnen: urllib.request Das Modul urllib.request ermöglicht den Zugriff auf Dateien im Internet, zum Beispiel den Quellcode einer Webseite anhand der URL. Die URL bezeichnet den Ort der Datei im Internet und das Netzwerkprotokoll (Übertragungsformat), mit dem auf die Datein zugegriffen werden kann (zum Beispiel HTTP). Für die Datei im Internet wird vom Modul urllib.request ein dateiähnliches Objekt (englisch: file-like object) erzeugt. Es ist keine echte Datei, da Schreiboperationen ausgeschlossen sind. Das Lesen ist aber auf die gleiche Weise möglich wie bei einer echten Datei. Das folgende Python-Programm öffnet eine Webseite (deren URL in der Variablen url gespeichert ist), genauer gesagt: die Datei mit dem Quellcode, und bildet sie in der Instanz fl als dateiähnliches Objekt ab. Der Inhalt (Quellcode) wird gelesen und in der Variablen b gespeichert. Da der Inhalt der Variablen b vom Datentyp bytes ist, wird decodiert und in der Variablen s als Zeichenkette (Datentyp string) gespeichert. Die Instanz fl wird danach nicht mehr gebraucht und (wie eine Datei) geschlossen. Die entsprechenden Befehle befinden sich im Programmteil, der mit # Zugriff auf Quelltext einer Webseite mit URL url überschrieben ist. #!/usr/bin/python3 # -*- coding: utf-8 -*import urllib.request, re 50 # Zugriff auf Quelltext einer Webseite mit URL url url = "http://kurse.boerse.ard.de/ard/indizes_einzel\ kurs_uebersicht.htn?i=159096" # url mit Aktien-Kursen fl = urllib.request.urlopen(url) # öffne Webseite url b = fl.read() # b : Webseite als bytes-String s = b.decode("utf-8") # s : Webseite als Zeichenkette fl.close() # file-like object fl schließen # Listen bilden der Aktiennamen (l1) und Aktien-Kurse (l2) s = s[ s.find("Alle Aktien") : s.find("Performance DAX") ] r1 = re.compile(r"<strong>([^<>]{3,})</strong></td>") r2 = re.compile(r"(\d{1,4},\d{2}) € ") l1 = re.findall(r1,s) ; l2 = re.findall(r2,s) # Ergbnisse der 30 DAX-Aktien in der Konsole ausgeben if len(l1) == 30 and len(l1) == 30: for a, k in zip(l1, l2): print(a, k) else: print("Fehler bei der Auswertung der Webseite.") In den weiteren Programmteilen wird die gesuchte Information aus der in s gespeicherten Zeichenkette entnommen und in der Konsole als Text ausgegeben. Die im Beispielprogramm durchgeführten Operationen mit Zeichenketten und Regulären Ausdrücken sollen an dieser Stelle nicht erläutert werden. Die Ausgabe in der Konsole listet die aktuellen Kurse der 30 Dax-Aktien auf (sofern eine Internetverbindung besteht). Mit dem urllib.request kann man auch prüfen, ob auf eine URL im Internet erreichbar ist. Folgenden Programm prüft, ob auf einen bestimmten Internetradiosender zugegriffen werden kann. #!/usr/bin/python3 # -*- coding: utf-8 -*from urllib import request try: url = "http://kulturradio.de/livemp3" fl = request.urlopen(url, timeout=2) fl.close() print("Verbindung OK zur URL "+url) except request.URLError: print("Keine Verbindung zur URL "+url) Abhängig vom Ergebnis der Prüfung könnte man dann den Sender mit einem Mediaplayer spielen. Mediaplayer VLC im Pythonprogramm: vlc Wenn man das Modul vlc mittels sudo pip3 install python-vlc installiert hat, kann man den Mediaplayer VLC in einem Pythonprogramm steuern: #!/usr/bin/python3 51 # -*- coding: utf-8 -*import vlc import time radio1 = "http://inforadio.de/livemp3" radio2 = "http://1940sradio1.co.uk:8100/1" i = vlc.Instance() # vlc-Instanz mp = i.media_player_new() # Mediaplayer m = i.media_new(radio1) # Medium: Webradio mp.audio_output_set('alsa') # Audioausgabe mp.audio_output_device_set('alsa', 'hw:0,0') mp.audio_set_volume(100) # Lautstärke 100% mp.set_media(m) # Medium -> Mediaplayer mp.play() # Wiedergabe mit Mediaplayer print("20 s Pause, um Radio 1 zu hören") time.sleep(20) # Programm-Pause (20 s) mp.stop() # Wiedergabe ausschalten m = i.media_new(radio2) # Medium: Webradio mp.set_media(m) # Medium -> Mediaplayer mp.play() # Wiedergabe mit Mediaplayer print("20 s Pause, um Radio 2 zu hören") time.sleep(20) # Programm-Pause (20 s) mp.stop() # Wiedergabe ausschalten Obiges Programm spielt (mit Internetverbindung) zwei Webradiosender jeweils 20 s lang ab. Webseite im Browser öffnen: webbrowser Mit dem Modul webbrowser kann man aus einem Pythonprogramm den Webbrowser aufrufen und eine Webseite (oder allgemein eine URL) darstellen lassen: #!/usr/bin/python3 # -*- coding: utf-8 -*# Python öffnet Webseite im Browser import webbrowser u = "https://de.wikipedia.org/wiki/Jena" webbrowser.open(u) print("Programm läuft weiter. Ende") Das Pythonprogramm läuft dabei weiter. 52 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). 53 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 54 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" 55 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.8 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. 8 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. 56 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 57 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. 58 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 BC547C9 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 (Ta10 = 25 °C) die maximal zulässige Spannung zwischen Kollektor und Emitter (collector emitter 9 Statt mit BC547C kann der Transistot auch (kürzer) mit C547C beschriftet sein. 10 Ta steht für ambient temperature, zu Deutsch Umgebungstemperatur. Für diese gelten die Angaben im Datenblatt. 59 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 . 60 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 = 61 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 62 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. 63 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. 64 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). 65 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) 11 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 11 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. 66 Ü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.12 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.13) 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,gpiopin=4 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.14 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. 12 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. 13 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-therm). 14 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,gpiopin=4 # dtdebug=on 67 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 68 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 69 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 70 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 '+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! Das Modul os muss natürlich (in üblicher Weise) am Anfang des Programms eingebunden werden. 71 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 72 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 i2cdev . (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 . 73 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 74 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. 75 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 76 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). 77 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). 78 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 (mit Aufgabe 7) 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) # Pause zwischen zwei Messungen except KeyboardInterrupt: # Folgendes nach Druecken von Ctrl-C spi.close() # trennt das SpiDev-Objekt spi vom SPI-Bus print("\n- Messung beendet -\n") # Ende des Programms 79 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. 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 80 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 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 81 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 Stellen der zwölfstelligen Binärzahl), so dass die zwölfstelligen Binärzahl fertig ist und ihr Wert der Variablen Wert zugewiesen werden kann. 82 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. 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. 83 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).15 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. 15 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. 84 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 85 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 86 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. 87 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. 88 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 89 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-Zeichenmatrix16. 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 16 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. 90 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) 91 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 ! 92 Anhang Internetradio- und Internetfernsehsender und ihre URLs Radiosender, die mit dem Mediaplayer omxplayer abgespielt werden können: afk M94.5 Bayern 1 Bayern 2 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 http://br-mp3-bayern2sued-s.akacast.akamaistream.net/7/717/256282/v1/gnl.akacast.akamaistream.net/br_mp3_bayern2sued_s BR-Klassik B5 aktuell http://br-mp3-br-klassik-s.akacast.akamaistream.net/7/150/142693/v1/gnl.akacast.akamaistream.net/br_mp3_br-klassik_s http://br-mp3-b5aktuell-s.akacast.akamaistream.net/7/773/142694/v1/gnl.akacast.akamaistream.net/br_mp3_b5aktuell_s BBC Radio 1 http://bbcmedia.ic.llnwd.net/stream/bbcmedia_radio1_mf_p BBC Radio 4 http://bbcmedia.ic.llnwd.net/stream/bbcmedia_radio4fm_mf_p BBC Radio 4 Extra http://bbcmedia.ic.llnwd.net/stream/bbcmedia_radio4extra_mf_p BBC Radio 5 Live http://bbcmedia.ic.llnwd.net/stream/bbcmedia_radio5live_mf_p BBC World Service http://bbcwssc.ic.llnwd.net/stream/bbcwssc_mp1_ws-eieuk Berliner Rundfunk 91.4 http://stream.berliner-rundfunk.de/brf/mp3-128/internetradio Bremen Eins http://rb-mp3-m-bremeneins.akacast.akamaistream.net/7/716/234436/v1/gnl.akacast.akamaistream.net/rb-mp3-m-bremeneins Campusradio Jena http://crjstream.stud.fh-jena.de:8090/Campusradio-Jena 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 DW English (Sendezeit) http://dw-radio-english-mp3.akacast.akamaistream.net/7/779/135362/v1/gnl.akacast.akamaistream.net/dw-radio-english-mp3 France Musique http://audio.scdn.arkena.com/11012/francemusique-midfi128.mp3 Fritz (128kbit/s) http://fritz.de/livemp3 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 Newstalk (96kbit/s) http://176.124.246.11/nt 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/ 93 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 94 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 BBC World Service (48kbit/s) http://wsdownload.bbc.co.uk/worldservice/meta/live/shoutcast/mp3/eieuk.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 Hank's Old Time Radio (32kbit/s) http://myradiostream.com/hanksotr 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 Newstalk ZB (64kbit/s) http://streaming.radiomyway.co.nz/zbakalt.pls 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 WUNC (64kbit/s) http://mediaserver.wuncfm.unc.edu:8000/wunc64.m3u 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 95 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 den leistungsstärkeren Π_2B und Π_3B aber möglich. Mit vlc oder dem omxplayer , kann man verschiedene deutsche Fernsehsender wiedergeben. Die ARD-Programme Das Erste und Tagesschau24 empfängt man über die URLs http://daserste_live-lh.akamaihd.net/i/daserste_de@91204/master.m3u8 http://tagesschau-lh.akamaihd.net/i/tagesschau_1@119231/master.m3u8 und das ZDF-Programm, ZDFinfo , ZDFneo und ZDFkultur über http://zdf1314-lh.akamaihd.net/i/de14_v1@392878/master.m3u8?b=0-736&dw=0&__a__=off http://zdf1112-lh.akamaihd.net/i/de12_v1@392882/master.m3u8?b=0-736&dw=0&__a__=off http://zdf1314-lh.akamaihd.net/i/de13_v1@392877/master.m3u8?b=0-736&dw=0&__a__=off 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 und WDR Fernsehen über http://livestream.sr-online.de/live.m3u8 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 folgenden URLs zu empfangen: http://www.metafilegenerator.de/DWelle/tv/ios/master.m3u8 http://www.metafilegenerator.de/DWelle/tv-asia/ios/master.m3u8 http://www.metafilegenerator.de/DWelle/tv-northamerica/ios/master.m3u8 Die österreichischen Fernsehsender ORF 1 , 2 , 3 und ORF sport sind über die URLs http://apasfiisl.apa.at/ipad/orf1_q4a/orf.sdp/playlist.m3u8 http://apasfiisl.apa.at/ipad/orf2_q4a/orf.sdp/playlist.m3u8 96 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. Nachrichten auf Deutsch beziehungsweise Englisch gibt es von Euronews mit den URLs rtsp://ewns-hls-b-stream.hexaglobe.net/rtpeuronewslive/de_vidan750_rtp.sdp rtsp://ewns-hls-b-stream.hexaglobe.net/rtpeuronewslive/en_vidan750_rtp.sdp Englischsprachige Nachrichten erhält man auch vom US-Sender ABC News , http://abclive.abcnews.com/i/abc_live4@136330/index_1200_av-b.m3u8 http://abclive.abcnews.com/i/abc_live4@136330/master.m3u8?b=500,300,700,900,1200 Wirtschaftsnachrichten von Bloomberg Television : http://btv-i.akamaihd.net/hls/live/202760/btvusa_ios/P1/M700.m3u8 Kleinere Sender in den USA sind zum Beispiel University of California TV , Jupiter Broadcasting , KTVU (San Francisco Bay Area) , This Week in Tech , und WGN Chicago : rtmp://ucsdtv-wowza.ucsd.edu:1935/live/live_800 rtsp://videocdn-us.geocdn.scaleengine.net/jblive/live/jblive.stream http://ktvulive-i.akamaihd.net/hls/live/224677/ktvu1/master.m3u8 http://bglive-a.bitgravity.com/twit/live/high http://wgntribune-lh.akamaihd.net/i/WGNPrimary_1@304622/index_350_av-p.m3u8 In England gibt es London Live und in Irland RTÉ News Now : http://bcoveliveios-i.akamaihd.net/hls/live/217434/3083279840001/master_900.m3u8 http://wmsrtsp1.rte.ie/live/android.sdp/playlist.m3u8 Englischsprachige Nachrichten vom französischen Sender France 24 , vom japanischen NHK World , von den russischen RT International und RT Documentary , vom arabischen Al Jazeera English , von den indischen NDTV 24x7 und NewsX , und vom nigerianischen TVC News erhält man mit http://static.france24.com/live/F24_EN_LO_HLS/live_web.m3u8 http://web-cache.stream.ne.jp/www11/nhkworld-tv/global/222714/live.m3u8 http://rt.ashttp14.visionip.tv/live/rt-global-live-HD/playlist.m3u8 http://rt.ashttp14.visionip.tv/live/rt-doc-live-HD/playlist.m3u8 http://aljazeera-eng-apple-live.adaptive.level3.net/apple/aljazeera/english/appleman.m3u8 http://bglive-a.bitgravity.com/ndtv/247hi/live/native http://newsx.live-s.cdn.bitgravity.com/cdn-live/_definst_/newsx/live/newsxnew.smil/playlist.m3u8 http://77.92.76.135:1935/tvcnews/livestream/playlist.m3u8 Auf iPanda gibt es rund um die Uhr nur Pandabären zu sehen: http://fms.cntv.lxdns.com/live/flv/channel95.flv Neues von der NASA kann man auf folgenden URLs betrachten: http://nasatv-lh.akamaihd.net/i/NASA_101@319270/master.m3u8 http://iphone-streaming.ustream.tv/uhls/6540154/streams/live/iphone/playlist.m3u8 97 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 98 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)] 99