Bemerkung
Hallo und herzlich willkommen in der SunFounder Raspberry Pi & Arduino & ESP32 Enthusiasten-Community auf Facebook! Tauche tiefer ein in Raspberry Pi, Arduino und ESP32 mit gleichgesinnten Technikbegeisterten.
Warum beitreten?
Expertenunterstützung: Löse Probleme nach dem Kauf und technische Herausforderungen mit Hilfe unserer Community und unseres Teams.
Lernen & Teilen: Tausche Tipps und Tutorials aus, um deine Fähigkeiten zu verbessern.
Exklusive Vorschauen: Erhalte frühzeitigen Zugang zu neuen Produktankündigungen und exklusiven Einblicken.
Sonderrabatte: Genieße exklusive Rabatte auf unsere neuesten Produkte.
Festliche Aktionen und Verlosungen: Nimm an Verlosungen und Feiertagsaktionen teil.
👉 Bereit, mit uns zu entdecken und zu kreieren? Klicke auf [hier] und tritt noch heute bei!
23. „Twinkle, Twinkle, Little Star“ spielen
In dieser Lektion tauchen wir in die faszinierende Verbindung zwischen Musik und Technologie ein. Du lernst, wie verschiedene Tonhöhen durch Frequenzänderungen erzeugt werden und wie dieses Prinzip mit einem Mikrocontroller wie Arduino genutzt werden kann, um einen Piezo-Summer zu steuern. Am Ende dieser Lektion wirst du nicht nur die Grundlagen der musikalischen Frequenzen verstehen, sondern auch in der Lage sein, ein Arduino so zu programmieren, dass es eine einfache Melodie spielt.
Am Ende dieser Lektion wirst du in der Lage sein:
Zu verstehen, wie musikalische Tonhöhen spezifischen Frequenzen entsprechen.
Arrays zu verwenden, um Noten zu speichern und zu manipulieren und dadurch das Programmieren zu vereinfachen.
Ein Programm zu schreiben und auszuführen, das einen passiven Piezo-Summer steuert, um „Twinkle, Twinkle, Little Star“ zu spielen.
Musikalische Frequenzen und Klangerzeugung

Verschiedene Musikinstrumente erzeugen unterschiedliche Tonhöhen durch Änderung der Frequenz. Zum Beispiel bringen beim Klavier die Tasten die entsprechenden Saiten zum schnellen Schwingen, wodurch spezifische Tonhöhen erzeugt werden. Wissenschaftler und Musiker haben verschiedene Methoden der Musiksstimmung und Tonhöhenstandards entwickelt, indem sie diese Schwingungsfrequenzen präzise gemessen haben.
Wenn du ein Arduino oder einen anderen Mikrocontroller steuerst, um ein elektrisches Signal an einen Piezo-Summer zu senden, schwingt die Membran des Summers je nach Frequenz des Signals schnell hin und her und erzeugt so einen Klang. Ein auf 440 Hz eingestelltes Signal erzeugt zum Beispiel die Standard-Tonhöhe „A4“, die als Referenzpunkt in der Musikstimmung dient. Wenn die Frequenz steigt oder fällt, ändert sich auch die erzeugte Tonhöhe entsprechend, sodass eine Bandbreite von tiefen bis hohen Tönen in einer musikalischen Komposition erreicht wird.
In der westlichen Musik umfasst eine Oktave 12 Tonhöhen (Halbtöne), von C bis B und dann zurück zu einem höheren C.
Zum Beispiel beträgt die Frequenz von Mittlerem C (meistens als C4 bezeichnet) etwa 261,63 Hz. Die Frequenz einer Note kann mit der folgenden Formel berechnet werden:

wobei f_0 die Referenztonhöhe (in der Regel A4 mit einer Frequenz von 440 Hz) ist, und n die Anzahl der Halbtonschritte von der Referenztonhöhe bis zur Zieltonhöhe angibt (positive Zahlen bedeuten eine Erhöhung, negative Zahlen eine Absenkung). Mit dieser Formel können wir die Frequenz jeder Note berechnen.
Hier ist eine Frequenztabelle:
C (C4): 262 Hz (actually close to 261.63 Hz, rounded to 262)
D (D4): 294 Hz
E (E4): 330 Hz
F (F4): 349 Hz
G (G4): 392 Hz
A (A4): 440 Hz
B (B4): 494 Hz
Nun werden wir die Geheimnisse der Noten mit Arduino und einem Piezo-Summer erkunden. Lass uns den passiven Summer die ersten zwei Zeilen von „Twinkle, Twinkle, Little Star“ spielen lassen:
Bemerkung
Die Melodie von „Twinkle, Twinkle, Little Star“ basiert auf einfachen Notenkombinationen, und die Melodie dieses Liedes geht auf Variationen von „Ah vous dirai-je, Maman“ des französischen Komponisten Wolfgang Amadeus Mozart zurück, was sie für Anfänger sehr geeignet macht.
Hier ist das grundlegende Notenblatt für „Twinkle, Twinkle, Little Star“, einschließlich jeder Note:
C C G G A A G
F F E E D D C
G G F F E E D
G G F F E E D
C C G G A A G
F F E E D D C
Schaltungsaufbau
Benötigte Komponenten
1 * Arduino Uno R3 |
1 * Steckbrett |
1 * Passiver Summer |
Jumper-Kabel |
1 * USB-Kabel |
|||
Schritt-für-Schritt Aufbau
Diese Lektion verwendet die gleiche Schaltung wie 12. Sirenensound.

Codeerstellung - Array
Öffne die Arduino IDE und starte ein neues Projekt, indem du „Neue Datei“ aus dem Menü „Datei“ wählst.
Speichere deinen Sketch unter dem Namen
Lesson23_Array
mitStrg + S
oder durch Klicken auf „Speichern“.Erstelle nun zu Beginn des Codes ein Array, das die Noten von „Twinkle, Twinkle, Little Star“ speichert.
// Definiere die Frequenzen für die Noten der C-Dur-Tonleiter (Oktave beginnend mit mittlerem C)
int c = 262;
int d = 294;
int e = 330;
int f = 349;
int g = 392;
int a = 440;
int b = 494;
int C = 523; // Hohes C
// Definiere ein Array, das die Reihenfolge der Noten in der Melodie enthält
int melody[] = { c, c, g, g, a, a, g, f, f, e, e, d, d, c, g, g, f, f, e, e, d, g, g, f, f, e, e, d, c, c, g, g, a, a, g, f, f, e, e, d, d, c };
Ein Array ist eine Datenstruktur, die in der Arduino-Programmierung verwendet wird, um mehrere Elemente des gleichen Typs zu speichern. Es ist ein sehr grundlegendes und leistungsfähiges Werkzeug, das bei richtiger Verwendung die Programmier-Effizienz und -Leistung erheblich steigern kann. Arrays können Elemente wie ganze Zahlen, Gleitkommazahlen und Zeichen speichern.
Ähnlich wie bei der Erstellung von Variablen und Funktionen wird auch bei der Erstellung eines Arrays der Array-Typ und der Array-Name angegeben - int melody[]
.
Die Elemente innerhalb der {}
Klammern werden als Array-Elemente bezeichnet, beginnend bei Index 0, sodass melody[0]
dem ersten c(262)
entspricht und melody[13]
ebenfalls c(262)
ist.
Nun drucke die Elemente an den Indizes 0 und 13 des Arrays
melody[]
im seriellen Monitor aus.
// Definiere die Frequenzen für die Noten der C-Dur-Tonleiter (Oktave beginnend mit mittlerem C)
int c = 262;
int d = 294;
int e = 330;
int f = 349;
int g = 392;
int a = 440;
int b = 494;
int C = 523; // Hohes C
// Definiere ein Array, das die Reihenfolge der Noten in der Melodie enthält
int melody[] = { c, c, g, g, a, a, g, f, f, e, e, d, d, c, g, g, f, f, e, e, d, g, g, f, f, e, e, d, c, c, g, g, a, a, g, f, f, e, e, d, d, c };
void setup() {
// Stelle deinen Setup-Code hier bereit, der einmal ausgeführt wird:
Serial.begin(9600); // Initialisiere die serielle Kommunikation mit einer Baudrate von 9600
Serial.println(melody[0]);
Serial.println(melody[13]);
}
void loop() {
// Stelle deinen Hauptcode hier bereit, der wiederholt ausgeführt wird:
}
Nach dem Hochladen des Codes auf das Arduino Uno R3 öffne den seriellen Monitor, und du wirst zweimal 262 sehen.
262
262
Wenn du jedes Element im Array
melody[]
einzeln ausdrucken möchtest, musst du zuerst die Länge des Arrays kennen. Du kannst die Funktionsizeof()
verwenden, um die Anzahl der Elemente im Array zu berechnen.
void setup() {
// Stelle deinen Setup-Code hier bereit, der einmal ausgeführt wird:
Serial.begin(9600); // Initialisiere die serielle Kommunikation mit einer Baudrate von 9600
int notes = sizeof(melody) / sizeof(melody[0]); // Berechne die Anzahl der Elemente
}
sizeof(melody)
gibt die Gesamtanzahl der Bytes zurück, die alle Elemente im Array belegen.sizeof(melody[0])
gibt die Anzahl der Bytes zurück, die ein einzelnes Element im Array belegt.Die Division der Gesamtbytes durch die Bytes pro Element ergibt die Gesamtanzahl der Elemente im Array.
Verwende dann eine
for
-Schleife, um durch die Elemente des Arraysmelody[]
zu iterieren und drucke sie mit der FunktionSerial.println()
aus.
// Definiere die Frequenzen für die Noten der C-Dur-Tonleiter (Oktave beginnend mit mittlerem C)
int c = 262;
int d = 294;
int e = 330;
int f = 349;
int g = 392;
int a = 440;
int b = 494;
int C = 523; // Hohes C
// Definiere ein Array, das die Reihenfolge der Noten in der Melodie enthält
int melody[] = { c, c, g, g, a, a, g, f, f, e, e, d, d, c, g, g, f, f, e, e, d, g, g, f, f, e, e, d, c, c, g, g, a, a, g, f, f, e, e, d, d, c };
void setup() {
// Stelle deinen Setup-Code hier bereit, der einmal ausgeführt wird:
Serial.begin(9600); // Initialisiere die serielle Kommunikation mit einer Baudrate von 9600
int notes = sizeof(melody) / sizeof(melody[0]); // Berechne die Anzahl der Elemente
// Schleife durch jede Note im Melody-Array
for (int i = 0; i < notes; i = i + 1) {
// Drucke die Frequenz jeder Note auf dem seriellen Monitor aus
Serial.println(melody[i]);
}
}
void loop() {
// Stelle deinen Hauptcode hier bereit, der wiederholt ausgeführt wird:
}
Nach dem Hochladen des Codes auf das Arduino Uno R3 öffne den seriellen Monitor, und du wirst die Elemente im Array
melody[]
nacheinander gedruckt sehen.
262
262
392
392
440
440
392
349
349
330
...
Fragen
Du kannst auch Operationen auf den Elementen im Array durchführen, wie zum Beispiel das Ändern zu Serial.println(melody[i] * 1.3);
. Welche Daten wirst du erhalten und warum?
Codeerstellung - „Twinkle, Twinkle, Little Star“ spielen
Da wir nun ein solides Verständnis für die Erstellung von Arrays, den Zugriff auf Array-Elemente und die Berechnung ihrer Längen und Operationen haben, wollen wir dieses Wissen anwenden, um einen passiven Piezo-Summer so zu programmieren, dass er „Twinkle, Twinkle, Little Star“ mit gespeicherten Frequenzen und Intervallen spielt.
Öffne den zuvor gespeicherten Sketch,
Lesson23_Array
. Wähle „Speichern unter…“ aus dem Menü „Datei“ und benenne es inLesson23_Little_Star
um. Klicke auf „Speichern“.Definiere zuerst den Pin für den Summer.
const int buzzerPin = 9; // Weist dem Pin 9 die Konstante für den Summer zu
Erstelle nun ein weiteres Array, um die Dauer der Noten zu speichern.
// Richte die Reihenfolge der Noten und deren Dauer in Millisekunden ein
int melody[] = { c, c, g, g, a, a, g, f, f, e, e, d, d, c, g, g, f, f, e, e, d, g, g, f, f, e, e, d, c, c, g, g, a, a, g, f, f, e, e, d, d, c };
int noteDurations[] = { 500, 500, 500, 500, 500, 500, 1000, 500, 500, 500, 500, 500, 500, 1000, 500, 500, 500, 500, 500, 500, 1000, 500, 500, 500, 500, 500, 500, 1000, 500, 500, 500, 500, 500, 500, 1000, 500, 500, 500, 500, 500, 500, 1000 };
Verschiebe nun einen Teil des Codes von
void setup()
invoid loop()
.
void setup() {
// Stelle deinen Setup-Code hier bereit, der einmal ausgeführt wird:
Serial.begin(9600); // Initialisiere die serielle Kommunikation mit einer Baudrate von 9600
}
void loop() {
// Stelle deinen Hauptcode hier bereit, der wiederholt ausgeführt wird:
int notes = sizeof(melody) / sizeof(melody[0]); // Berechne die Anzahl der Elemente
// Schleife durch jede Note im Melody-Array
for (int i = 0; i < notes; i = i + 1) {
// Drucke die Frequenz jeder Note auf dem seriellen Monitor aus
Serial.println(melody[i]);
}
}
Kommentiere im
for
-Statement den Druckbefehl aus und verwende dietone()
-Funktion, um die Noten abzuspielen.
void loop() {
// Hauptcode, der wiederholt ausgeführt wird:
int notes = sizeof(melody) / sizeof(melody[0]); // Berechne die Anzahl der Elemente
// Schleife durch jede Note im Melody-Array
for (int i = 0; i < notes; i = i + 1) {
// Drucke jede Frequenz der Noten auf den seriellen Monitor
// Serial.println(melody[i]);
tone(buzzerPin, melody[i], noteDurations[i]); // Spiele die Note
}
}
Um die Melodie natürlicher klingen zu lassen, füge nach jeder Note eine kurze Pause hinzu. Hier multiplizieren wir die Notendauer mit 1,30, um das Intervall zu berechnen und die Melodie weniger gehetzt wirken zu lassen.
void loop() {
// Hauptcode, der wiederholt ausgeführt wird:
int notes = sizeof(melody) / sizeof(melody[0]); // Berechne die Anzahl der Elemente
// Schleife durch jede Note im Melody-Array
for (int i = 0; i < notes; i = i + 1) {
// Drucke jede Frequenz der Noten auf den seriellen Monitor
// Serial.println(melody[i]);
tone(buzzerPin, melody[i], noteDurations[i]); // Spiele die Note
delay(noteDurations[i] * 1.30); // Warte, bevor die nächste Note gespielt wird
}
}
Verwende die
noTone()
-Funktion, um die Tonausgabe am aktuellen Pin zu stoppen. Dies ist ein notwendiger Schritt, um sicherzustellen, dass jede Note klar gespielt wird, ohne in die nächste überzugehen.
void loop() {
// Hauptcode, der wiederholt ausgeführt wird:
int notes = sizeof(melody) / sizeof(melody[0]); // Berechne die Anzahl der Elemente
// Schleife durch jede Note im Melody-Array
for (int i = 0; i < notes; i = i + 1) {
// Drucke jede Frequenz der Noten auf den seriellen Monitor
// Serial.println(melody[i]);
tone(buzzerPin, melody[i], noteDurations[i]); // Spiele die Note
delay(noteDurations[i] * 1.30); // Warte, bevor die nächste Note gespielt wird
noTone(buzzerPin); // Stoppe das Spielen der Note
}
}
Dein vollständiger Code ist unten dargestellt. Sobald du den Code auf das Arduino Uno R3 hochgeladen hast, wirst du hören, wie der Summer „Twinkle Twinkle Little Star“ spielt.
int buzzerPin = 9; // Weist den Pin 9 als Konstante für den Summer zu
// Definiere die Frequenzen für die Noten der C-Dur-Tonleiter (Oktave beginnend mit mittlerem C)
int c = 262;
int d = 294;
int e = 330;
int f = 349;
int g = 392;
int a = 440;
int b = 494;
int C = 523; // Hohes C
// Richte die Reihenfolge der Noten und deren Dauer in Millisekunden ein
int melody[] = { c, c, g, g, a, a, g, f, f, e, e, d, d, c, g, g, f, f, e, e, d, g, g, f, f, e, e, d, c, c, g, g, a, a, g, f, f, e, e, d, d, c };
int noteDurations[] = { 500, 500, 500, 500, 500, 500, 1000, 500, 500, 500, 500, 500, 500, 1000, 500, 500, 500, 500, 500, 500, 1000, 500, 500, 500, 500, 500, 500, 1000, 500, 500, 500, 500, 500, 500, 1000, 500, 500, 500, 500, 500, 500, 1000 };
void setup() {
// Initialisiere den Setup-Code, der einmal ausgeführt wird:
Serial.begin(9600); // Initialisiere die serielle Kommunikation mit einer Baudrate von 9600
}
void loop() {
// Hauptcode, der wiederholt ausgeführt wird:
int notes = sizeof(melody) / sizeof(melody[0]); // Berechne die Anzahl der Elemente
// Schleife durch jede Note im Melody-Array
for (int i = 0; i < notes; i = i + 1) {
// Drucke jede Frequenz der Noten auf den seriellen Monitor
// Serial.println(melody[i]);
tone(buzzerPin, melody[i], noteDurations[i]); // Spiele die Note
delay(noteDurations[i] * 1.30); // Warte, bevor die nächste Note gespielt wird
noTone(buzzerPin); // Stoppe das Spielen der Note
}
}
Vergiss nicht, deinen Code zu speichern und deinen Arbeitsplatz aufzuräumen.
Frage
Wenn du den passiven Summer in der Schaltung durch einen aktiven Summer ersetzt, kannst du dann trotzdem „Twinkle Twinkle Little Star“ spielen? Warum?
Zusammenfassung
Nachdem der Unterricht nun beendet ist, haben wir in dieser Lektion gelernt, wie man Arrays verwendet, um Daten zu speichern, die Länge von Arrays zu berechnen, Elemente innerhalb eines Arrays zu indexieren und Operationen mit jedem Element durchzuführen. Indem wir Notenfrequenzen und Zeitintervalle in Arrays speicherten und sie mithilfe einer For-Schleife durchliefen, haben wir erfolgreich einen passiven Summer so programmiert, dass er „Twinkle, Twinkle, Little Star“ spielt.
Zusätzlich haben wir gelernt, wie man die Wiedergabe einer Note mit der noTone()
-Funktion pausiert.
Diese Lektion hat nicht nur unser Verständnis von Array-Operationen und Kontrollstrukturen in der Programmierung vertieft, sondern auch gezeigt, wie diese Konzepte angewendet werden können, um Musik mit elektronischen Komponenten zu erzeugen. Auf unterhaltsame und ansprechende Weise verknüpften wir theoretisches Wissen mit praktischen Anwendungen.