Inhaltsverzeichnis 1 Von der Betriebssysteminstallation bis zum ersten Python-Programm 1.1 Was braucht man? 1.1.1 Micro-USB-Handyladegerät 1.1.2 Speicherkarte 1.1.3 Tastatur 1.1.4 Maus 1.1.5 Netzwerkkabel 1.1.6 HDMI-Kabel 1.1.7 Audiokabel 1.1.8 Gelbes FBAS-Videokabel 1.2 Raspbian-Betriebssystem installieren 1.2.1 Speicherkarte im PC vorbereiten 1.2.2 Der Software-Installer NOOBS 1.2.3 Der erste Start auf dem Raspberry Pi 1.3 Fast wie Windows – die grafische Oberfläche LXDE 1.3.1 Uhrzeit einstellen 1.3.
6 LED per Pulsweitenmodulation dimmen 6.1.1 So funktioniert es 6.1.2 Zwei LEDs unabhängig dimmen 6.1.3 So funktioniert es 51 54 55 57 7 Speicherkartenfüllstandsanzeige mit LEDs 7.1.1 So funktioniert es 58 61 8 Grafischer Spielwürfel 8.1.1 So funktioniert es 63 65 9 Analoguhr auf dem Bildschirm 9.1.1 So funktioniert es 70 71 10 Grafische Dialogfelder zur Programmsteuerung 10.1.1 So funktioniert es 10.2 Lauflicht mit grafischer Oberfläche steuern 10.2.1 So funktioniert es 10.
1 Von der Betriebssysteminstallation bis zum ersten Python-Programm Kaum ein elektronisches Gerät in seiner Preisklasse hat in den letzten Jahren so viel von sich reden gemacht wie der Raspberry Pi. Der Raspberry Pi ist, auch wenn es auf den ersten Blick gar nicht so aussieht, ein vollwertiger Computer etwa in der Größe einer Kreditkarte – zu einem sehr günstigen Preis.
So äußert sich ein zu schwaches Netzteil Wenn der Raspberry Pi zwar bootet, sich dann aber der Mauszeiger nicht bewegen lässt oder das System nicht auf Tastatureingaben reagiert, deutet dies auf eine zu schwache Stromversorgung hin. Auch wenn der Zugriff auf angeschlossene USB-Sticks oder Festplatten nicht möglich ist, sollten Sie ein stärkeres Netzteil verwenden. 1.1.2 Speicherkarte Die Speicherkarte dient im Raspberry Pi als Festplatte. Sie enthält das Betriebssystem.
eines Fernsehers ist ein Adapterkabel mit einem 3,5-mm-Klinkenstecker erforderlich. Für Fernseher ohne gelben FBAS-Eingang gibt es Adapter von FBAS auf SCART. Die grafische Oberfläche lässt sich in analoger Fernsehauflösung nur mit Einschränkungen bedienen. 1.2 Raspbian-Betriebssystem installieren Der Raspberry Pi wird ohne Betriebssystem ausgeliefert. Anders als bei PCs, die fast alle Windows verwenden, empfiehlt sich für den Raspberry Pi ein speziell angepasstes Linux.
Installationsarchiv für NOOBS auf der offiziellen Downloadseite www.raspberrypi.org/downloads herunter und entpacken Sie es am PC auf eine mindestens 4 GB große Speicherkarte. Die Experimente in diesem Lernpaket wurden mit der NOOBS-Version 1.9.2 getestet. Ältere Versionen sind zu aktuellen Raspberry-PiModellen nur eingeschränkt kompatibel. Starten Sie jetzt den Raspberry Pi mit dieser Speicherkarte.
Abb. 1.2: Der LXDE-Desktop auf dem Raspberry Pi Das Raspbian-Linux für den Raspberry Pi verwendet die Oberfläche LXDE (Lightweight X11 Desktop Environment), die einerseits sehr wenig Systemressourcen benötigt und andererseits mit ihrem Startmenü und dem Dateimanager der gewohnten Windows-Oberfläche sehr ähnelt – mit dem Unterschied, dass die Taskleiste am oberen Bildschirmrand liegt. Linux-Anmeldung Selbst die bei Linux typische Benutzeranmeldung wird im Hintergrund erledigt.
1.3.1 Uhrzeit einstellen Der Raspberry Pi hat keine interne Echtzeituhr, sondern holt sich die aktuelle Uhrzeit aus dem Internet. Aber auch bei aktiver Internetverbindung wird die Uhr oben rechts in der Taskleiste zunächst eine falsche Zeit anzeigen. Das liegt an der standardmäßig eingestellten Zeitzone. Wählen Sie den Punkt Einstellungen/Raspberry Pi Confi guration. Dieses Dialogfeld ersetzt das textbasierte Konfi gurationstool früherer Raspbian-Versionen.
Unter Linux legt man alle eigenen Dateien grundsätzlich nur unterhalb des eigenen Home-Verzeichnisses ab. Hier heißt es /home/pi nach dem Benutzernamen pi. Linux verwendet den einfachen Schrägstrich zur Trennung von Verzeichnisebenen (/), nicht den von Windows bekannten Backslash (\). In diesem Verzeichnis werden Sie auch Ihre Python-Programme ablegen. Der Dateimanager zeigt standardmäßig auch nur dieses Home-Verzeichnis an. Einige Programme legen dort automatisch Unterverzeichnisse an.
Python 2 oder 3? Auf dem Raspberry Pi sind gleich zwei Versionen von Python vorinstalliert. Leider verwendet die neueste Python-Version 3.x teilweise eine andere Syntax als die bewährte Version 2.x, sodass Programme aus der einen Version nicht mit der anderen laufen. Einige wichtige Bibliotheken, sind noch nicht für Python 3.x verfügbar. Deshalb, und weil auch die meisten im Internet verfügbaren Programme für Python 2.x geschrieben wurden, verwenden wir in diesem Lernpaket die bewährte Python-Version 2.7.9.
Abb. 1.6: »Hallo Welt« in Python (oberhalb ist noch die Ausgabe der Berechnung zu sehen). Hier sehen Sie auch gleich, dass die Python-Shell zur Verdeutlichung automatisch verschiedene Textfarben verwendet. Python-Kommandos sind orange, Zeichenketten grün und Ergebnisse blau. Später werden Sie noch weitere Farben entdecken. Python-Flashcards Python ist die ideale Programmiersprache, um den Einstieg in die Programmierung zu erlernen. Nur die Syntax und die Layoutregeln sind etwas gewöhnungsbedürftig.
Abb. 1.7: Ausschnitt aus den Python-Flashcards. 1.4.1 Zahlenraten mit Python Anstatt uns mit Programmiertheorie, Algorithmen und Datentypen aufzuhalten, schreiben wir gleich das erste kleine Spiel in Python, ein einfaches Ratespiel, in dem eine vom Computer zufällig gewählte Zahl vom Spieler in möglichst wenigen Schritten erraten werden soll. 1. Wählen Sie im Menü der Python-Shell File/New Window.
2. Speichern Sie die Datei über File/Save As als spiel1.py ab. Oder Sie laden sich die fertige Programmdatei bei www.buch.cd herunter und öffnen sie in der Python-Shell mit File/Open. Die Farbcodierung im Quelltext erscheint automatisch und hilft dabei, Tippfehler zu finden. 3. Bevor Sie das Spiel starten, müssen Sie noch eine Besonderheit der deutschen Sprache berücksichtigen, nämlich die Umlaute. Python läuft auf verschiedensten Computerplattformen, die Umlaute unterschiedlich codieren.
4. Starten Sie jetzt das Spiel mit der Taste [F5] oder dem Menüpunkt Run/Run Module. 5. Das Spiel verzichtet der Einfachheit halber auf jede grafische Oberfläche sowie auf erklärende Texte oder Plausibilitätsabfragen der Eingabe. Im Hintergrund generiert der Computer eine Zufallszahl zwischen 0 und 1.000. Geben Sie einfach einen Tipp ab, und Sie erfahren, ob die gesuchte Zahl größer oder kleiner ist. Mit weiteren Tipps tasten Sie sich an die richtige Zahl heran. Abb. 1.9: Zahlenraten in Python. 1.4.
Diese Zufallszahl wird in der Variablen zahl gespeichert. Variablen sind in Python Speicherplätze, die einen beliebigen Namen haben und Zahlen, Zeichenfolgen, Listen oder andere Datenarten speichern können. Anders als in einigen anderen Programmiersprachen müssen sie nicht vorher deklariert werden. Wie entstehen Zufallszahlen? Gemeinhin denkt man, in einem Programm könne nichts zufällig geschehen.
if tipp < zahl: Wenn die geheime Zahl zahl größer ist als die vom Benutzer getippte Zahl tipp, dann ... print "Die gesuchte Zahl ist größer als ",tipp ... wird ein anderer Text ausgegeben. i += 1 In jedem Fall – deshalb nicht mehr eingerückt – wird der Zähler i, der die Versuche zählt, um 1 erhöht. Diese Zeile mit dem Operator += bedeutet das Gleiche wie i = i + 1. print "Du hast die Zahl beim ",i,". Tipp erraten" Diese Zeile ist mehr eingerückt, was bedeutet, dass auch die while-Schleife zu Ende ist.
Vorsicht Verbinden Sie auf keinen Fall irgendwelche GPIO-Pins miteinander und warten ab, was passiert, sondern beachten Sie unbedingt folgende Hinweise: Einige GPIO-Pins sind direkt mit Anschlüssen des Prozessors verbunden, ein Kurzschluss kann den Raspberry Pi komplett zerstören. Verbindet man über einen Schalter oder eine LED zwei Pins miteinander, muss immer ein Vorwiderstand dazwischengeschaltet werden. Verwenden Sie für Logiksignale immer Pin 1, der +3,3 V liefert und bis 50 mA belastet werden kann.
• ca. 1 m Schaltdraht 2.1.1 Steckplatinen Für den schnellen Aufbau elektronischer Schaltungen sind zwei Steckplatinen im Paket enthalten. Hier können elektronische Bauteile direkt in ein Lochraster mit Standardabständen eingesteckt werden, ohne dass man löten muss. Bei diesen Platinen sind die äußeren Längsreihen mit Kontakten (X und Y) alle miteinander verbunden. Abb. 2.2: Die Steckplatine aus dem Paket mit ihren eingebauten Verbindungen.
den, sodass eine Art Keil entsteht. Entfernen Sie an beiden Enden auf einer Länge von etwa einem halben Zentimeter die Isolierung. 2.1.3 Widerstände und ihre Farbcodes Widerstände werden in der Digitalelektronik im Wesentlichen zur Strombegrenzung an den Ports eines Mikrocontrollers sowie als Vorwiderstände für LEDs verwendet. Die Maßeinheit für Widerstände ist Ohm. 1.000 Ohm sind ein Kiloohm, abgekürzt kOhm. Die Widerstandswerte werden auf den Widerständen durch farbige Ringe angegeben.
GPIO-Eingänge Tab. 2.2: Farbcodes der Widerstände im Lernpaket. Achten Sie besonders bei den 1-kOhm- und 10-kOhm-Widerständen genau auf die Farben. Diese sind leicht zu verwechseln. 2.2 LED anschließen An die GPIO-Ports können für Lichtsignale und Lichteffekte LEDs (LED = Light Emitting Diode, zu Deutsch Leuchtdiode) angeschlossen werden.
Abb. 2.3: Steckbrettaufbau, um eine LED anzuschließen.
Abb. 2.4: Die erste LED am Raspberry Pi. In diesem ersten Experiment wird der Raspberry Pi lediglich als Stromversorgung für die LED genutzt. Die LED leuchtet immer, man braucht keinerlei Software dazu. Im nächsten Experiment setzen Sie einen Taster in die Zuleitung der LED. Die LED leuchtet jetzt nur, wenn dieser Taster gedrückt ist. Auch dafür braucht man keinerlei Software.
Abb. 2.5: Steckbrettaufbau für eine LED, die mit einem Taster geschaltet wird.
Abb. 2.6: LED mit Taster am Raspberry Pi. 2.3 GPIO mit Python Damit Sie GPIO-Ports über Python-Programme nutzen können, muss die Python-GPIO-Bibliothek installiert sein. In ganz alten Raspbian-Versionen musste man diese Bibliothek noch manuell installieren. Dies ist heute nicht mehr nötig, auch der früher benötigte sudo-Zugriff ist inzwischen Geschichte. 2.
Benötigte Bauteile: 1x Steckplatine 1x LED rot 1x 220-Ohm-Widerstand 2x Verbindungskabel Das nächste Programm led.py schaltet die LED für 2 Sekunden ein und danach wieder aus: import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) GPIO.setup(25, GPIO.OUT) GPIO.output(25, 1) time.sleep(2) GPIO.output(25, 0) GPIO.
Abb. 2.7: Eine LED am GPIO-Port 25. 2.4.1 So funktioniert es Das Beispiel zeigt die wichtigsten grundlegenden Funktionen der RPi.GPIO-Bibiothek. import RPi.GPIO as GPIO Die Bibliothek RPi.GPIO muss in jedem Python-Programm importiert werden, in dem sie genutzt werden soll. Durch diese Schreibweise können alle Funktionen der Bibliothek über das Präfix GPIO angesprochen werden. import time Die häufig verwendete Python-Bibliothek time hat nichts mit GPIO-Programmierung zu tun.
Nummerierung der GPIO-Ports Die Bibliothek RPi.GPIO unterstützt zwei verschiedene Methoden zur Bezeichnung der Ports. Im Modus BCM werden die bekannten GPIO-Portnummern genutzt, die auch auf Kommandozeilenebene oder in Shell-Skripten verwendet werden. Im alternativen Modus BOARD entsprechen die Bezeichnungen den PinNummern von 1 bis 40 auf der Raspberry-Pi-Platine. GPIO.setup(25, GPIO.OUT) Die Funktion GPIO.setup initialisiert einen GPIO-Port als Ausgang oder als Eingang.
Abb. 3.1: Steckbrettaufbau für die Verkehrsampel.
Abb. 3.2: Eine einfache Verkehrsampel. Das Programm ampel01.py steuert die Ampel: import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) rot = 0; gelb = 1; gruen = 2 Ampel=[4,18,23] GPIO.setup(Ampel[rot], GPIO.OUT, initial=False) GPIO.setup(Ampel[gelb], GPIO.OUT, initial=False) GPIO.setup(Ampel[gruen], GPIO.OUT, initial=True) print ("Strg+C beendet das Programm") try: while True: time.sleep(2) GPIO.output(Ampel[gruen],False); GPIO.
time.sleep(0.6) GPIO.output(Ampel[gelb],False); GPIO.output(Ampel[rot],True) time.sleep(2) GPIO.output(Ampel[gelb],True) time.sleep(0.6) GPIO.output(Ampel[rot],False); GPIO.output(Ampel[gelb],False) GPIO.output(Ampel[gruen],True) except KeyboardInterrupt: GPIO.cleanup() 3.1.1 So funktioniert es Die ersten Zeilen sind bereits bekannt, sie importieren die Bibliotheken RPi.GPIO für die Ansteuerung der GPIO-Ports und time für Zeitverzögerungen.
renddessen eine Systemausnahme auftritt – das kann ein Fehler sein oder auch die Tastenkombination [Strg]+[C] –, wird abgebrochen, und die except-Anweisung am Programmende wird ausgeführt. except KeyboardInterrupt: GPIO.cleanup() Durch diese Tastenkombination wird ein KeyboardInterrupt ausgelöst und die Schleife automatisch verlassen. Die letzte Zeile schließt die verwendeten GPIO-Ports und schaltet damit alle LEDs aus. Danach wird das Programm beendet.
4 Fußgängerampel Im nächsten Experiment erweitern wir die Ampelschaltung noch um eine zusätzliche Fußgängerampel, die während der Rotphase der Verkehrsampel ein Blinklicht für Fußgänger anzeigt, wie es in einigen Ländern verwendet wird. Natürlich könnte man auch die in Mitteleuropa übliche Fußgängerampel mit rotem und grünem Licht in das Programm einbauen, nur enthält dieses Lernpaket neben den von der Verkehrsampel verwendeten LEDs nur noch eine weitere.
Abb. 4.2: Verkehrsampel mit Fußgängerblinklicht. Das Programm ampel02.py steuert die neue Ampelanlage. Gegenüber der vorherigen Version wurde das Programm geringfügig erweitert. import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) rot = 0; gelb = 1; gruen = 2; blau = 3 Ampel=[4,18,23,24] GPIO.setup(Ampel[rot], GPIO.OUT, initial=False) GPIO.setup(Ampel[gelb], GPIO.OUT, initial=False) GPIO.setup(Ampel[gruen], GPIO.OUT, initial=True) GPIO.setup(Ampel[blau], GPIO.
time.sleep(2) GPIO.output(Ampel[gruen],False); GPIO.output(Ampel[gelb],True) time.sleep(0.6) GPIO.output(Ampel[gelb],False); GPIO.output(Ampel[rot],True) time.sleep(0.6) for i in range(10): GPIO.output(Ampel[blau],True); time.sleep(0.05) GPIO.output(Ampel[blau],False); time.sleep(0.05) time.sleep(0.6) GPIO.output(Ampel[gelb],True); time.sleep(0.6) GPIO.output(Ampel[rot],False) GPIO.output(Ampel[gelb],False) GPIO.output(Ampel[gruen],True) except KeyboardInterrupt: GPIO.cleanup() 4.1.
time.sleep(0.6) Mit einer Verzögerung von 0,6 Sekunden nach dem letzten Schleifendurchlauf wird der normale Schaltzyklus der Verkehrsampel fortgesetzt, indem die gelbe LED zusätzlich zur bereits leuchtenden roten eingeschaltet wird. So weit nicht viel Neues. Richtig interessant wird die Fußgängerampel, wenn sie nicht automatisch läuft, sondern erst durch einen Tastendruck gestartet wird, wie dies bei vielen Fußgängerampeln der Fall ist.
Abb. 4.4: Taster mit Schutzwiderstand und Pull-down-Widerstand an einem GPIO-Eingang. Bauen Sie gemäß folgender Abbildung einen Taster mit den beiden Widerständen in die Schaltung ein. Abb. 4.5: Steckbrettaufbau für die Fußgänger-»Bedarfsampel«.
Benötigte Bauteile: 1x Steckplatine 1x LED rot 1x LED gelb 1x LED grün 1x LED blau 4x 220-Ohm-Widerstand 1x Taster 1x 1-kOhm-Widerstand 1x 10-kOhm-Widerstand 7x Verbindungskabel 1x kurze Drahtbrücke Die in der Abbildung untere Kontaktleiste des Tasters ist über die Plusschiene der Steckplatine mit der +3,3V-Leitung des Raspberry Pi (Pin 1) verbunden. Zur Verbindung des Tasters mit der Plusschiene verwenden wir, um die Zeichnung übersichtlich zu halten, eine kurze Drahtbrücke.
Abb. 4.6: Fußgängerblinklicht mit Taster. Das Programm ampel03.py steuert die neue Ampelanlage mit dem Taster für das Fußgängerblinklicht. # -*- coding: utf-8 -*import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) rot = 0; gelb = 1; gruen = 2; blau = 3; taster = 4 Ampel=[4,18,23,24,25] GPIO.setup(Ampel[rot], GPIO.OUT, initial=False) GPIO.setup(Ampel[gelb], GPIO.OUT, initial=False) GPIO.setup(Ampel[gruen], GPIO.OUT, initial=True) GPIO.setup(Ampel[blau], GPIO.
GPIO.setup(Ampel[taster], GPIO.IN) print ("Taster drücken, um Fußgängerblinklicht einzuschalten, Strg+C beendet das Programm") try: while True: if GPIO.input(Ampel[taster])==True: GPIO.output(Ampel[gruen],False) GPIO.output(Ampel[gelb],True) time.sleep(0.6) GPIO.output(Ampel[gelb],False) GPIO.output(Ampel[rot],True) time.sleep(0.6) for i in range(10): GPIO.output(Ampel[blau],True); time.sleep(0.05) GPIO.output(Ampel[blau],False); time.sleep(0.05) time.sleep(0.6) GPIO.output(Ampel[gelb],True) time.sleep(0.
Als später parallel zum ASCII-Zeichensatz der ANSI-Zeichensatz eingeführt wurde, der von älteren Windows-Versionen verwendet wird, machte man den gleichen Fehler noch einmal. Um das Sprachengewirr perfekt zu machen, wurden die deutschen Umlaute und andere Buchstaben mit Akzenten an anderen Stellen im Zeichensatz eingeordnet als im ASCII-Standard.
while True: if GPIO.input(Ampel[taster])==True: Innerhalb der Endlosschleife ist jetzt eine Abfrage eingebaut. Die folgenden Anweisungen werden erst ausgeführt, wenn der GPIO-Port 25 den Wert True annimmt, der Benutzer also den Taster drückt. Bis zu diesem Zeitpunkt bleibt die Verkehrsampel in ihrer Grünphase stehen. Der weitere Ablauf der Schleife entspricht im Wesentlichen dem des letzten Programms. Die Verkehrsampel schaltet über Gelb auf Rot, das Blinklicht blinkt zehnmal.
Benötigte Bauteile: 1x Steckplatine 1x LED rot 1x LED gelb 1x LED grün 1x LED blau 4x 220-Ohm-Widerstand 5x Verbindungskabel Abb. 5.2: Vier LEDs mit Vorwiderständen.
Anhand verschiedener LED-Blinkmuster erklären wir weitere Schleifen und Programmiermethoden in Python. Das nächste Programm bietet verschiedene LED-Muster an, die vom Benutzer per Tastatureingabe ausgewählt werden können. Das Programm ledmuster.py lässt die LEDs in unterschiedlichen Mustern blinken. # -*- coding: utf-8 -*import RPi.GPIO as GPIO import time import random GPIO.setmode(GPIO.BCM) LED = [4,18,23,24] for i in LED: GPIO.setup(i, GPIO.OUT, initial=0) z = len(LED); w = 5; t = 0.
for j in range(z): GPIO.output(LED[j], False) time.sleep(t) elif e == "5": for i in range(w*z): j = random.randint(0,z-1) GPIO.output(LED[j], True); time.sleep(t) GPIO.output(LED[j], False) else: print ("Ungültige Eingabe") except KeyboardInterrupt: GPIO.cleanup() 5.1.1 So funktioniert es Die ersten Zeilen des Programms mit der Definition der UTF-8-Codierung und dem Import der notwendigen Bibliotheken sind bereits aus früheren Experimenten bekannt.
Um das Programm allgemeingültig und leicht veränderbar zu halten, werden jetzt noch drei Variablen definiert: z Zahl der LEDs Die Anzahl der LEDs wird mithilfe der Funktion len() automatisch aus der Liste LED übernommen. w Wiederholungen Jedes Muster wird, damit man es besser erkennt, standardmäßig fünfmal wiederholt. Diese Anzahl kann beliebig geändert werden und gilt dann für alle Muster. t Zeit Diese Variable gibt an, wie lange eine LED beim Blinken eingeschaltet ist.
matische Operationen oder Variablennamen direkt ausgewertet. In den meisten Fällen ist also raw_input() die bessere Wahl, da man sich um viele Eventualitäten möglicher Eingaben nicht zu kümmern braucht. Das Programm wartet, bis der Benutzer einen Buchstaben eingibt und die [Enter]-Taste drückt. Abhängig davon, welche Zahl der Benutzer eingegeben hat, soll jetzt ein bestimmtes Muster mit den LEDs angezeigt werden. Um dies abzufragen, verwenden wir ein if...elif...else-Konstrukt.
for i in range(w): for j in range(z): GPIO.output(LED[j], GPIO.output(LED[j], for j in range(z-1, -1, GPIO.output(LED[j], GPIO.output(LED[j], True); time.sleep(t) False) -1): True); time.sleep(t) False) Auch hier werden ineinandergeschachtelte Schleifen verwendet. Nach der ersten inneren Schleife, die dem zuvor beschriebenen Programmteil entspricht, also nachdem die LED mit der Nummer 3 leuchtet, beginnt eine weitere Schleife für das Lauflicht in entgegengesetzter Richtung.
Die erste innere Schleife schaltet die LEDs nacheinander mit einer Zeitverzögerung ein. Am Ende der Schleife, das an der Ausrückung der Zeile time.sleep(2*t) zu erkennen ist, wird die doppelte Verzögerungszeit gewartet. So lange leuchten alle LEDs. Danach beginnt eine weitere Schleife, die rückwärts zählt und eine LED nach der anderen wieder ausschaltet. Auch hier wird am Ende, wenn alle LEDs aus sind, die doppelte Verzögerungszeit gewartet, bevor die äußere Schleife den gesamten Zyklus noch einmal startet.
Ungültige Eingabe Bei allen Programmen, die Benutzereingaben erfordern, muss man Fehleingaben abfangen. Gibt der Benutzer etwas nicht Vorgesehenes ein, muss das Programm darauf reagieren. else: print ("Ungültige Eingabe") Hat der Benutzer irgendetwas anderes eingegeben, wird die unter else angegebene Anweisung ausgeführt. Dieser Abschnitt einer Abfrage trifft immer dann zu, wenn keine der anderen Abfragen ein wahres Ergebnis geliefert hat.
Abb. 6.2: Steckbrettaufbau mit einer LED.
Abb. 6.3: Eine LED am GPIO-Port 18. Das Programm leddimmen01.py dimmt die LED zyklisch heller und dunkler und verwendet dazu eine eigene PWM-Funktionalität der GPIO-Bibliothek. Das PWM-Signal wird als eigener Thread generiert. Auf diese Weise kann eine gedimmte LED (fast) wie eine normal leuchtende in einem Programm eingesetzt werden. import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM); LED = 18 GPIO.setup(LED, GPIO.OUT) print ("Strg+C beendet das Programm") p = GPIO.PWM(LED, 50); p.
6.1.1 So funktioniert es Ein Teil dieses Programms wird Ihnen bekannt vorkommen, einige Elemente aber auch gar nicht, da wir an dieser Stelle einen Exkurs in die objektorientierte Programmierung machen. Am Anfang werden, wie bekannt, Bibliotheken importiert. Diesmal wird nur eine einzige Variable, LED, für den GPIO-Port 18 festgelegt, dieser wird als Ausgang initialisiert. print ("Strg+C beendet das Programm") Da auch dieses Programm mit einem try...
Nachdem die LED volle Helligkeit erreicht hat, regelt eine zweite Schleife sie nach dem gleichen Schema wieder herunter. Diese Schleife zählt von 100 an in Schritten von -2 nach unten. Dieser Zyklus wiederholt sich, bis ein Benutzer die Tastenkombination [Strg]+[C] drückt. except KeyboardInterrupt: p.stop(); GPIO.cleanup() Der KeyboardInterrupt löst jetzt zusätzlich die Methode stop() des PWM-Objekts aus. Diese Methode beendet die Erzeugung eines PWM-Signals.
Benötigte Bauteile: 1x Steckplatine 1x LED gelb 1x LED rot 2x 220-Ohm-Widerstand 3x Verbindungskabel Abb. 6.5: Eine zweite LED am GPIO-Port 25. Das Programm leddimmen02.py dimmt die eine LED zyklisch heller und dunkler, während die andere LED zwar zusammen mit der ersten LED heller, im anderen Zyklus aber nicht dunkler wird, sondern wieder von 0 an heller wird und dabei schnell flackert. import RPi.
GPIO.setmode(GPIO.BCM); LED = [18,25] GPIO.setup(LED[0], GPIO.OUT); GPIO.setup(LED[1], GPIO.OUT) print ("Strg+C beendet das Programm") p = GPIO.PWM(LED[0], 50); q = GPIO.PWM(LED[1], 50) p.start(0) q.start(0) try: while True: for c in range(0, 101, 2): p.ChangeDutyCycle(c); q.ChangeDutyCycle(c) time.sleep(0.1) q.ChangeFrequency(10) for c in range(0, 101, 2): p.ChangeDutyCycle(100-c); q.ChangeDutyCycle(c) time.sleep(0.1) q.ChangeFrequency(50) except KeyboardInterrupt: p.stop(); GPIO.cleanup() 6.1.
Jetzt startet die zweite Schleife, der Übersichtlichkeit halber diesmal auch mit aufsteigender Zählung. Für die erste LED aus dem PWM-Objekt p, die in diesem Zyklus Schritt für Schritt abgedimmt werden soll, werden die entsprechenden Werte für das Tastverhältnis in jedem Durchlauf ausgerechnet. Bei der zweiten LED aus dem PWM-Objekt q wird das Tastverhältnis einfach wieder hochgezählt. Der Blinkeffekt entsteht durch die veränderte Frequenz. q.
Abb. 7.2: Steckbrettaufbau für die Speicherkartenfüllstandsanzeige.
Abb. 7.3: Drei LEDs zeigen den freien Speicherplatz auf der Speicherkarte an. Das Programm speicheranzeige.py liefert abhängig vom freien Speicherplatz auf der Speicherkarte unterschiedliche LED-Anzeigen: Freier Speicherplatz LED-Anzeige < 1 MB Rot 1 MB bis 10 MB Rot–Gelb 10 MB bis 100 MB Gelb 100 MB bis 500 MB Gelb–Grün > 500 MB Grün Tab. 7.1: So wird der Füllstand der Speicherkarte angezeigt.
import RPi.GPIO as GPIO import time import os g1 = 1; g2 = 10; g3 = 100; g4 = 500 GPIO.setmode(GPIO.BCM) LED = [4,18,23] for i in range(3): GPIO.setup(LED[i], GPIO.OUT, initial=False) print ("Strg+C beendet das Programm") try: while True : s = os.statvfs('/') f = s.f_bsize * s.f_bavail / 1000000 if f < g1: x = "100" elif f < g2: x = "110" elif f < g3: x = "010" elif f < g4: x = "011" else: x = "001" for i in range(3): GPIO.output(LED[i], int(x[i])) time.sleep(1.0) except KeyboardInterrupt: GPIO.
GPIO.setmode(GPIO.BCM) LED = [4,18,23] for i in range(3): GPIO.setup(LED[i], GPIO.OUT, initial=False) Eine Liste definiert die GPIO-Portnummern der drei LEDs. Danach initialisiert eine Schleife die drei GPIOPorts als Ausgänge und setzt alle LEDs auf ausgeschaltet. Auch in diesem Experiment verwenden wir eine try...except-Konstruktion und eine Endlosschleife, um das Programm automatisch immer wieder laufen zu lassen, bis es der Benutzer mit [Strg]+[C] abbricht.
Eine Schleife legt die GPIO-Ausgabewerte für die drei LEDs fest. Nacheinander bekommen alle LEDs den Zahlenwert der jeweiligen Ziffer aus der Zeichenfolge, 0 oder 1, zugewiesen. Die Werte 0 und 1 können genauso wie False und True verwendet werden, um GPIO-Ausgänge aus- oder einzuschalten. Die Funktion int() errechnet aus einem Zeichen dessen Zahlenwert. Das Zeichen wird über den Schleifenzähler i aus einer bestimmten Position der Musterzeichenkette ausgelesen. time.sleep(1.
# -*- coding: utf-8 -*import pygame, sys, random from pygame.locals import * pygame.init() FELD = pygame.display.set_mode((320, 320)) pygame.display.set_caption("Wuerfel") BLAU = (0, 0, 255); WEISS = (255, 255, 255) P1 = ((160, 160)); P2 = ((60, 60)); P3 = ((160, 60)); P4 = ((260, 60)) P5 = ((60, 260)); P6 = ((160, 260)); P7 = ((260, 260)) mainloop = True print "Beliebige Taste drücken, um zu würfeln, [Esc] beendet das Spiel" while mainloop: for event in pygame.event.get(): if event.type == QUIT or (event.
8.1.1 So funktioniert es Dieses Programm zeigt zahlreiche neue Funktionen, besonders zur Grafikausgabe mit der PyGame-Bibliothek, die natürlich nicht nur für Spiele, sondern auch für jegliche andere Grafik auf dem Bildschirm verwendet werden kann. import pygame, sys, random from pygame.locals import * pygame.init() Diese drei Programmzeilen stehen am Anfang fast jedes Programms, das PyGame verwendet.
Das Koordinatensystem für Computergrafik Jeder Punkt in einem Fenster bzw. auf einem Surface-Objekt wird durch eine x- und eine y-Koordinate bezeichnet. Der Nullpunkt des Koordinatensystems ist nicht, wie man in der Schule lernt, links unten, sondern links oben. Genau so, wie man einen Text von links oben nach rechts unten liest, erstreckt sich die xAchse von links nach rechts, die y-Achse von oben nach unten. Die sieben Punkte P1 bis P7 bezeichnen die in der Grafik angegebenen Mittelpunkte der Würfelaugen.
mainloop = True Damit sind die Grundlagen geschaffen, und das eigentliche Spiel kann beginnen. print "Beliebige Taste drücken, um zu würfeln, [Esc] beendet das Spiel" Diese Zeile erklärt dem Benutzer kurz, was zu tun ist. Bei jedem Druck auf eine beliebige Taste der Tastatur wird neu gewürfelt. print schreibt immer in das Python-Shell-Fenster, nicht in das neue grafische Fenster. while mainloop: Jetzt beginnt die Hauptschleife des Spiels.
Jetzt generiert die Zufallsfunktion random eine Zufallszahl zwischen 1 und 6 und speichert sie in der Variablen ZAHL. Diese Zeile schreibt nur zur Kontrolle das Würfelergebnis in das Python-Shell-Fenster. Sie können diese Zeile auch weglassen, wenn Sie auf die textbasierte Ausgabe verzichten wollen. print ZAHL if ZAHL == 1: pygame.draw.circle(FELD, WEISS, P1, 40) Jetzt folgen, alle nach dem gleichen Schema, sechs Abfragen.
Abb. 8.3: Die sechs möglichen Würfelergebnisse.
Die Schleife startet sofort von Neuem und wartet wieder auf einen Tastendruck des Benutzers. Falls während der Schleife mainloop auf False gesetzt wurde, weil der Benutzer das Spiel beenden will, wird die Schleife kein weiteres Mal durchlaufen, stattdessen wird die folgende Zeile ausgeführt: pygame.quit() Diese Zeile beendet das PyGame-Modul, was auch das grafische Fenster schließt und danach das ganze Programm.
Das Programm uhr01.py stellt die abgebildete Analoguhr auf dem Bildschirm dar: import pygame, time from pygame.locals import * from math import sin, cos, radians pygame.init() ROT = (255, 0, 0); WEISS = (255, 255, 255); SCHWARZ = (0, 0, 0) FELD = pygame.display.set_mode((400, 400)) FELD.fill(WEISS) MX = 200; MY = 200; MP = ((MX, MY)) def punkt(A, W): w1 = radians(W * 6 – 90); x1 = int(MX + A * cos(w1)) y1 = int(MY + A * sin(w1)); return((x1, y1)) for i in range(60): pygame.draw.
FELD = pygame.display.set_mode((400, 400)); FELD.fill(WEISS) Ein 400 x 400 Pixel großes Fenster wird geöffnet und komplett mit Weiß gefüllt. MX = 200; MY = 200; MP = ((MX, MY)) Drei Variablen legen die Koordinaten des Mittelpunkts fest, auf den bezogen alle weiteren grafischen Elemente, das Zifferblatt und der Uhrzeiger ausgerichtet werden. Die Variablen MX und MY enthalten die xund y-Koordinaten des Mittelpunkts, die Variable MP den Mittelpunkt als Punkt, wie er für grafische Funktionen verwendet wird.
for i in range(60): pygame.draw.circle(FELD, SCHWARZ, punkt(190, i), 2) Eine Schleife zeichnet nacheinander die 60 Minutenpunkte auf einem Kreis. Alle Punkte werden mit der Funktion punkt() ermittelt. Sie haben den gleichen Abstand vom Mittelpunkt, der mit 190 Pixeln in den vier Quadranten noch genau 10 Pixel vom Fensterrand entfernt ist. Die Punkte haben einen Radius von 2 Pixeln. for i in range(12): pygame.draw.
hm = (h + m / 60.0) * 5 Die Variable hm speichert den Winkel des Stundenzeigers in Minuteneinheiten, wie sie im gesamten Programm verwendet werden. Dazu wird zur aktuellen Stunde 1/60 des Minutenwerts addiert. In jeder Minute bewegt sich der Stundenzeiger um 1/60 einer Stunde weiter. Der errechnete Wert wird mit 5 multipliziert, da der Stundenzeiger in einer Stunde fünf Minuteneinheiten auf dem Zifferblatt vorrückt. if s1 <> s: Die Dauer eines Schleifendurchlaufs im Programm ist nicht bekannt.
Diese Zeile zeichnet den Sekundenzeiger als rote Linie mit einer Breite von 2 Pixeln vom Mittelpunkt aus 180 Pixel lang im Winkel, der durch den Sekundenwert angegeben wird. s1 = s Jetzt wird die gerade dargestellte Sekunde in der Variablen s1 gespeichert, um diesen Wert in den nächsten Schleifendurchläufen mit der aktuellen Sekunde zu vergleichen. pygame.display.set_caption("Aktuelle Zeit: " + time.asctime()) Diese Zeile schreibt die aktuelle Uhrzeit in digitaler Form in den Fenstertitel.
Benötigte Bauteile: 1x Steckplatine 1x LED rot 1x 220-Ohm-Widerstand 2x Verbindungskabel Abb. 10.1: Eine einzelne LED am GPIO-Port 4.
Schließen Sie eine LED über einen Vorwiderstand am GPIO-Port 4 an. Das Programm ledtk01.py wird diese zum Leuchten bringen. import RPi.GPIO as GPIO from Tkinter import * LED = 4; GPIO.setmode(GPIO.BCM); GPIO.setup(LED,GPIO.OUT) def LedEin(): GPIO.output(LED,True) def LedAus(): GPIO.output(LED,False) root = Tk(); root.title("LED") Label(root, text="Bitte Button klicken, um die LED ein- und auszuschalten").pack() Button(root, text="Ein", command=LedEin).
Eine ähnliche Funktion, LedAus(), schaltet die LED wieder aus. Diese beiden Funktionen werden später über die beiden Buttons im Dialogfeld aufgerufen. Bis hierhin war alles reines Python, jetzt geht es mit Tk und seinen Eigenheiten los. root = Tk() Tkinter arbeitet mit sogenannten Widgets. Dabei handelt es sich um eigenständige Bildschirmelemente, in den meisten Fällen um Dialogfelder, die ihrerseits verschiedene Elemente enthalten.
Die Methode .pack() kann auch noch Parameter enthalten, die festlegen, wie ein Objekt innerhalb des Dialogfelds angeordnet werden soll. side=LEFT bedeutet, dass der Button linksbündig und nicht zentriert angeordnet wird. Button(root, text="Aus", command=LedAus).pack(side=LEFT) Nach dem gleichen Schema wird noch ein zweiter Button angelegt, der die LED über die Funktion LedAus() wieder ausschaltet. Nun sind alle Funktionen und Objekte definiert, und das eigentliche Programm kann starten. root.
Abb. 10.3: Das Dialogfeld bietet drei LED-Muster zur Auswahl. Der Aufbau der Schaltung ist der gleiche wie der im Experiment »Bunte LED-Muster und Lauflichter«. Abb. 10.4: Steckbrettaufbau zu Experiment 10.2.
Abb. 10.5: Vier LEDs blinken in unterschiedlichen Mustern. Das Programm ledtk02.py basiert auf dem vorherigen Programm, wurde aber um die Radiobuttons sowie die Funktionen für die LED-Lauflichter und Blinkmuster erweitert. import RPi.GPIO as GPIO import time from Tkinter import * GPIO.setmode(GPIO.BCM) LED = [4,18,23,24] for i in LED: GPIO.setup(i, GPIO.OUT, initial=0) w = 5; t = 0.
] root = Tk(); root.title("LED"); v = IntVar(); v.set(1) def LedEin(): e = v.get() if e == 1: for i in range(w): for j in range(4): GPIO.output(LED[j], True) time.sleep(t) GPIO.output(LED[j], False) elif e == 2: for i in range(w): for j in range(4): GPIO.output(LED[j], True) time.sleep(t) for j in range(4): GPIO.output(LED[j], False) time.sleep(t) else: for i in range(w): for j in range(4): GPIO.output(LED[3-j], True); time.sleep(t) GPIO.
Zwei Variablen legen zwei Werte im Programm fest: die Anzahl der Wiederholungen w eines Musters sowie die Blinkzeit t. Beide Werte könnten auch bei jedem Vorkommen im Programm fest eingetragen werden. Auf diese Weise lassen sie sich aber leichter anpassen, da sie nur an einer Stelle definiert sind. muster = [ ("Lauflicht nach links",1), ("Blinken",2), ("Lauflicht nach rechts",3) ] Die Texte der drei Muster, die zur Auswahl stehen, werden in einer besonderen Listenform definiert.
elif e == 2: for i in range(w): for j in range(4): GPIO.output(LED[j], True) time.sleep(t) for j in range(4): GPIO.output(LED[j], False) time.sleep(t) Im zweiten Fall werden fünfmal hintereinander alle vier LEDs gleichzeitig eingeschaltet und, nachdem sie für 0,2 Sekunden geleuchtet haben, auch gleichzeitig wieder ausgeschaltet. else: for i in range(w): for j in range(4): GPIO.output(LED[3-j], True); time.sleep(t) GPIO.
Der Button wird wie im letzten Beispiel definiert. root.mainloop(); GPIO.cleanup() Auch die Hauptschleife und das Programmende entsprechen dem letzten Beispiel. Starten Sie das Programm und wählen Sie über einen der Radiobuttons ein Blinkmuster. Über die Variable v ist die erste Auswahl vorausgewählt. Wenn Sie Radiobuttons in einem Dialogfeld verwenden, sollten Sie immer eine sinnvolle Vorauswahl festlegen, damit es nie zu einem undefinierten Ergebnis kommt, falls der Benutzer selbst keine Auswahl trifft.
import RPi.GPIO as GPIO import time from Tkinter import * GPIO.setmode(GPIO.BCM); LED = [4,18,23,24] for i in LED: GPIO.setup(i, GPIO.OUT, initial=0) w = 5 muster = [ ("Lauflicht nach links",1), ("Blinken",2), ("Lauflicht nach rechts",3) ] root = Tk(); root.title("LED"); v = IntVar(); v.set(1); g = IntVar(); g.set(5) def LedEin(): e = v.get() t = 1.0/g.get() if e == 1: for i in range(w): for j in range(4): GPIO.output(LED[j], True); time.sleep(t) GPIO.
10.3.1 So funktioniert es Die Initialisierung der Bibliotheken und GPIO-Ports sowie die Definition der Liste für die drei Blinkmuster entsprechen dem vorangegangenen Programm. Die Festlegung der Variablen t für die Blinkzeit fällt weg, da diese später aus dem Schieberegler ausgelesen wird. g = IntVar(); g.set(5) Zusätzlich zur Tk-Variablen v, in der das ausgewählte Blinkmuster gespeichert wird, wird eine weitere Integervariable g für die Geschwindigkeit deklariert.
Der Schieberegler ist ein Objekt vom Typ Scale, das wie alle Objekte in diesem Dialogfeld als ersten Parameter root enthält. Der Parameter orient=HORIZONTAL gibt an, dass der Schieberegler waagerecht liegt. Ohne diesen Parameter würde er senkrecht stehen. Die Parameter from_ und to geben die Anfangs- und Endwerte des Schiebereglers an. Beachten Sie dabei die Schreibweise from_, da from ohne Unterstrich ein reserviertes Wort in Python für den Import von Bibliotheken ist.
Abb. 11.1: Das Spiel Simulate aus den Python Games. Unser Spiel PiDance basiert ebenfalls auf diesem Spielprinzip. LEDs blinken in einer zufälligen Reihenfolge. Der Benutzer muss die gleiche Reihenfolge anschließend mit den Tastern drücken. Mit jeder Runde leuchtet eine weitere LED, sodass es immer schwieriger wird, sich die Reihenfolge zu merken. Sobald man einen Fehler macht, ist das Spiel zu Ende.
Abb. 11.2: Steckbrettaufbau zu Experiment 11.
Abb. 11.3: PiDance mit LEDs und Tastern auf zwei Steckplatinen. Die Taster sind gegenüber von den zugehörigen LEDs aufgebaut. Die mittleren beiden Längsreihen der Steckplatinen auf beiden Seiten der Verbindungsstelle dienen als 0-V- und +3,3-V-Leitung für die Schaltung. Das Programm pidance01.py enthält das fertige Spiel. # -*- coding: utf-8 -*import time, random import RPi.GPIO as GPIO GPIO.setmode(GPIO.BCM) rzahl = 10; farbe = [] for i in range(rzahl): farbe.append(random.
while True: if(GPIO.input(TAST[0])): return 0 if(GPIO.input(TAST[1])): return 1 if(GPIO.input(TAST[2])): return 2 if(GPIO.input(TAST[3])): return 3 ok = True for runde in range(1, rzahl +1): print "Runde", runde for i in range(runde): LEDein(farbe[i], 1) for i in range(runde): taste = Druecken() LEDein(taste, 0.2) if(taste != farbe[i]): print "Verloren!" print "Du hast es bis Runde ", runde – 1, " geschafft" for j in range(4): GPIO.output(LED[j], True) for j in range(4): time.sleep(0.5) GPIO.
farbe = [] for i in range(rzahl): farbe.append(random.randrange(4)) Die Liste farbe wird über eine Schleife mit so vielen Zufallszahlen zwischen 0 und 3 gefüllt, wie Runden gespielt werden. Dazu wird die Methode append() verwendet, die in jeder Liste zur Verfügung steht. Diese hängt das als Parameter übergebene Element an die Liste an. LED = [23,24,25,8] for i in LED: GPIO.setup(i, GPIO.
Die Funktion Druecken() besteht aus einer Endlosschleife, die darauf wartet, dass der Benutzer einen der Taster drückt. Danach wird die Nummer des Tasters an das Hauptprogramm zurückgegeben. ok = True Nach der Definition der Funktionen startet das eigentliche Hauptprogramm und setzt als Erstes eine Variable ok auf True. Sobald der Spieler einen Fehler macht, wird ok auf False gesetzt. Ist die Variable nach der vorgegebenen Rundenzahl immer noch True, hat der Spieler gewonnen.
Das Programm zeigt auf dem Bildschirm an, dass der Spieler verloren hat und wie viele Runden er geschafft hat. Die Zahl der bestandenen Runden ist um eins kleiner als der aktuelle Rundenzähler. for j in range(4): GPIO.output(LED[j], True) Als optisch sichtbares Zeichen werden alle LEDs eingeschaltet ... for j in range(4): time.sleep(0.5); GPIO.output(LED[j], False) ... dann wird eine nach der anderen im Abstand von 0,5 Sekunden wieder ausgeschaltet. So ergibt sich ein deutlicher Abbaueffekt.
Im Gewinnfall erscheint eine Anzeige im Python-Shell-Fenster. Danach blinken alle LEDs fünfmal kurz hintereinander. GPIO.cleanup() geschlossen. 96 Die letzte Zeile wird auf jeden Fall ausgeführt.
Impressum © 2016 Franzis Verlag GmbH, Richard-Reitzner-Allee 2, 85540 Haar bei München www.elo-web.de Autor: Christian Immler ISBN 978-3-645-10145-5 Alle Rechte vorbehalten, auch die der fotomechanischen Wiedergabe und der Speicherung in elektronischen Medien. Das Erstellen und Verbreiten von Kopien auf Papier, auf Datenträger oder im Internet, insbesondere als PDF, ist nur mit ausdrücklicher Genehmigung des Verlags gestattet und wird widrigenfalls strafrechtlich verfolgt.