Das Array
Ein Array ist eine Datenstruktur, die es uns erlaubt, mehrere Werte desselben Typs unter einem gemeinsamen Namen zu speichern. Dies ermöglicht uns eine effizientere Organisation und Verwaltung unserer Daten, insbesondere wenn wir mit großen Mengen von Daten arbeiten. So können wir zum Beispiel eine Reihe von Zahlen speichern, die eine Melodie repräsentieren, oder die digitalen Lesungen eines Sensors im Laufe der Zeit.
Beim Programmieren ist eine gewisse Effizienz erstrebenswert. Ein guter Code zeichnet sich durch Kompaktheit aus. Stell dir vor, du hast die Aufgabe, sieben Töne nacheinander abzuspielen. Mit unserem bisherigen Wissen über die Programmierung könnte der Sketch wie folgt aussehen:
Was ist ein Array?
Ein Array ist wie eine Liste von Variablen desselben Typs, die alle den gleichen Namen haben. Es ermöglicht uns, eine große Anzahl von Variablen auf einfache Weise zu verwalten. Jede im Array platzierte Variable wird als Element bezeichnet. Die Anzahl der Elemente wird als Array-Größe bezeichnet. Die Syntax zur Erzeugung eines Arrays sieht wie folgt aus:
int note[] = {525, 664, 598, 701, 661, 781, 695};
Ein Array beginnt mit dem Variablentyp (int), gefolgt vom Namen des Arrays (note) und zwei eckigen Klammern. Dieser wird gleichgesetzt mit dem Inhalt: innerhalb von zwei geschweiften Klammern sind die Array-Elemente platziert, die durch Kommas voneinander getrennt sind. Sie alle heißen note, werden aber durch ihre Position im Array unterschieden. Arrays sind nullindiziert, das heißt, sie beginnen nicht bei 1, sondern bei 0. Der erste Wert 525 hat zum Beispiel den Index 0, der zweite Wert 664 den Index 1, und so weiter. Um auf ein bestimmtes Element in einem Array zuzugreifen, verwenden wir den Index dieses Elements.
In der unteren Codezeile wird das fünfte Element (index 4) aus dem Array gezogen und über den seriellen Monitor die Zahl 661 ausgegeben.
Serial.println(note[4]); // Gibt den fünften Wert des Arrays aus, der 661 entspricht.
Hier eine Übersicht der aller Index-Elemente von 0 bis 6 mit den entsprechenden Werten.
note[0] = 525
note[1] = 664
note[2] = 598
note[3] = 701
note[4] = 661
note[5] = 781
note[6] = 695
Eleganz von Code
Das wahre Potenzial eines Arrays zeigt sich jedoch, wenn es in Kombination mit einer Schleife verwendet wird. Mit einer for-Schleife können wir auf einfache Weise durch jedes Element in einem Array iterieren. Das folgende Beispiel zeigt, wie wir den vorherigen Code effizienter gestalten können:
int piezoPin = 7;
int note[] = {525, 664, 598, 701, 661, 781, 695};
void setup()
{
// Initialisiere die serielle Kommunikation
Serial.begin(9600);
// Schleife zum Spielen der Töne
for(int index = 0; index < 7; index++)
{
// Spiele den aktuellen Ton ab und warte
tone(piezoPin, note[index], 1000);
delay(500);
}
}
void loop()
{
// Leere Schleife, keine weitere Aktion erforderlich
}
Dieser Code macht genau dasselbe wie der vorherige, ist aber viel kompakter und leichter zu lesen und zu warten. Es demonstriert auch, wie Begriffe wie "elegant" und "stilvoll" auch in der Programmierung Anwendung finden können.
Lass uns den Sketch genauer betrachten. Im Kern des Sketches steht die for-Schleife. Die for-Schleife zählt von 0 bis 6, was der Anzahl der Elemente im Array entspricht. Die Dauer des Tons ist mit dem Wert 1000 fest eingestellt und ändert sich nicht. Das Array und die for()-Schleife bestimmen die Tonfrequenz. Bei jedem Durchlauf der Schleife wird das Ergebnis des Index aus dem Schleifenkopf in die eckigen Klammern von sequenz[index] eingesetzt, wodurch die Frequenzwerte aus dem Array geholt werden. So werden alle Elemente aus dem Array nacheinander abgerufen und mit einem Abstand von 500ms (Verzögerung) abgespielt.
// Definiere den Pin, an dem der Piezo-Lautsprecher angeschlossen ist
int piezoPin = 8;
// Array mit den Frequenzen der Töne
int note[] = {525, 664, 598, 701, 661, 781, 695};
void setup()
{
// Initialisiere die serielle Kommunikation mit einer Baudrate von 9600
Serial.begin(9600);
// Schleife, um die Töne sequenziell abzuspielen
for (int index = 0; index < 7; index++)
{
// Spiele den aktuellen Ton aus dem Array note ab
tone(piezoPin, note[index], 1000);
// Warte für 500 Millisekunden, bevor der nächste Ton gespielt wird
delay(500);
}
}
void loop()
{
// Leer - keine weiteren Aktionen in der Dauerschleife
}
1. Schleifendurchgang > note[0] (Element 1 im Array) > Ergebnis: 525 für Frequenz
2. Schleifendurchgang > note[1] (Element 2 im Array) > Ergebnis: 664 für Frequenz
3. Schleifendurchgang > note[2] (Element 3 im Array) > Ergebnis: 598 für Frequenz
4. Schleifendurchgang > note[3] (Element 4 im Array) > Ergebnis: 701 für Frequenz
5. Schleifendurchgang > note[4] (Element 5 im Array) > Ergebnis: 661 für Frequenz
6. Schleifendurchgang > note[5] (Element 6 im Array) > Ergebnis: 781 für Frequenz
7. Schleifendurchgang > note[6] (Element 7 im Array) > Ergebnis: 695 für Frequenz
Werte außerhalb der Array-Größe
Die for-Schleife durchläuft Indexwerte von 0 bis 6, was die Anzahl der Elemente im Array darstellt. Ein Fehler kann zum Beispiel auftreten, wenn die Schleife bis 10 zählt, obwohl nur 7 Elemente vorhanden sind. Der Compiler wird in solchen Fällen keinen Fehler melden, aber das Ergebnis beeinflussen, wie du im folgenden Beispiel hören und sehen kannst:
// Definiere den Pin, an dem der Piezo-Lautsprecher angeschlossen ist
int piezoPin = 8;
// Array mit den Frequenzen der Töne
int sequenz[] = {525, 664, 598, 701, 661, 781, 695};
void setup()
{
// Initialisiere die serielle Kommunikation mit einer Baudrate von 9600
Serial.begin(9600);
// Schleife, um die Töne aus dem Array sequenz abzuspielen
for(int i = 0; i < 10; i++)
{
// Spiele den aktuellen Ton aus dem Array sequenz ab
tone(piezoPin, sequenz[i], 1000);
// Warte für 500 Millisekunden, bevor der nächste Ton gespielt wird
delay(500);
// Gib die Frequenz des aktuellen Tons über die serielle Schnittstelle aus
Serial.println(sequenz[i]);
}
}
void loop()
{
// Leer - keine weiteren Aktionen in der Dauerschleife
}
Die Schleife zählt diesmal von 0 bis 9 – also über die Array-Größe von 7 Elementen hinaus. Es werden am Schluss drei zusätzliche Töne abgespielt.
for(int i=0; i<10; i++) { ... }
Die Anweisung Serial.println() zeigt an, dass drei zusätzliche Werte, die nicht im Array enthalten sind, ausgegeben werden. Wenn dieser Fehler unbekannt bleibt, führt dies definitiv zu Fehlberechnungen.
Serial.println(sequenz[i]);
Entweder man passt genau auf und fügt die richtige Array-Größe in die for-Schleife, oder bedient sich einem Trick und macht sich keine Gedanken mehr darüber, wie groß das Array ist. Mit Hilfe der sizeof()-Funktion können wir die Anzahl von Array-Elementen ausrechnen. Ein direktes Auslesen der Elementen-Anzahl funktioniert leider nicht. Wir müssen eine kleine Berechnung anstellen.
Die sizeof()-Funktion liest die Speichergröße aus, die die Elemente belegen – nicht die Anzahl. Der Rückgabewert von sizeof() erfolgt in Byte. Folgender Code liest die Größe des Arrays im seriellen Monitor als Byte aus. Der serielle Monitor gibt die Zahl 16 aus.
// Array mit den Frequenzen der Töne
int sequenz[] = {523, 659, 587, 698, 659, 784, 698, 880};
// Anzahl der Elemente im Array
int elements = sizeof(sequenz); // sizeof(sequenz[0]);
void setup()
{
// Initialisiere die serielle Kommunikation mit einer Baudrate von 9600
Serial.begin(9600);
// Gib die Anzahl der Elemente im Array über die serielle Schnittstelle aus
Serial.println(elements);
}
void loop()
{
// Leer - keine weiteren Aktionen in der Dauerschleife
}
Unser Array enthält 8 Elemente.
int elements = sizeof(sequenz) / sizeof(int);
Hier der vollständige Sketch:
// Pin-Nummer für das Piezo-Element
const int piezoPin = 8;
// Array mit den Frequenzen der Töne
int sequenz[] = {523, 659, 587, 698, 659, 784, 698, 880};
// Anzahl der Elemente im Array
int arrayElements = sizeof(sequenz) / sizeof(int);
void setup()
{
// Initialisiere die serielle Kommunikation mit einer Baudrate von 9600
Serial.begin(9600);
// Durchlaufe das Array und spiele die Töne ab
for(int i=0; i
Diese Lösung ist allerdings speicherintensiv und der Code wirkt etwas klobig. Mit der Verwendung eines Arrays könnten wir dieses Problem viel eleganter lösen.
Aufbau und Verkabelung
int piezoPin = 7;
// Definiere Tonhöhen
int tone0 = 525;
int tone1 = 664;
int tone2 = 598;
int tone3 = 701;
int tone4 = 661;
int tone5 = 481;
int tone6 = 695;
void setup()
{
// Initialisiere die serielle Kommunikation
Serial.begin(9600);
// Spiele Töne ab und warte
tone(piezoPin, tone0, 1000);
delay(500);
tone(piezoPin, tone1, 1000);
delay(500);
tone(piezoPin, tone2, 1000);
delay(500);
tone(piezoPin, tone3, 1000);
delay(500);
tone(piezoPin, tone4, 1000);
delay(500);
tone(piezoPin, tone5, 1000);
delay(500);
tone(piezoPin, tone6, 1000);
delay(500);
}
void loop()
{
// Leere Schleife, keine weitere Aktion erforderlich
}