1 Rot Grün Blau
Lass uns nun endlich den ersten großen Schritt wagen und die erste Schaltung auf dem Steckbrett aufbauen. Dieses Mal verwendest du eine dreifarbige LED - eine RGB-LED. Diese LEDs kann man dazu bringen in allen erdenklichen Farben zu leuchten, indem man die drei Elementarfarben rot, grün und blau entsprechend mischt. Dazu erfährst du aber später mehr.

Die Beinchen der LED kann man mit einem Seitenschneider auf Länge kürzen und mit einer Zange auseinander biegen. Auf dem Foto kannst du sehen, wie sie danach aussehen sollte. Das längste Beinchen ist der Minus-Anschluss der LED und wird auch Kathode genannt. Es sollte nach dem Kürzen immer noch das längste Beinchen sein.
Die Schaltung aufbauen
Baue jetzt die RGB-LED mit den drei Widerständen (zu je 47 Ohm) und das Circuitpython-Board wie in der Skizze abgebildet auf.
Auf einem Steckbrett gibt es zwei Plus- und zwei Minus-Leitungen. Plus ist rot. Minus ist blau.
Wie du siehst, verwenden wir auch schwarze Kabel für Minus. Aber Farben spielen nur für die Übersichtlichkeit eine Rolle. Dem Strom ist es egal, welche Farbe ein Kabel hat.
Achte darauf, dass auch die Kathode über das schwarze Kabel mit der Minus-Leitung verbunden ist.
Verbinde niemals eine Leitung direkt mit einer der Minus-Leitungen. Das nennt man Kurzschluss und wird das Board zerstören.

Foto der Schaltung
Wenn du alles richtig angeschlossen hast, müsste der Aufbau ungefähr so ausschauen:

Das Programm kopieren
Verbinde jetzt die Schaltung mit dem Computer und kopiere den Code links, indem du den Inhalt der Datei code.py damit ersetzt und speichere die Änderung ab.
1import board
2import time
3import digitalio
4
5 led_red = digitalio.DigitalInOut(board.D10)
6led_green = digitalio.DigitalInOut(board.D11)
7 led_blue = digitalio.DigitalInOut(board.D12)
8 led_red.direction = digitalio.Direction.OUTPUT
9led_green.direction = digitalio.Direction.OUTPUT
10 led_blue.direction = digitalio.Direction.OUTPUT
11
12while True:
13 print("Beginne Schleife von neuem.")
14 led_red.value = true
15 time.sleep(0,5)
16 led_red.value = False
17 time.Sleep(0.5)
Fehler machen
Wenn die LED jetzt nicht rot blinkt, haben sich vermutlich Fehler in das Programm eingeschlichen.
Das ist kein Beinbruch, sondern in diesem Fall Absicht! Wenn man ein guter Programmierer werden will, ist es absolut wichtig, dass man versteht, was ein Fehler bedeutet! Darum ist der Code, den du eben kopiert hast, übersät mit Fehlern!
Auf der nächsten Seite lernst du, wie du mit einem Error umgehst. Nur eine Sache vorweg: Alle Programmierer - selbst die besten - machen ständig Fehler. Wichtig ist es deshalb, dass man versteht, wie sie zustande kommen.
2 Fehler verstehen
Behandle jeden Fehler als eine Gelegenheit, etwas zu lernen.
Wenn du verstehst, wodurch ein Fehler ausgelöst wurde, hast du wieder etwas Neues über die Programmiersprache gelernt. Ließ dir darum unbedingt immer die Fehlermeldungen genau durch und versuche zu verstehen, was sie bedeuten.
Du wirst mit der Zeit merken, ob dir ein ähnlicher Fehler schon einmal passiert ist und immer schneller die Ursache des Fehlers ausfindig machen können.
Computer verzeihen nicht
Eigentlich müsste es heißen: Programmiersprachen sind extrem penibel und verzeihen keinen Tippfehler. Aber wenn sie das nicht wären, könnte es Missverständnisse geben und das wäre noch schlimmer als einfach nichts zu tun.

Wenn du auf Fehler stößt, liegt es normalerweise nicht daran, dass du sie absichtlich herbeigeführt hast. In der Regel sind es total banale Kleinigkeiten (Syntaxfehler), die einen Error auslösen und dein Programm sicherheitshalber abstürzen lassen. Aber ob du es glaubst oder nicht: Es ist gut, dass es Fehler gibt! Python zeigt dir durch Fehler, dass er nicht versteht, was du verlangst.
Fehlermeldungen verstehen
Über die serielle Konsole bekommst du die Fehlermeldungen mitgeteilt. Das ist ein großer Vorteil gegenüber Arduino. Wenn du dir die Meldung genau durchliest, erhältst du genug Informationen, um den Fehler zu finden und zu beheben. Die Zeile, die einen Fehler ankündigt, lautet immer:
Zurückverfolgung (jüngste Aufforderung zusetzt)
Die darauf folgenden Zeilen geben Auskunft darüber, wo Python den Fehler vermutet.
Datei "code.py", Zeile 5
In der Zeile steht der Dateiname und die Zeile, in der Python nicht mehr weiter wusste. Die darauf folgende Zeile zeigt die Art des Fehlers an.
Manchmal sitzt der Fehler aber auch an einer anderen Stelle. Es lohnt sich also auch die Zeilen davor anzusehen.
IndentationError
IndentationError: unerwarteter Einzug (Einrückung) Bitte Leerzeichen am Zeilenanfang kontrollieren!
Betrachte den Code und wirf einen Blick auf Zeile 5. Die Zeile beginnt mit einem Leerzeichen. Leerzeichen haben in der Programmiersprache Python eine Bedeutung und dürfen nur verwendet werden, wenn ein neuer Block nach einem while
oder nach einem if
bzw. else
beginnt. In den Zeilen 5 bis 10 muss das Leerzeichen also weg.
Einen IndentationError erhältst du also, wenn du an einem Zeilenanfang unerwartet viele Leerzeichen schreibst. Du darfst aber gerne vor das Gleichheitszeichen Leerzeichen einfügen.
led_red = digitalio.DigitalInOut(board.D10)
led_green = digitalio.DigitalInOut(board.D11)
led_blue = digitalio.DigitalInOut(board.D12)
led_red.direction = digitalio.Direction.OUTPUT
led_green.direction = digitalio.Direction.OUTPUT
led_blue.direction = digitalio.Direction.OUTPUT
Verbessere den Fehler und speichere ab!
NameError
Der nächste Fehler lässt nicht lange auf sich warten:
Datei "code.py", Zeile 14, in <module>
NameError: Name 'true' ist nirgends definiert worden. (Schreibweise kontrollieren)
Die nächste Zeile zeigt wieder die Art des Fehlers an. Wirf einen Blick auf Zeile 14 und versuche selbst herauszufinden, was hier falsch ist.
Verbessere den Fehler und speichere ab!
TypeError
Weiter gehts mit dem nächsten Fehler in Zeile 15
Datei "code.py", Zeile 15, in <module>
TypeError: Funktion nimmt 1 Argumente ohne Keyword an, aber es wurden 2 angegeben
Wenn man in Deutschland zur Schule geht, lernt man das Komma als Dezimaltrennzeichen kennen. In einigen Ländern - unter anderem in Großbritannien und den Vereinigten Staaten - benutzt man allerdings den Punkt an Stelle des Kommas. Der Punkt hat sich deshalb in fast allen Programmiersprachen als Dezimaltrennzeichen durchgesetzt.
Das Komma hat in den meisten Programmiersprachen eine andere Bedeutung. Mit einem Komma trennt man die Argumente, die man an eine Methode übergeben möchte, voneinander. Die Zeile time.sleep(0,5)
liest sich also:
Es sollte aber heißen:
Verbessere den Fehler und speichere!
AttributeError
Und schon wieder ein neuer Fehler:
Datei "code.py", Zeile 17, in <module>
AttributeError: 'module' Objekt hat kein Attribut 'Sleep'
Wirf einen Blick auf Zeile 17 und versuche wieder selbst den Fehler zu finden.
time.Sleep(0.5)
Fazit
Du hast nun hoffentlich verstanden, dass es etwas ganz Normales ist, beim Programmieren Fehler zu machen. Mache dich bereit, dass du in Zukunft viel Zeit damit zubringen wirst, Fehler aufzuspüren. Du kennst jetzt vier wichtige Error-Typen. Es gibt aber noch eine ganze Menge weiterer. Manchmal ist es hilfreich im Internet recherchieren, um herauszufinden was sie bedeuten. Profis schreiben sogar ihre eigenen Fehlertypen für ihre Module.
Aufgaben
Laden
3 Die Konsole und die REPL
Gute Arbeit! Du hast alle Fehler gefunden und verbessert. Wenn du nun einen Blick in deine serielle Konsole wirfst, wird dort ständig neuer Text gestreamt und die rote LED sollte nun auch endlich blinken.

Der print-Befehl
Die serielle Konsole - unten im Fenster - zeigt dir alle, von deinem Code generierten Ausgaben an. Das ist praktisch, wenn du zum Beispiel Daten von einem Sensor anzeigen möchtest oder wie im Beispielprogramm oben, wann eine Schleife von vorne beginnt.
Der print-Befehl ist also perfekt dazu geeignet, um dir vom Programm eine Rückmeldung geben zu lassen. Du kannst sie auch gut verwenden, um Fehler aufzuspüren. Wenn dein Code nicht funktioniert und du herausfinden möchtest, wo er versagt, kannst du print
-Anweisungen an verschiedenen Stellen platzieren, und beobachten, welche Anweisung ausgeführt werden und welche nicht.
Die serielle Konsole ist ein mächtiges Werkzeug, wie du in den nächsten Abschnitten sehen wirst. Du wirst bemerkt haben, dass dein Programm schon eine ganze Weile ununterbrochen läuft. Das ist auch gut so. Um uns im nächsten Abschnitt der REPL zuzuwenden, werden wir das Programm aber jetzt brutal abbrechen.
Die CircuitPython-REPL
Drückte die Tastenkombination Strg + C um das laufende Programm abzuwürgen und drücke anschließend eine beliebige Taste um dich mit der REPL zu verbinden.

Die Fehlermeldung KeyboardInterrupt
zeigt einen Programmabbruch durch die Tastatur an. Wenn du dir die Zeile darüber genauer anschaust, siehst du, welche Zeile in deinem Code kurz vor dem Programmabbruch ausgeführt wurde. Der Python Interpreter möchte dir mit dieser Fehlermeldung mitteilen, dass das Programm unerwartet abgebrochen wurde (unerwartet für CircuitPython).
Die ersten Informationen, die du von der REPL erhältst, sind …
die CircuitPython-Versionsnummer,
das Datum, an dem diese Version erstellt wurde,
der Name des Boards und
der Name des Mikrochips.
Danach erscheint der REPL-Prompt: >>>
REPL steht für read-evaluate-print-loop. Das bedeutet übersetzt: Lesen - Ausführen - Anzeigen - Wiederholen.
Du kannst dir die REPL wie einen Chat mit dem Python-Interpreter vorstellen. Python wartet auf deinen Befehl (read) und führt ihn aus (evaluate), wenn du die Eingabetaste drückst. Wenn der Befehl ausgeführt wurde, erhältst du (manchmal) eine Rückmeldung (print) und das Spiel wiederholt (loop) sich so lange von vorn bis du die REPL verlässt.
Der Prompt >>>
zeigen dir an, dass Python auf deinen nächsten Befehl wartet. Die farbige LED auf deinem Board sollte außerdem weiß leuchten.
Teste doch mal, ob Python rechnen kann.

Führe als nächstes help()-Befehl aus. Dieses Kommando begrüßt uns in der REPL und zeigt uns, wo wir mit der Erkundung der REPL beginnen sollen.
Tippe help()
ein und bestätige die Ausführung mit der Eingabetaste:

Der erste Teil der Nachricht ist ein weiterer Verweis auf die verwendete CircuitPython-Version. Darauf folge eine URL auf die englischsprachigen CircuitPython-Anleitungen.
Interessant ist die letzte Zeile. Probieren wir aus, was dort steht.
Erinnerst du dich noch daran, als wir über das Importieren von Modulen/Bibliotheken sprachen. Genau darum geht es hier! Lass uns das ausprobieren!
Gebe das Kommando help("modules")
ein.
Es erscheint nun eine Aufzählung aller integrierten Module:

Die import-Anweisung und der dir-Befehl
Dies ist eine Liste aller in CircuitPython integrierten Kernbibliotheken. Im Kapitel CircuitPython Module haben wir kurz angesprochen, dass zum Beispiel das Modul board über die Pins (Anschlüsse) des Boards Bescheid weiß.
Gib jetzt import board
in die REPL ein und drücke die Eingabetaste.
Es erscheint sofort eine neue Eingabeaufforderung und es sieht so aus, als sei nichts passiert, aber das ist nicht der Fall! Wenn du dich noch erinnerst, teilt die import-Anweisung Python mit, dass das Programm dieses Modul verwenden möchte.
Möchtest du dir anschauen, was ein Modul anbietet, so gebe einfach dir(board)
ein. Du bekommst wieder eine Liste angezeigt.

Wow! Was ist das? Du bekommst eine Liste aller Pins, die du in deinem Code verwenden kannst, angezeigt. Die Board-Liste unterscheidet sich je nach verwendetem Board geringfügig.
Fazit
Du weißt nun, wie du einzelne Codezeilen in der REPL testen kannst. Die REPL eignet sich darum auch fantastisch um Fehler in deinen Programmen aufzuspüren, indem du deinen Code Zeile für Zeile eingibst und schaust, wo er versagt. Außerdem du kannst nachschauen, welche Bibliotheken (Module) dir zur Verfügung stehen, und diese Bibliotheken untersuchen.
Du kannst im Prinzip auch ganze Programme in die REPL schreiben, um sie zu testen. Denke jedoch daran, dass der Code, den du in die REPL eingegeben hast, nirgendwo gespeichert wird. Wenn du etwas getestet hast, das du behalten möchtest, dann speichere den Code irgendwo auf deinem Computer oder direkt auf dem Board!
Aufgaben
Laden
Laden
Laden
Wir verlassen nun wieder die REPL um fortzufahren.
4 Die Hardware verstehen
In diesem Kapitel werfen wir einen Blick auf die Hardware und das Board selbst.
Betrachte zunächst einmal das Board mit all seinen Bauteilen und der weißen Beschriftung. Du kennst hoffentlich bereits den USB-Anschluss und weißt, wo der Mikrochip versteckt wurde (unter der Metallkappe rechts). Den großen SWD-Anschluss in der Mitte kannst du getrost ignorieren.

Adafruit nrf52840 Express
Über die schwarze Buchse oben links kannst du dein Board mit einer LiPo-Batterie betreiben. Eine volle Batterie kann das Board bis zu mehreren Monaten mit Strom versorgen.
Erinnere dich bitte an die Liste der Pins, die du erhältst, wenn du dir(board)
in der REPL ausführst. Hier ist sie nochmal.

Ein genauer Blick entlarvt, dass der Aufdruck auf der Platine nicht exakt mit der Liste übereinstimmt. Das solltest du solltest im Hinterkopf behalten.
Die Pins D5
, D6
, D9
bis D13
, sind auf dem Board ohne das D aufgedruckt. Pin D2
und Pin D13
sind eine Ausnahme. Beachte, dass D13
und RED_LED
identisch sind.
Pinout
Dein Adafruit Feather nRF52840 Express hat 28 Anschlüsse - auch Pins genannt. Wir werden hier auf die wichtigsten eingehen. Zwei Pins mit einer ganz besonderen Funktion - SCL
und SDA
- lernst du später im Kurs kennen.
Power Pins
3V: Dieser Pin ist mit dem Ausgang des integrierten 3,3 V-Spannungsreglers verbunden. Dieser Pin ist der PLUS-Pol. Er wird mit der roten Versorgungsleitung verbunden.
GND ist der MINUS-Pol. Er ist immer mit der blauen Versorgungsleitung verbunden.

Digitale Ein- und Ausgabe
Du kannst alle Pins mit einem D am Anfang frei verwenden, um zum Beispiel LEDs oder Taster anzuschließen. Die meisten dieser Pins haben, wie schon gesagt, auf der Platine kein D aufgedruckt.
Eine Besonderheit sind die Pins RED_LED
, BLUE_LED
und SWITCH
. Du hast bereits beide LEDs auf dem Board angesteuert; wie du den kleinen Taster verwendest, lernst du jetzt.
Achtung: Du solltest unbedingt darauf achten, dein Board keinesfalls zu überlasten. Das heißt, dass die maximale Stromstärke von 10mA pro Pin nicht überschritten werden darf. Die Gesamtstromstärke für das Board darf 30mA nicht langfristig überschreiten. Zu viele LEDs kannst du also nicht anschließen, ohne dass dein Board Schaden nimmt.
5 Den Taster abfragen
Um erste Erfahrungen im Umgang mit Hardware zu machen, ist es ratsam, mit der digitalen Ein- und Ausgabe zu beginnen. Mit dem Ein- und Ausschalten von LEDs hast du schon erste Erfahrungen mit digitaler Ausgabe gemacht. Hier lernst du, wie du einen Taster als digitalen Eingang verwendest, um eine LED zu steuern.
Neue Datei anlegen
Erstelle aber zuerst ein neues Python-Skript, indem du in der Symbolleiste auf die Schaltfläche Neu klickst. Du hast jetzt zwei Tabs offen - eines für jede Datei.

Das Programm
Kopiere bitte den Inhalt aus deiner code.py in die neue Datei und speichere sie unter dem Namen rgb_led.py auf dem Laufwerk CIRCUITPY ab.
Überschreibe jetzt den Inhalt von code.py mit diesem neuen Programm und speichere die Datei mit Strg + S.
1import board
2import digitalio
3import time
4
5button = digitalio.DigitalInOut(board.SWITCH)
6button.switch_to_input(pull=digitalio.Pull.UP)
7
8
9while True:
10 if not button.value:
11 print('pressed')
12 else:
13 print('not pressed')
14 time.sleep(0.5)
15

Falls du noch in der REPL bist, musst du jetzt einen Soft-Reset durchführen indem du in der REPL die Strg-Taste gedrückt hältst und gleichzeitig D drückst.
Hast du schon herausgefunden, welchen Taster du drücken musst?
Hinweis: Er ist sehr klein. Wenn du versehentlich den Reset-Taster betätigt hast, ist das ist nicht dramatisch. Du hast dann einen Hard-Reset durchgeführt. Lies bitte weiter.
Was tun bei einem Hard-Reset
Wie du bereits weißt, wird ein Hard-Reset durchgeführt, wenn du den Reset-Taster auf dem Board drückst. Das kann dein Board nicht zerstören. Anders als ein Computer, bei dem ein Drücken der Reset-Taste böse Folgen haben kann, sind Mikrocontroller unempfindlich, wenn die Stromzufuhr plötzlich aus bleibt.
Genau das passiert nämlich, wenn du einen Hard-Reset durchführst. Du könntest genauso gut den USB-Stecker ziehen und ihn wieder einstecken.
Die Folgen eines Hard-Resets, die du direkt bemerkst, ist, dass die RGB-LED auf dem Board kurz bunt zu blinken beginnt und dass die serielle Konsole nicht mehr reagiert. Mache in diesem Fall folgendes:
Konsole schließen mit Schaltfläche Seriell
Konsole wieder öffnen mit Schaltfläche Seriell
Strg+C und Strg+D nacheinander drücken.
Danach ist wieder alles beim Alten. Am besten, du merkst dir die Abfolge gut.
6 Taster anschließen
In vorigen Kapitel hast du den kleinen Taster auf dem Feather Board abgefragt. Wir wollen jetzt einen externen Taster an das Board anschließen und im Anschluss versuchen wir den Programmcode zu verstehen. Vorweg solltest du mit einer Zange die vier Beinchen der Taster um 90° drehen, damit sie in das Steckbrett passen. Hier ist ein Foto, wie es aussehen sollte.

Baue jetzt die Schaltung auf. Du siehst, warum wir neben der LED Platz gelassen haben.

Um den Taster abzufragen, musst du nur zwei Änderungen am vorigen Programm machen.
1import board
2import digitalio
3import time
4
5button = digitalio.DigitalInOut(board.D13)
6button.switch_to_input(pull=digitalio.Pull.DOWN)
7
8
9while True:
10 if button.value:
11 print('pressed')
12 else:
13 print('not pressed')
14 time.sleep(0.5)
15
Der Code unterscheidet sich bei genauem Betrachten nur an wenigen Stellen vom Code auf der vorherigen Seite. Du hast die Stelle sicher schon gefunden?
Es werde Licht
Ein Taster und eine RGB-Leuchtdiode. Das passt gut zusammen. Lass die grüne LED leuchten, wenn der Taster gedrückt wird.
Kopiere die Zeilen 5 bis 10 und ändere die Zeilen 18 und 20 ab.
1import board
2import digitalio
3import time
4
5led_red = digitalio.DigitalInOut(board.D10)
6led_green = digitalio.DigitalInOut(board.D11)
7led_blue = digitalio.DigitalInOut(board.D12)
8led_red.direction = digitalio.Direction.OUTPUT
9led_green.direction = digitalio.Direction.OUTPUT
10led_blue.direction = digitalio.Direction.OUTPUT
11
12button = digitalio.DigitalInOut(board.D13)
13button.switch_to_input(pull=digitalio.Pull.DOWN)
14
15
16while True:
17 if button.value:
18 led_green.value = True
19 else:
20 led_green.value = False
21
Aufgabe
Es ist wieder an Zeit zu Experimentieren.
Die blaue LED soll immer leuchten wenn der Taster nicht gedrückt wird und die rote soll leuchten wenn der Taster gedrückt wird. Viel Spaß bei der Aufgabe.
Der Magnetkontaktschalter
Ein Magnetkontaktschalter funktioniert im Prinzip wie ein Taster. Bringt man die Hälfte mit dem Magneten (das Teil ohne Kabel) in die Nähe des Reedschalters (das ist das weiße Teil mit den beiden Kabeln), so wird der Kontakt geschlossen.

In diesem Programm werden beide "Taster" verwendet, um zwei der drei LEDs zu schalten.
Kopiere die beiden neuen Teile in die Datei.
1import board
2import digitalio
3import time
4
5led_red = digitalio.DigitalInOut(board.D10)
6led_green = digitalio.DigitalInOut(board.D11)
7led_blue = digitalio.DigitalInOut(board.D12)
8led_red.direction = digitalio.Direction.OUTPUT
9led_green.direction = digitalio.Direction.OUTPUT
10led_blue.direction = digitalio.Direction.OUTPUT
11
12button = digitalio.DigitalInOut(board.D13)
13button.switch_to_input(pull=digitalio.Pull.DOWN)
14door = digitalio.DigitalInOut(board.D9)
15door.switch_to_input(pull=digitalio.Pull.UP)
16
17
18while True:
19 if button.value:
20 led_green.value = True
21 else:
22 led_green.value = False
23
24 if door.value:
25 led_red.value = True
26 else:
27 led_red.value = False
28
Teste nun zuerst das Programm und überlege dir, warum der Programmcode das tut, was er tut. Wenn du glaubst das Programm verstanden zu haben, versuche das Programm abzuändern. Fahre anschließend auf der nächsten Seite fort.
7 Bedingte Verzweigung
Neben den Schleifen ist die Bedingte Verzweigungen die wichtigste Kontrollstruktur in jeder Programmiersprache. Du hast sie im aktuellen Programm schon benutzt. Der Aufbau ist immer der Gleiche.
Wenn die Bedingung wahr ist, dann soll etwas passieren und wenn sie nicht wahr ist, dann soll etwas anderes passieren.
if «Bedingung»
«tu was»
else
«tu was anderes»

Der else
-Teil kann auch weggelassen werden.
if «Bedingung»
«tu was»

True und False
Wir wollen hier noch einmal kurz auf die beiden Wahrheitswerte True
und False
, die du schon bei der while
-Schleife im letzten Kurs kennengelernt hast, zurückkommen.
In der booleschen Algebra - keine Angst, es ist ganz einfach - beschäftigt man sich mit Aussagen, entweder wahr (True
) oder Falsch (False
) sein können. Entscheide selbst, welche der folgenden Aussage wahr (True
) und welche nicht wahr (False
) ist. Zwei Gleichheitszeichen sind gleichbedeutend mit "ist gleich"
11 + 1 == 2
22 + 5 == 6
34 < 4
45 >= 5
5button.value == True
6tempsensor.value > 10
Wie du siehst, es gibt Aussagen, die immer wahr sind und solche, die sowohl wahr als auch falsch sein können. Wenn der Taster gerade gedrückt ist, dann ist wäre die Aussage 5 wahr, sonst nicht. Und wenn die Temperatur größer als 10 ist, kann wahr oder falsch sein. Eine Aussage, die immer wahr ist, kann man einfach durch True
ersetzen, wie du es von der Endlosschleife schon kannst. Solche Aussagen sind langweilig.
Probiere man ob, du in der while-Schleife anstelle von True auch 1+1==2 schreiben kannst. Was geht noch?
Fällt dir auch ein Beispiel ein, welches du anstelle von False
schreiben könntest?
Betrachte noch einmal die Zeile 5. Wenn der Taster gedrückt ist, dann steht doch dort True
== True
. Nur Anfänger schreiben solche Bedingungen. Es ist nämlich vollkommen ausreichend, wenn du einfach button.value
schreibt - so wie im letzten Programm in Zeile 18. Man sagt: value
ist eine Variable vom Typ boolean.
Man kann noch viel mehr Sachen mit booleschen Variablen anfangen. Du kannst dir diesen Artikel auf Serlo dazu anschauen.
Das Programm auf der vorherigen Seite ist ein sehr gutes Beispiel dafür, dass man manchmal gar keine Bedingte Verzweigung braucht. Schauen wir uns die 8 Zeilen noch einmal an:
while True:
if button.value:
led_green.value = True
else:
led_green.value = False
if door.value:
led_red.value = True
else:
led_red.value = False

Überlege dir, wie du aus den acht Zeilen im Schleifenrumpf zwei machen kannst. Wenn der Taster gedrückt ist, dann ist der Wert von button.value
True und so soll auch die LED leuchten - also True
sein. Bei der zweiten Verzweigung genauso.
Kurzgesagt: led.value
soll den Wert haben, den button.value
hat.
Schreibe den Schleifenrumpf so um, dass er nur aus zwei Zeilen besteht und schaue dir erst danach die Lösung an.
Negation (not
)
Du kannst eine Bedingung übrigens auch umkehren, indem du das Keyword not
vor eine Bedingung stellst. Der folgende Code tut das Gleiche, wie der obige:
if not button.value:
led_green.value = False
else:
led_green.value = True
Auf der folgenden Seite in diesem Kurs lernst du, wie man Programme visualisieren kann. Denn je komplexer Programme versteht man besser, wenn man sie auf eine elegante Art graphisch darstellen kann.
8 Programmablaufpläne
Du wirst schon bemerkt haben, dass sich jedes Programm bisher stets gleich gliedert. Am Anfang kommen die Import-Anweisungen. Dann folgen einige Deklarationen, in denen Objekte erzeugt und an Variablen zugewiesen werden und schließlich die Endlosschleife mit teils verschachtelten Anweisungen und Kontrollstrukturen.
Der Start des Codes wird durch einen rechteckigen Block mit abgerundeten Ecken angezeigt. Alle Import-Anweisungen können in einem Programmablaufplan (kurz PAP) als Rechteck dargestellt werden. In den meisten Fällen lässt man diesen Block aber ganz weg!

Im zweiten Teil werden benötigte Objekte, die man benötigt (z.B. von der Klasse DigitalInOut
) erzeugt (man sagt dazu Instanziieren). Dazu werden neue Variablen (z.B. led_red
) angelegt (man sagt dazu Deklarieren) und die Objekte werden an diese Variablen gebunden (man sagt dazu Initialisieren).
Für einen einfachen Button sind das vier Schritte. Der letzte Schritt ist im Grunde nur eine Unterstützung. Man kann im Grunde auf ihn verzichten. Wozu du das Debauncer-Objekt brauchst, erfährst du im nächsten Kapitel.
led_blue = digitalio.DigitalInOut(board.D12)
led_blue.direction = digitalio.Direction.OUTPUT
button = digitalio.DigitalInOut(board.D13)
button.switch_to_input(pull=digitalio.Pull.DOWN)
Aber auch diese Blöcke können weggelassen werden, da es in einem Programmablaufplan um den Hauptteil des Programms geht!

Jetzt kommt der spannende Teile. Wenn du den PAP mit dem Code vergleichst, siehst du schnell welcher Block welcher Zeile zugeordnet ist.
while True:
led_green.value = not button.value
if led_green.value:
led_red.value = False
else:
led_red.value = True

Der Profi hat natürlich schon erkannt, dass auch hier die if-Bedingung eigentlich nicht nötig ist.
Kannst du den Code entsprechend anpassen?
9 code.py
Während des gesamten Tutorials hast du in der Datei code.py programmiert. Zwischenzeitlich hast du eine weitere Datei - rgb_led.py angelegt, weil ein neues Programm kopiert werden sollte. Das vorherige Programm sollte aber nicht verloren gehen.
Das Gleiche machst du jetzt für den Code, der sich aktuell in der Datei code.py befindet. Kopiere ihn in eine neue Datei und speichere sie unter dem Namen button1.py auf das Laufwerk CIRCUITPY ab.
Du hast nun zwei Programme in zwei separaten Dateien auf deinem Board liegen. Ein wichtiges Unterscheidungsmerkmal, das einen Mikrocontroller von einem PC unterscheidet, ist, dass immer nur ein Programm gleichzeitig ausgeführt werden kann! Das heißt aber nicht, dass man nicht mehrere Programme auf ihm speichern kann. Man kann eben immer nur eines ausführen.
Fortan wirst du die Datei code.py nur noch zur Auswahl des Programms, das du gerade ausführen möchtest, verwenden.

Nachdem du die Datei button1.py angelegt und den Inhalt hineinkopiert hast, kannst du den Inhalt aus der Datei code.py löschen. Nutze die import-Anweisung um eines der beiden Programme zu starten. Die Raute #
zeigt dir an, welche Programme deaktiviert sind und somit nicht importiert werden. Es sollte immer nur eine Zeile in deiner code.py aktiviert (also ohne eine Raute) sein.
Lege gleich eine neue Datei mit dem Namen button2.py an und importierst sie in deiner code.py. Die anderen beiden Zeilen deaktivierst du mit einer vorangestellten Raute.

10 Alarmanlage
Ziel dieses Kapitels ist es, eine Alarmanlage für ein Fenster bzw. eine Tür zu entwickeln. Wir verwenden dazu die Schaltung aus dem vorletzten Kapitel. Wenn du keinen Magnetkontaktschalter hast, kannst du auch einen zweiten Taster benutzen. Der Magnetkontaktschalter funktioniert nämlich wie ein Taster.

Kopiere jetzt das folgende Programm in die Datei button2.py und speichere sie ab.
1import board
2import digitalio
3from adafruit_debouncer import Debouncer
4
5led_red = digitalio.DigitalInOut(board.D10)
6led_green = digitalio.DigitalInOut(board.D11)
7led_blue = digitalio.DigitalInOut(board.D12)
8led_red.direction = digitalio.Direction.OUTPUT
9led_green.direction = digitalio.Direction.OUTPUT
10led_blue.direction = digitalio.Direction.OUTPUT
11
12button = digitalio.DigitalInOut(board.D13)
13button.switch_to_input(pull=digitalio.Pull.DOWN)
14button_d = Debouncer(button)
15door = digitalio.DigitalInOut(board.D9)
16door.switch_to_input(pull=digitalio.Pull.UP)
17
18while True:
19 button_d.update()
20
21 if button_d.rose:
22 led_green.value = not led_green.value
23
24 led_red.value = door.value
25

Vergleiche zuerst die beiden Programme button1.py und button2.py. Welche Unterschiede und Gemeinsamkeiten gibt es?
Hast du bemerkt, dass grüne LED bei Programm button1 nur so lange leuchtet, wie der jeweilige Taster gedrückt wird. Im Programm button2 ist etwas anders. Wir können jetzt den Taster als Schalter verwenden und die LED durch den Taster ein- und ausschalten.
Toggeln einer LED
Mit dem Befehl led_red.value = not led_red.value
kann man den Zustand der LED toggeln - also umkehren. Dadurch wechselt die LED ihren Zustand von an nach aus oder umgekehrt.
Die Debouncer-Klasse
Wenn man einen Taster verwendet, erwartet man je nach Anwendung, dass sich etwas tut …
im Moment des Herunterdrückens oder
im Moment des Loslassens oder
solange man ihn drückt bzw. nicht drückt.
Den letzten Fall kennst du schon - er ist einfach zu programmieren. Wir nutzen dazu einfach das Attribut value
. Ist der Taster heruntergedrückt, dann ist value
gleich True
. Wenn value
aber True
ist, na dann ist auch die if-Bedingung True
. Und wenn die if-Bedingung True
ist, dann soll ein Text ausgegeben werden. Andernfalls (der Taster ist nicht gedrückt) passiert gar nichts, weil value
False
ist und damit ist auch die if-Bedingung False
.
if button.value:
print('pressed')
Soll die grüne LED ihren Zustand ändern, wenn der Taster runtergedrückt wird, kommen wir nicht drumherum ein neues Modul zu importieren. Das Modul heißt adafruit_debouncer
und es stellt eine Klasse Debouncer
bereit. Diese Klasse hat zwei sehr nützliche Attribute: fell
und rose
.
Betrachte das folgende Beispiel.
1import board
2import digitalio
3from adafruit_debouncer import Debouncer
4
5button = digitalio.DigitalInOut(board.D13)
6button.switch_to_input(pull=digitalio.Pull.DOWN)
7button_d = Debouncer(button)
8
9while True:
10 button_d.update()
11
12 if button_d.rose: # Wurde der Taster heruntergedrückt
13 print("Spannung ging von 0 auf 3.3V")
14
15 if button_d.fell: # Wurde der Tester losgelassen
16 print("Spannung ging von 3.3V auf 0V")
17
In dem Moment, als der Taster gedrückt wurde, stieg (engl.: rose
) das Potential am Pin D13
von 0V auf 3.3V an. Und in dem Moment, als der Taster losgelassen wurde, fiel (engl.: fell
) das Potential am Pin D13
von 3.3V auf 0V ab.
11 Aufgabe
Deine Aufgabe ist es, den Programmablaufplan unten in ein Programm umzusetzen. Willst du überprüfen, ob die LED gerade leuchtet, benutze einfach:
if led_green.value:
Das Programm soll eine Alarmanlage simulieren. Mit dem Taster wird sie scharf gestellt (die grüne LED leuchtet). Mit dem gleichen Taster kann sie auch jederzeit wieder deaktiviert werden (die grüne LED leuchtet nicht). Nur wenn die grüne LED leuchtet, soll der Alarm (rot LED) angehen, falls der Reedschalter geöffnet wird. Wenn die grüne LED nicht an ist, soll die rote LED (also der Alarm) immer aus sein.

Viel Erfolg.