unser Arduino von Haus aus kein Ausgabefenster besitzt, müssen wir uns etwas anderes einfallen lassen. Die serielle Schnittstelle, an der er quasi angeschlossen ist, können wir dazu nutzen, Daten zu versenden. Die Entwicklungsumgebung verfügt über einen Serial Monitor, der diese Daten bequem empfangen und darstellen kann. Du kannst ihn sogar dazu verwenden, Daten an das Arduino-Board zu schicken, die anschließend dort verarbeitet werden können. Doch dazu gleich mehr. Der folgende Befehl initialisiert die serielle Schnittstelle mit einer Übertragungsrate von 9600 Baud:
Serial.begin(9600);
Die folgende Zeile sendet dann mittels der println-Funktion den Wert der Variablen i an die Schnittstelle:
Serial.println(i);
Du musst jetzt lediglich den Serial Monitor öffnen und die Werte werden angezeigt (Abbildung 6).
Du siehst hier, wie die Werte der Laufvariablen i von 0 bis 6 ausgegeben werden, die wir in unserem eigentlichen Sketch zur Auswahl der Array-Elemente benötigen. Ich habe den Code innerhalb der setup-Funktion platziert, damit die for-Schleife nur einmal ausgeführt wird und die Anzeige nicht ständig durchläuft.
Abb. 6: Die Ausgabe der Werte im Serial Monitor
Die folgende Abbildung 7 zeigt dir die einzelnen Durchläufe der for-Schleife etwas genauer:
Abb. 7: Das Verhalten der for-Schleife
Wie die serielle Schnittstelle zu konfigurieren ist und wie man etwas dahin versendet, hast du schon gesehen. Die Methode begin initialisiert das Serial-Objekt mit der angeforderten Übertragungsrate und die Methode println (print line bedeutet so viel wie Drucke und mache einen Zeilenvorschub) gibt etwas auf der seriellen Schnittstelle aus. Das Bindeglied zwischen Objekt und Methode ist der Punktoperator (.), der beide verbindet.
Die serielle Schnittstelle bei der Fehlersuche
Du hast jetzt erfahren, wie etwas an die serielle Schnittstelle geschickt werden kann. Du kannst dir diesen Umstand zunutze machen, wenn du einen oder mehrere Fehler in einem Sketch finden möchtest. Funktioniert der Sketch nicht so, wie du es dir vorstellst, dann positioniere an unterschiedlichen Stellen im Code, die dir wichtig erscheinen, Ausgabebefehle in Form von Serial.println(...); und lass dir bestimmte Variableninhalte oder auch Texte ausgeben. Auf diese Weise erfährst du, was dein Sketch treibt und warum er möglicherweise nicht korrekt abläuft. Du musst lediglich lernen, die ausgegebenen Daten zu interpretieren. Das ist manchmal nicht so einfach und es gehört ein wenig Übung dazu.
Register direkt beeinflussen
Im Bastelprojekt 2 über die Low-Level-Programmierung des Arduino haben wir gesehen, wie einfach es ist, die digitalen Pins über die Manipulation von Registern zu beeinflussen. Hinsichtlich des Lauflichts kann man sich die Sache zunutze machen. Der nachfolgende Schaltplan verfügt lediglich über sechs LEDs mit den entsprechenden Vorwiderständen, wobei ich aber jeder LED eine kleine Zahl beigestellt habe. Wozu das ganze sinnvoll ist, werden wir gleich sehen.
Abb. 8: Der Schaltplan für unser kleines Lauflicht
Werfen wir noch einmal einen Blick auf das Register PORT B.
Die acht Bits eines Ports werden zu einem sogenannten Byte zusammengefasst. Jedes einzelne Bit dieses Bytes besitzt eine Nummer, die von rechts nach links aufsteigend bei 0 beginnt, wie das in der oberen Reihe zu erkennen ist. Somit können wir jedes einzelne Bit eindeutig von 0 bis 7 adressieren. Jedes einzelne Bit besitzt neben seiner Position innerhalb des Bytes einen Stellenwert oder eine Wertigkeit, die eben genau von der betreffenden Position innerhalb des Bytes abhängt und ebenfalls von rechts nach links zunimmt. Die untere Reihe zeigt die Wertigkeit jedes einzelnen Bits an. Die Frage ist nur, wie diese Werte eigentlich zustande kommen. Das ist sehr einfach! Da das binäre System lediglich die beiden Zustände 0 und 1 kennt, ist die Basis zur Berechnung der Stellenwertigkeit die Zahl 2. Wir erinnern uns, dass unser Dezimalsystem die Ziffern 0 bis 9 kennt und demnach zehn mögliche Zustände vorhanden sind. Die Basis zur Berechnung der Stellenwertigkeit ist demnach die Zahl 10.
Doch kommen wir zurück zum binären System. Wie berechnet man die Stellenwertigkeit? Das erfolgt nach folgender Formel:
Wie groß ist also die Wertigkeit des Bits an der Position 4? Dann wollen wir mal sehen:
Sehen wir uns jetzt die Variante an, die mithilfe der Register- beziehungsweise Bit-Manipulation realisiert wird. Um das gewünschte LED-Muster zu erzeugen, muss lediglich an den Stellen innerhalb des Bytes eine 1 stehen, an denen die LEDs leuchten sollen. Zum besseren optischen Verständnis habe ich hier anstelle der LED-Bar, wie sie auf dem Arduino Discoveryboard zum Einsatz kommt, richtige LEDs mit 5mm Durchmesser verwendet, was du natürlich ebenfalls machen kannst:
Der entsprechende Sketch-Code dazu sieht wie folgt aus:
void setup() { DDRB = 0b11111111; // PORT B komplett als OUTPUT PORTB = 0b00010101; // Erzeugung des LED-Musters } void loop() { /* leer */ }
Wir sehen, dass die Zeile mit der verwendeten Bit-Kombination
PORTB = 0b00010101;
genau dem LED-Muster entspricht. Natürlich muss bei der Initialisierung keine Binärzahl verwendet werden. Es funktioniert auch mit einer Ganzzahl. Machen wir ein kleines Experiment und lassen uns ein paar Bit-Kombinationen von 0 bis 63 anzeigen. Dazu muss lediglich ein Wert immer um 1 inkrementiert – also erhöht werden. Diesmal muss sich aber ein Teil des Codes innerhalb der loop-Funktion befinden, denn es soll ja in regelmäßigen Zeitabständen eine Änderung bewirkt werden:
byte pattern = 0; void setup() { DDRB = 0b11111111; // PORT B komplett als OUTPUT } void loop() { PORTB = pattern++; // Inkrementieren von pattern delay(100); // Kurze Pause von 100ms }
Die Variable pattern ist vom Datentyp byte und hat somit acht Bits und kann Werte von 0 bis 255 speichern. Wenn wir sie innerhalb der loop-Funktion inkrementieren, dann wird irgendwann einmal ein sogenannter Überlauf erfolgen, wenn der Inhalt der Variablen 255 beträgt und anschließend noch einmal der Wert 1 addiert wird. Das funktioniert natürlich nicht, denn das Fassungsvermögen ist erschöpft. Es erfolgt der genannte Überlauf und das Spiel beginnt bei 0 von vorn. Mit folgender Zeile erfolgt das Inkrementieren der Variablen, wobei der Inkrement-Operator, der durch die beiden Pluszeichen repräsentiert wird, die Aufgabe des Hochzählens übernimmt:
PORTB = pattern++;
Man hätte das Gleiche auch mit den folgenden Zeilen erreicht:
pattern = pattern + 1; PORTB = pattern;
Das ist natürlich Geschmackssache, aber Programmierer lieben es, Dinge zu verkürzen und so wenig Code wie möglich zu formulieren.