0145-5 Raspberry Pi verstehen und anwenden_01.indd 1 30.06.
10145-5 Raspberry Pi verstehen und anwenden_01.indd 2 30.06.
Inhalt 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 Tastatur 1.1.3 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 1.3.1 Sprache auf Deutsch umstellen 1.3.
6 LED per Pulsweitenmodulation dimmen 6.1 So funktioniert es 6.2 Zwei LEDs unabhängig dimmen 6.3 So funktioniert es 46 48 49 51 7 Speicherkartenfüllstandsanzeige mit LEDs So funktioniert es 7.1 52 54 8 Grafischer Spielwürfel 8.1 So funktioniert es 56 58 9 Analoguhr auf dem Bildschirm 9.1 So funktioniert es 63 64 10 Grafische Dialogfelder zur Programmsteuerung 10.1 So funktioniert es 10.2 Lauflicht mit grafischer Oberfläche steuern 10.2.1 So funktioniert es 10.3 Blinkgeschwindigkeit einstellen 10.3.
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.
1.1.1 Micro-USB-Handyladegerät Für den Raspberry Pi reicht jedes moderne Handynetzteil. Ältere Ladegeräte aus den Anfangszeiten der USBLadetechnik sind noch zu schwach. Schließt man leistungshungrige USB-Geräte wie externe Festplatten ohne eigene Stromversorgung an, ist ein stärkeres Netzteil erforderlich. Das Netzteil muss 5 V und mindestens 2.000 mA aufweisen. Der eingebaute Leistungsregler verhindert ein »Durchbrennen« bei zu starken Netzteilen.
Monitoren ist kein Audiokabel nötig. Wird ein PC-Monitor über ein HDMI-Kabel mit DVI-Adapter angeschlossen, geht meist an dieser Stelle das Audiosignal verloren, sodass Sie den analogen Audioausgang wieder brauchen. 1.1.8 Gelbes FBAS-Videokabel Steht kein HDMI-Monitor zur Verfügung, kann der Raspberry Pi mit einem analogen Videokabel an einen klassischen Fernseher angeschlossen werden, die Bildschirmauflösung ist hier jedoch sehr gering. Der analoge Videoausgang ist mit dem Audioausgang kombiniert.
1.2.2 Der Software-Installer NOOBS »New Out Of Box Software« (NOOBS) ist ein besonders einfacher Installer für Raspberry-Pi-Betriebssysteme. Hier braucht sich der Benutzer nicht mehr wie früher selbst mit Image-Tools und Bootblöcken auseinanderzusetzen, um eine bootfähige Speicherkarte einzurichten.
Abb. 1.2: Der PIXEL-Desktop auf dem Raspberry Pi. Das Raspbian-Linux für den Raspberry Pi verwendet die Oberfläche PIXEL, die auf dem bekannten LXDE (Lightweight X11 Desktop Environment) basiert. Sie benötigt einerseits sehr wenig Systemressourcen, andererseits ähnelt sie mit ihrem Startmenü und dem Dateimanager sehr der gewohnten Windows-Oberfläche — mit dem Unterschied, dass die Taskleiste am oberen Bildschirmrand liegt.
1.3.1 Sprache auf Deutsch umstellen Nicht immer klappt es, dass die Sprache der Benutzeroberfläche automatisch auf Deutsch umgestellt wird. Zeigt das Startmenü englische Texte, wählen Sie den Punkt Preferences/Raspberry Pi Configuration. Dieses Dialogfeld ersetzt das textbasierte Konfigurationstool früherer Raspbian-Versionen. Klicken Sie auf der Registerkarte Localisation auf den Button Set Locale. Wählen Sie dann im Feld Language die Sprache de (German) und bei Country das Land DE (Germany).
Abb. 1.4: Zeitzone einstellen. Haben Sie keine Internetverbindung, zeigt der Raspberry Pi eine falsche Uhrzeit an. Sie können in solchen Fällen über das Symbol mit dem schwarzen Bildschirm in der Taskleiste ein Kommandozeilenfenster öffnen und beispielsweise so die richtige Zeit einstellen: sudo date –s "2017-05-09 08:00:00 CEST" Die Einstellung wird anschließend mit einer Klartextanzeige von Datum und Uhrzeit quittiert: Di 09.
Abb. 1.5: Der Dateimanager auf dem Raspberry Pi in zwei verschiedenen Darstellungen. Wie viel Platz ist auf der Speicherkarte frei? Nicht nur Festplatten von PCs sind ständig voll — bei der Speicherkarte des Raspberry Pi kann das noch viel schneller gehen. Umso wichtiger ist es, den freien und insgesamt verfügbaren Platz auf der Speicherkarte immer im Blick zu haben. Die Statuszeile des Dateimanagers am unteren Fensterrand zeigt rechts den freien und den gesamten Speicherplatz auf der Speicherkarte. 1.
Abb. 1.6: Das Eingabefenster der Python-Shell. In diesem Fenster öffnen Sie vorhandene Python-Programme, schreiben neue und können auch direkt PythonKommandos interaktiv abarbeiten, ohne ein eigentliches Programm schreiben zu müssen. Geben Sie z. B. am Prompt Folgendes ein: >>> 1+2 Es erscheint sofort die richtige Antwort: 3 Auf diese Weise lässt sich Python als komfortabler Taschenrechner verwenden, was aber noch nichts mit Programmierung zu tun hat.
Abb. 1.8: 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.
codieren. Damit sie richtig dargestellt werden, wählen Sie im Menü Options/Configure IDLE und schalten auf der Registerkarte General die Option Locale-defined im Bereich Default Source Encoding ein. Abb. 1.9: Die richtige Einstellung zur Darstellung von Umlauten in Python. 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.
Abb. 1.10: Zahlenraten in Python. 1.4.2 So funktioniert es Dass das Spiel funktioniert, lässt sich einfach ausprobieren. Es stellen sich natürlich einige Fragen: Was passiert im Hintergrund? Und was bedeuten die einzelnen Programmzeilen? import random Um die zufällige Zahl zu generieren, wird ein externes Python-Modul namens random importiert, das diverse Funktionen für Zufallsgeneratoren enthält. zahl = random.
i = 0 Die Variable i hat sich unter Programmierern als Zähler für Programmschleifendurchläufe eingebürgert. Hier wird sie verwendet, um die Anzahl der Tipps zu zählen, die der Benutzer brauchte, um die geheime Zahl zu erraten. Auch diese Variable steht am Anfang auf 0. while tipp != zahl: Das Wort while (englisch für »so lange wie«) leitet eine Programmschleife ein, die in diesem Fall so lange wiederholt wird, wie tipp (die Zahl, die der Benutzer eintippt) ungleich der geheimen Zahl zahl ist.
2 Die erste LED leuchtet am Raspberry Pi Die 40-polige Stiftleiste in der Ecke des Raspberry Pi bietet die Möglichkeit, Hardware anzuschließen, um z. B. über Taster Eingaben zu tätigen oder programmgesteuert LEDs leuchten zu lassen. Diese Stiftleiste wird als GPIO bezeichnet. Die englische Abkürzung für General Purpose Input Outputt bedeutet auf Deutsch einfach »allgemeine Ein- und Ausgabe«.
• • • • • • • • 1 LED grün 1 LED blau 4 Taster 4 Widerstände 10 kOhm (Braun-Schwarz-Orange) 4 Widerstände 1 kOhm (Braun-Schwarz-Rot) 4 Widerstände 220 Ohm (Rot-Rot-Braun) 12 Verbindungskabel (Steckplatine — Raspberry Pi) 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 gesteckt werden, ohne dass man löten muss.
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.
Achten Sie besonders bei den 1-kOhm- und 10-kOhm-Widerständen genau auf die Farben. Sie 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. Dabei muss zwischen dem verwendeten GPIO-Pin und der Anode der LED ein 220-Ohm-Vorwiderstand (Rot-Rot-Braun) eingebaut werden, um den Durchflussstrom zu begrenzen und damit ein Durchbrennen der LED zu verhindern.
Abb. 2.3: 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 wird. Auch dafür braucht man keinerlei Software.
Abb. 2.4: 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. Das ist heute nicht mehr nötig, auch der früher benötigte sudo-Zugriff ist inzwischen Geschichte. 2.
Benötigte Bauteile: 1 Steckplatine 1 LED rot 1 220-Ohm-Widerstand 2 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.cleanup() Abb. 2.5: Eine LED an GPIO-Port 25. 24 10145-5 Raspberry Pi verstehen und anwenden_01.indd 24 30.06.
2.4.1 So funktioniert es Das Beispiel zeigt die 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.
GPIO-Warnungen abfangen Soll ein GPIO-Port konfiguriert werden, der nicht sauber zurückgesetzt wurde, sondern möglicherweise von einem anderen oder einem abgebrochenen Programm noch geöffnet ist, kommt es zu Warnmeldungen, die jedoch den Programmfluss nicht unterbrechen. Während der Programmentwicklung können diese Warnungen sehr nützlich sein, um Fehler zu entdecken. In einem fertigen Programm können sie einen unbedarften Anwender aber verwirren. Deshalb bietet die GPIO-Bibliothek mit GPIO.
Abb. 3.1: 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: 27 10145-5 Raspberry Pi verstehen und anwenden_01.indd 27 30.06.
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(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 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.
Die GPIO.setup-Anweisung kann einen optionalen Parameter initial enthalten, der dem GPIO-Port bereits beim Initialisieren einen logischen Status zuweist. Damit schalten wir in diesem Programm die grüne LED bereits von Anfang an ein. Die anderen beiden LEDs beginnen das Programm im ausgeschalteten Zustand. print ("Strg+C beendet das Programm") Jetzt wird eine kurze Bedienungsanleitung auf dem Bildschirm ausgegeben. Das Programm läuft automatisch. Die Tastenkombination [Strg]+[C] soll es beenden.
GPIO.output(Ampel[rot],False) GPIO.output(Ampel[gelb],False) GPIO.output(Ampel[gruen],True) Am Ende der Schleife springt die Ampel wieder auf Grün. Die rote und die gelbe LED werden ausgeschaltet, die grüne wird eingeschaltet. Die Schleife beginnt in der Grünphase der Ampel von Neuem mit einer Wartezeit von 2 Sekunden. Natürlich können Sie alle Zeiten beliebig anpassen. In der Realität hängen die Ampelphasen von den Ausmaßen der Kreuzung und den Verkehrsströmen ab.
Abb. 4.1: 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.
print ("Strg+C beendet das Programm") try: while True: 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.
for i in range(10): Jede for-Schleife benötigt einen Schleifenzähler, eine Variable, die bei jedem Schleifendurchlauf einen neuen Wert annimmt. Für einfache Schleifenzähler hat sich in allen Programmiersprachen der Variablenname i eingebürgert. Jeder andere Name ist natürlich auch möglich. Dieser Wert kann wie jede andere Variable innerhalb der Schleife abgefragt werden, was hier aber nicht nötig ist.
Abb. 4.3: 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.4: 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] 35 10145-5 Raspberry Pi verstehen und anwenden_01.indd 35 30.06.
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.OUT, initial=False) 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.
Ziemlich bald stellte sich heraus, dass die Erfinder des auf 256 Zeichen basierenden ASCII-Zeichensatzes (American Standard Code for Information Interchange) falsch lagen. Es waren Amerikaner, die nicht über den englischen Sprachraum hinausgedacht hatten. In allen wichtigen Weltsprachen, ohne die ostasiatischen und arabischen Sprachen mit ihren ganz eigenen Schriften, gibt es mehrere Hundert Buchstaben, die dargestellt werden müssen.
GPIO.setup(Ampel[taster], GPIO.IN) Der GPIO-Port des Tasters wird als Eingang tion erfolgt ebenfalls über GPIO.setup, diesmal aber mit dem Parameter GPIO.IN. definiert. Diese Defini- print ("Taster drücken, um Fußgängerblinklicht einzuschalten, Strg+C beendet das Programm") Beim Start zeigt das Programm eine erweiterte Meldung an, die mitteilt, dass der Benutzer den Taster drücken soll. while True: if GPIO.input(Ampel[taster])==True: Innerhalb der Endlosschleife ist jetzt eine Abfrage eingebaut.
Abb. 5.1: Vier LEDs mit Vorwiderständen. Anhand verschiedener LED-Blinkmuster erklären wir weitere Schleifen und Programmiermethoden in Python. Das nächste Programm bietet unterschiedliche 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.
for i in LED: GPIO.setup(i, GPIO.OUT, initial=0) z = len(LED) w = 5 t = 0.2 print print print print print print print ("Lichteffekte zur Auswahl") ("1 — Lauflicht zyklisch") ("2 — Lauflicht hin und zurück") ("3 — auf- und absteigend") ("4 — alle blinken gleichzeitig") ("5 — alle blinken zufällig") ("Strg+C beendet das Programm") try: while True: e = raw_input ("Bitte Muster auswählen: ") if e == "1": for i in range(w): for j in range(z): GPIO.output(LED[j], True) time.sleep(t) GPIO.
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 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.
w Wiederholungen t Zeit 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. Diese Variable gibt an, wie lange eine LED beim Blinken eingeschaltet ist. Die Pause danach dauert genauso lange. Der Name t hat sich für Variablen, die Zeiträume in Programmen speichern, in fast allen Programmiersprachen eingebürgert.
Muster 1 War die Eingabe eine 1, wird der hinter dieser Zeile eingerückte Programmteil ausgeführt. if e == "1": Beachten Sie, dass Einrückungen in Python nicht nur der Optik dienen. Wie Schleifen werden auch solche Abfragen mit einer Einrückung eingeleitet. Gleich ist nicht gleich gleich Python verwendet zwei Arten von Gleichheitszeichen. Das einfache = dient dazu, einer Variablen einen bestimmten Wert zuzuweisen.
Auch hier werden ineinandergeschachtelte Schleifen genutzt. 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. Listenelemente sind immer mit 0 beginnend nummeriert. Die vierte LED hat demnach die Nummer 3. Um eine Schleife rückwärts laufen zu lassen, verwenden wir die erweiterte Syntax von for...range().
Muster 4 Hat der Benutzer eine 4 eingegeben, startet ein anderes Blinkmuster. Jetzt blinken alle LEDs gleichzeitig und werden nicht nacheinander aufgerufen. elif e == "4": for i in range(w): for j in range(z): GPIO.output(LED[j], True) time.sleep(2*t) for j in range(z): GPIO.output(LED[j], False) time.
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. In unserem Fall gibt das Programm eine Meldung auf dem Bildschirm aus. Wie in den vorangegangenen Experimenten wird das Programm über einen KeyboardInterrupt beendet, indem der Benutzer die Tastenkombination [Strg]+[C] drückt.
Abb. 6.2: Eine LED an 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) in einem Programm wie eine normal leuchtende 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.
time.sleep(0.1) for c in range(100, -1, -2): p.ChangeDutyCycle(c) time.sleep(0.1) except KeyboardInterrupt: p.stop(); GPIO.cleanup() 6.1 So funktioniert es Ein Teil dieses Programms wird Ihnen bekannt vorkommen, einige Elemente aber vielleicht gar nicht, da wir an dieser Stelle einen Exkurs in die objektorientierte Programmierung machen. Am Anfang werden, wie bekannt, Bibliotheken importiert.
time.sleep(0.1) In jedem Schleifendurchlauf werden 0,1 Sekunden gewartet, bevor der nächste Durchlauf das Tastverhältnis wieder um 2 % erhöht. for c in range(100, -1, -2): p.ChangeDutyCycle(c) time.sleep(0.1) 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.
Abb. 6.3: Eine zweite LED an 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 as GPIO import time 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.
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.3 So funktioniert es Die Grundstruktur des Programms entspricht der des vorherigen Experiments mit ein paar kleinen Erweiterungen. LED = [18,25] GPIO.setup(LED[0], GPIO.OUT) GPIO.setup(LED[1], GPIO.
for c in range(0, 101, 2): p.ChangeDutyCycle(100-c) q.ChangeDutyCycle(c) time.sleep(0.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 gedimmt 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.
Abb. 7.2: 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 1 MB bis 10 MB 10 MB bis 100 MB 100 MB bis 500 MB > 500 MB Rot Rot–Gelb Gelb Gelb–Grün Grün Tab. 7.1: So wird der Füllstand der Speicherkarte angezeigt. 53 10145-5 Raspberry Pi verstehen und anwenden_01.indd 53 30.06.
import time import os g1 g2 g3 g4 = = = = 1 10 100 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.
g1 = 1; g2 = 10; g3 = 100; g4 = 500 Diese Zeilen definieren die Grenzen der Bereiche für freien Speicherplatz, an denen die Anzeige umschalten soll. Der Einfachheit halber verwendet das Programm Megabyte und nicht Byte, da man sich diese Zahlen besser vorstellen kann. Sie können die Grenzen jederzeit anders festlegen, die vier Werte müssen nur in aufsteigender Größe angeordnet sein. GPIO.setmode(GPIO.BCM) LED = [4,18,23] for i in range(3): GPIO.setup(LED[i], GPIO.
for i in range(3): GPIO.output(LED[i], int(x[i])) 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.
# -*- 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.
if ZAHL == 6: pygame.draw.circle(FELD, pygame.draw.circle(FELD, pygame.draw.circle(FELD, pygame.draw.circle(FELD, pygame.draw.circle(FELD, pygame.draw.circle(FELD, pygame.display.update() pygame.quit() WEISS, WEISS, WEISS, WEISS, WEISS, WEISS, P2, P3, P4, P5, P6, P7, 40) 40) 40) 40) 40) 40) 8.
P1 P2 P3 P4 P5 P6 P7 = = = = = = = ((160, 160)) ((60, 60)) ((160, 60)) ((260, 60)) ((60, 260)) ((160, 260)) ((260, 260)) Diese Zeilen legen die Mittelpunkte der Würfelaugen fest. Auf dem 320 x 320 Pixel großen Zeichenfeld liegen die drei Achsen der Würfelaugen jeweils auf den Koordinaten 60, 160 und 260. Das Koordinatensystem für Computergrafik Jeder Punkt in einem Fenster bzw. auf einem Surface-Objekt wird durch eine x- und eine y-Koordinate bezeichnet.
An dieser Stelle wird mit den anderen Variablen auch eine Variable namens mainloop auf True gesetzt, die später für die Hauptschleife des Spiels benötigt wird. 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 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. if ZAHL == 1: pygame.draw.circle(FELD, WEISS, P1, 40) Jetzt folgen sechs Abfragen, alle nach dem gleichen Schema. Wenn die zufällig gewürfelte Zahl einen bestimmten Wert hat, werden dementsprechend ein bis sechs Würfelaugen gezeichnet. Die dazu verwendete Funktion pygame.draw.
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. Damit schließt auch das grafische Fenster und danach das ganze Programm.
9 Analoguhr auf dem Bildschirm Die digitale Zeitanzeige, wie wir sie heute von Computern gewohnt sind, ist erst in den 70er-Jahren in Mode gekommen. Davor hatte man jahrhundertelang die Uhrzeit analog mit Zeigern auf einem Zifferblatt angezeigt. Der Digitaluhrboom ist in den letzten Jahren schon wieder etwas abgeebbt, da man erkannt hat, dass Analoguhren schneller und bei schlechten Wetterbedingungen oder auf große Entfernungen, wie zum Beispiel auf Bahnhöfen, klarer abzulesen sind.
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.circle(FELD, SCHWARZ, punkt(190, i), 2) for i in range(12): pygame.draw.circle(FELD, SCHWARZ, punkt(190, i * 5), 4) mainloop = True s1 = 0 while mainloop: zeit = time.localtime() s = zeit.tm_sec m = zeit.tm_min h = zeit.tm_hour if h > 12: h = h — 12 hm = (h + m / 60.0) * 5 if s1 <> s: pygame.draw.circle(FELD, WEISS, MP, 182) pygame.draw.
ROT = (255, 0, 0) WEISS = (255, 255, 255) SCHWARZ = (0, 0, 0) Die drei in der Grafik verwendeten Farben werden in drei Variablen gespeichert. 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.
Der Rückgabewert der Funktion ist ein geometrischer Punkt mit den errechneten Koordinaten x1 und y1, der wie alle Punkte in doppelte Klammern gesetzt wird. Nach der Definition dieser Funktion wird das Zifferblatt gezeichnet. 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.
Zeitdarstellung bei Analoguhren Je nach verwendeter Mechanik gibt es zwei unterschiedliche Anzeigen bei Analoguhren. Bei echten analog laufenden Uhren führt der Minutenzeiger eine gleichförmige Kreisbewegung aus, bei digital gesteuerten Uhren, wie zum Beispiel Bahnhofsuhren, springt er zur vollen Minute um eine ganze Minute weiter. Letzteres Verfahren hat den Vorteil, dass die Uhrzeit besser auf einen Blick minutengenau abgelesen werden kann.
Die gleiche Funktion zeichnet auch die anderen beiden Zeiger der Uhr. pygame.draw.line(FELD, SCHWARZ, MP, punkt(170, m), 4) Diese Zeile zeichnet den Minutenzeiger als Linie mit einer Breite von 4 Pixeln vom Mittelpunkt aus 170 Pixel lang in dem Winkel, der durch den Minutenwert angegeben wird. pygame.draw.
Die Strukturen des grafischen Toolkits Tk unterscheiden sich etwas von Python und mögen auf den ersten Blick ungewöhnlich erscheinen. Deshalb fangen wir mit einem ganz einfachen Beispiel an: Eine LED soll über Buttons in einem Dialogfeld ein- und ausgeschaltet werden. Benötigte Bauteile: 1 Steckplatine 1 LED rot 1 220-Ohm-Widerstand 2 Verbindungskabel Abb. 10.1: Eine einzelne LED an GPIO-Port 4. 69 10145-5 Raspberry Pi verstehen und anwenden_01.indd 69 30.06.
Schließen Sie eine LED über einen Vorwiderstand an 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).pack(side=LEFT) Button(root, text="Aus", command=LedAus).
Jetzt wird eine Funktion LedEin() definiert, die die LED einschaltet. def LedAus(): GPIO.output(LED,False) 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.
Die Methode .pack() kann 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 gesetzt wird. Button(root, text="Aus", command=LedAus).pack(side=LEFT) Nach dem gleichen Schema wird 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.
Benötigte Bauteile: 1 Steckplatine 1 LED rot 1 LED gelb 1 LED grün 1 LED blau 4 220-Ohm-Widerstände 5 Verbindungskabel Abb. 10.4: Vier LEDs blinken in unterschiedlichen Mustern. 73 10145-5 Raspberry Pi verstehen und anwenden_01.indd 73 30.06.
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.2 muster = [("Lauflicht nach links",1), ("Blinken",2), ("Lauflicht nach rechts",3) ] root = Tk() root.title("LED") v = IntVar() v.set(1) def LedEin(): e = v.
10.2.1 So funktioniert es Am Anfang werden wieder die notwendigen Bibliotheken importiert. In Ergänzung zum letzten Programm ist auch die time-Bibliothek dabei, die für die Wartezeiten bei den LED-Blinkeffekten benötigt wird. GPIO.setmode(GPIO.BCM) LED = [4,18,23,24] for i in LED: GPIO.setup(i, GPIO.OUT, initial=0) Anschließend wird eine Liste für die vier LEDs definiert. Die entsprechenden GPIO-Ports werden als Ausgänge definiert und auf 0 gesetzt, damit alle LEDs am Anfang ausgeschaltet sind. w = 5 t = 0.
Abhängig von der Benutzerauswahl, werden drei verschiedene Programmschleifen gestartet: 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) Im ersten Fall läuft eine Schleife fünfmal durch. Sie schaltet nacheinander jede der vier LEDs ein, lässt sie 0,2 Sekunden leuchten und schaltet sie wieder aus. Die fünf Wiederholungen und die 0,2 Sekunden Blinkzeit sind über die Variablen w und t am Anfang des Programms definiert.
Die Schleife legt auf diese Weise drei Radiobuttons an, deren erster Parameter immer root ist, das Widget, in dem die Radiobuttons liegen. Der Parameter text eines Radiobuttons gibt den anzuzeigenden Text an, der in diesem Fall aus der Variablen txt gelesen wird. Der Parameter variable legt eine zuvor deklarierte Tk-Variable fest, in die nach der Auswahl durch den Benutzer der Wert des ausgewählten Radiobuttons eingetragen wird.
Verwendung von Schiebereglern Schieberegler bieten eine sehr intuitive Methode zur Eingabe von Zahlenwerten innerhalb eines bestimmten Bereichs. Auf diese Weise spart man sich eine Plausibilitätsabfrage, die ermittelt, ob der Benutzer einen Wert eingegeben hat, den das Programm auch sinnvoll umsetzen kann, da Werte außerhalb des durch den Schieberegler vorgegebenen Bereichs nicht möglich sind. Richten Sie den Schieberegler immer so ein, dass die Werte für den Benutzer vorstellbar sind.
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.output(LED[3-j], False) Label(root,text="Bitte Button klicken, um das Lauflicht zu starten").pack() for txt, m in muster: Radiobutton(root, text = txt, variable = v, value = m).pack(anchor=W) Label(root, text="Geschwindigkeit").pack() Scale(root, orient=HORIZONTAL, from_ = 1, to = 10, variable = g).pack() Button(root, text="Start", command=LedEin).pack(side=LEFT) root.
Ganzzahlen in Fließkommawerte umrechnen Das Ergebnis einer Berechnung wird automatisch als Fließkommazahl gespeichert, wenn mindestens einer der Werte in der Formel eine Fließkommazahl ist. Sind alle Werte in der Formel Ganzzahlen (Integer), wird das Ergebnis ebenfalls auf eine Ganzzahl gekürzt. Die Definition des Labels und der Radiobuttons im Dialogfeld werden aus dem vorhergehenden Beispiel übernommen. Label(root, text="Geschwindigkeit").
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.
Benötigte Bauteile: 2 Steckplatinen 1 LED rot 1 LED gelb 1 LED grün 1 LED blau 4 220-Ohm-Widerstände 4 1-kOhm-Widerstände 4 10-kOhm-Widerstände 4 Taster 10 Verbindungskabel 4 kurze Drahtbrücken Abb. 11.2: PiDance mit LEDs und Tastern auf zwei Steckplatinen. Die Taster sind gegenüber 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.
rzahl = 10 farbe = [] for i in range(rzahl): farbe.append(random.randrange(4)) LED = [23,24,25,8] for i in LED: GPIO.setup(i, GPIO.OUT, initial=False) TAST = [4,17,21,22] for i in TAST: GPIO.setup(i, GPIO.IN) def LEDein(n, z): GPIO.output(LED[n], True) time.sleep(z) GPIO.output(LED[n], False) time.sleep(0.15) def Druecken(): 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.
for i in range(5): for j in range(4): GPIO.output(LED[j], True) time.sleep(0.05) for j in range(4): GPIO.output(LED[j], False) time.sleep(0.05) GPIO.cleanup() 11.1 So funktioniert es Das Programm bietet viel Neues, die Grundlagen der GPIO-Steuerung sind aber bekannt. rzahl = 10 Nach dem Import der Module time, random und RPi.GPIO wird eine Variable rzahl angelegt, die die Anzahl zu spielender Runden festlegt.
Die Funktion LEDein() schaltet eine LED ein und lässt sie eine bestimmte Zeitlang leuchten. Die Funktion verwendet zwei Parameter. Der erste Parameter, n, gibt die Nummer der LED zwischen 0 und 3 an, der zweite Parameter, z, die Zeit, die die LED leuchten soll. Nachdem die LED wieder ausgeschaltet wurde, wartet die Funktion noch 0,15 Sekunden, bis sie beendet wird, damit man beim mehrfachen Aufrufen kurze Pausen zwischen dem Aufleuchten der LEDs sieht.
taste = Druecken() Dazu wird die Funktion Druecken() aufgerufen, die wartet, bis der Spieler einen der Taster gedrückt hat. Die Nummer des gedrückten Tasters wird in der Variablen taste gespeichert. LEDein(taste, 0.2) Nach dem Drücken einer Taste leuchtet die entsprechende LED für 0,2 Sekunden auf. if(taste != farbe[i]): Wenn die zuletzt gedrückte Taste nicht der Farbe an der entsprechenden Position in der Liste entspricht, hat der Spieler verloren. Der Operator != steht für ungleich.
GPIO.output(LED[j], True) time.sleep(0.05) for j in range(4): GPIO.output(LED[j], False) time.sleep(0.05) Im Gewinnfall erscheint eine Anzeige im Python-Shell-Fenster. Danach blinken alle LEDs fünfmal kurz hintereinander. GPIO.cleanup() Die letzte Zeile wird auf jeden Fall ausgeführt. Hier werden die verwendeten GPIO-Ports geschlossen. 87 10145-5 Raspberry Pi verstehen und anwenden_01.indd 87 30.06.
10145-5 Raspberry Pi verstehen und anwenden_01.indd 88 30.06.
Index A Ampel 25 Fußgängerampel 29 Anode 20 ASCII-Zeichensatz 36 Audiokabel 6 GPIO.cleanup 24 GPIO.output 24 GPIO.PWM 47 GPIO.setmode 24 GPIO.
P Passwort 9 PiDance 79 print 12 Programmschleife 16 Pull-down-Widerstand 32 Pulsweitenmodulation 45 PWM 45 Frequenz 50 Python 11 Python, Flashcards 13 freier Platz 11, 51 Steckplatine 18 Stromversorgung 6 T Tastatur 6 Taster 21, 32 Tastverhältnis 45 time 24 try 28 U R random 15, 44 range 32, 43 Raspbian 7, 8 raw_input 41 RPi.
10145-5 Raspberry Pi verstehen und anwenden_01.indd 91 30.06.
Vorsicht Sie sollten auf keinen Fall irgendwelche GPIO-Pins miteinander verbinden und abwarten, was passiert. Beachten Sie stattdessen 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.