In diesem Projekt lernst du, wie du ein einfaches Arduino Theremin mit einem Piezo-Summer und dem Ultraschall-Sensor HC-SR04 baust. Aber nicht nur das – damit auch ungeübte Musiker ihre Freunde begeistern können, spielt dieses Theremin nur Töne innerhalb einer von dir festgelegten Tonleiter.
Im Folgenden verwenden wir die beliebte A-Moll Pentatonik als Beispiel. Du kannst aber auch jede andere Tonleiter definieren und verwenden. Mehr dazu später.
Anfänger
1 – 2 Stunden
ca. 10 € plus ggfs. Kosten für den Arduino Uno
Für dieses Projekt benötigst du (Mengen s. Beschreibung):
Der Aufbau des Arduino Theremins
Du musst nur zwei Bauteile auf deinem Breadboard montieren und mit deinem Arduino verbinden: Den Piezo-Summer und den Ultraschall-Sensor. Ersteren verbindest du mit dem Digitalpin 3 und mit Erde. Beim Ultraschall-Sensor verbindest du zunächst VCC mit Plus und GND mit Minus. Anschließend verbindest du den Ausgang TRIG mit dem Digitalpin 5 und ECHO mit dem Digitalpin 4 an deinem Arduino.
So funktioniert dein Theremin
Dieses Projekt funktioniert eigentlich ganz simpel: Der Ultraschall-Sensor HC-SR04 misst die Entfernung zu einem Objekt, z.B. zu deiner Hand. Diese Entfernung rechnest du in Tonhöhen um, die du über den Piezo-Summer ausgibst.
Da hier natürlich alle möglichen Entfernungen in einem bestimmten Bereich möglich sind, gibt es auch alle möglichen Töne – auch welche, die in klassischen Tonleitern nicht vorkommen. Deshalb sucht sich der folgende Sketch immer den nächsttieferen Ton in der A-Moll Pentatonik heraus. So spielst du kinderleicht ansprechende Melodien!
Der passende Sketch für Musiker
Zunächst legst du ein paar Variablen fest, die du später mit Leben füllst:
//Arduino Pins für den Ultraschall-Sensor
int trigger = 5;
int echo = 4;
int distance = 0;
//Pin des Piezo-Summers
const int piezo = 3;
//Variablen für die Bestimmung der Reichweite
int distance = 0;
int distanceHigh = 0;
//Variable für die Anzahl der Töne in der Tonleiter
int lengthOfScale = 0;
//Variable für die zu spielende Note
int note = 0;
Danach folgt ein Array, in dem die Töne der A-Moll Pentatonik stecken – genauer gesagt, welche Frequenzen (in Hertz) du mit deinem Piezo-Summer ausgibst. Das sind immer wieder die Töne A – C – D – E – G in verschiedenen Oktaven.
int scale[] = {
147, 165, 196, 220, 262, 294, 330, 392, 440,
523, 587, 659, 784, 880, 1047, 1175, 1319, 1568,
1760, 2093, 2349
};
Auf Github findest du eine mehr oder weniger vollständige Liste aller Töne und ihrer Frequenzen.
Die Setup-Funktion
Hier startest du zunächst den Seriellen Monitor und legst die PinModes für die Pins des Ultraschall-Sensors fest. Dann kommt der erste interessante Teil des Sketchs: Dein Sensor hat eine theoretische Reichweite von 2cm bis 4m – die Reichweite, in der du spielst, wird aber vermutlich geringer sein.
Deshalb kalibrierst du den Sensor in den ersten fünf Sekunden nach dem Start. Das heißt, du bestimmst, wie weit weg deine Hand vom Sensor sein wird. Hierfür bewegst du deine Hand vor dem Sensor langsam circa 40-50cm weg. Die größte Entfernung speicherst du dann in die Variablen distanceHigh. Diese benötigst du später wieder.
void setup() {
Serial.begin (9600);
pinMode(trigger, OUTPUT);
pinMode(echo, INPUT);
while (millis() < 5000) {
//Der Sensor misst die Entfernung
digitalWrite(trigger, HIGH);
digitalWrite(trigger, LOW);
distance = pulseIn(echo, HIGH);
Serial.println(distance);
//Größte Entfernung speichern
if (distance > distanceHigh) {
distanceHigh = distance;
}
}
}
Hinweis: Um genau zu sein, misst der HC-SR04 nicht direkt die Entfernung, sondern nur wie lange ein ausgesendetes Ultraschall-Signal benötigt, um von einem Hindernis (deine Hand) wieder im Sensor einzutreffen. In diesem Tutorial erfährst du, wie du die Entfernung in cm messen kannst.
Jetzt musst du noch ermitteln, wie viele Töne sich in der Tonleiter, also im Array scale[] befinden. Das machst du folgendermaßen:
for (byte i = 0; i < (sizeof(scale) / sizeof(scale[0])); i++) {
lengthOfScale += 1;
}
Der Loop
Hier spielt die Musik. Im Loop lässt du deinen Ultraschall-Sensor immer wieder die Entfernung zu deiner Hand messen. Je nachdem wie weit sie von ihm entfernt ist, erklingt ein anderer Ton. Zentral ist hierbei folgende Funktion:
note = map(distance, 250, distanceHigh, scale[0], scale[lengthOfScale - 1]);
Mithilfe der Funktion map() kannst du eine Zahl aus einem Bereich einem anderen Bereich zuordnen. In diesem Projekt „mapst“ du die aktuelle Entfernung deiner Hand (distance) auf eine bestimmte Tonfrequenz.
Hierfür sind zwei Bereiche notwendig: Die aktuelle Entfernung deiner Hand liegt im Bereich der minimalen (legst du auf 250 fest) und maximalen (distanceHigh) Entfernung deiner Hand, die du in der Kalibrierung zu Beginn festgelegt hast. Der zweite Bereich wird vom tiefsten Ton (also die Position 0 im Array scale[]) und dem höchsten Ton (ermittelst du mit scale[lengthOfScale – 1]) deiner Pentatonik im Array scale[] begrenzt.
Die Entfernung deiner Hand wird also in unserem konkreten Fall einer Zahl zwischen 147 und 2349 zugeordnet und in der Variablen note gespeichert.
In der Arduino-Referenz erfährst du mehr über die Funktion map().
Den richtigen Ton treffen
Bis jetzt hast du nur einen Frequenzbereich, in der die Note liegt. Dein Arduino Theremin soll aber keine ungenauen Zwischentöne spielen, sondern nur Noten der A-Moll Pentatonik. Hierfür benötigst du einen Loop und ein paar Abfragen:
for (byte j = 0; j < (lengthOfScale); j++) {
if (note == scale[j]) {
tone(piezo, note);
break;
}
else if (note > scale[j] && note < scale[j + 1]) {
note = scale[j];
tone(piezo, note);
break;
}
}
Im For-Loop fragst du für jede Note des Arrays scale[] ab, ob du deine Hand schon in der richtigen Entfernung und die Note somit genau getroffen hast. In diesem Fall spielst du sie über die Funktion tone() mit deinem Piezo-Summer ab.
Falls nicht, fragst du im ersten else if, ob dein gespielter Ton zwischen zwei Noten steckt. Wenn das so ist, spielst du einfach die niedrigere von beiden.
Zu kompliziert? Ein Beispiel: Deine Hand hat eine Entfernung zum Sensor, die du mithilfe der Funktion map() auf eine Frequenz von 200 Hertz umgerechnet hast. Das ist aber keine Note der A-Moll Pentatonik, sondern liegt irgendwo zwischen einem G und einem Gis. Der nächsttiefere, richtige Ton ist laut deinem Array ein G mit 196 Hertz. Und den spielt dein Theremin dann.
Und das war’s! Schalte dein Arduino Theremin ein, kalibriere es und lass die Fetzen fliegen. 🙂
Hier nun der gesamte Sketch:
/*
Arduino Theremin with A minor pentatonic scale
pollux labs, 2020
All rights reserved.
*/
const int trigger = 5;
const int echo = 4;
const int piezo = 3;
int distance = 0;
int distanceHigh = 0;
int lengthOfScale = 0;
int note = 0;
//A Minor pentatonic scale
int scale[] = {
147, 165, 196, 220, 262, 294, 330, 392, 440,
523, 587, 659, 784, 880, 1047, 1175, 1319, 1568,
1760, 2093, 2349
};
//C Major scale
//int scale[] = {
// 131, 147, 165, 175, 196, 220, 247, 262, 294,
// 330, 349, 392, 440, 494, 523, 587, 659, 698,
// 784, 880, 988, 1047
//};
void setup() {
pinMode(trigger, OUTPUT);
pinMode(echo, INPUT);
while (millis() < 5000) {
digitalWrite(trigger, HIGH);
digitalWrite(trigger, LOW);
distance = pulseIn(echo, HIGH);
if (distance > distanceHigh) {
distanceHigh = distance;
}
}
for (byte i = 0; i < (sizeof(scale) / sizeof(scale[0])); i++) {
lengthOfScale += 1;
}
}
void loop() {
digitalWrite(trigger, HIGH);
digitalWrite(trigger, LOW);
distance = pulseIn(echo, HIGH);
note = map(distance, 250, distanceHigh, scale[0], scale[lengthOfScale - 1]);
for (byte j = 0; j < (lengthOfScale); j++) {
if (note == scale[j]) {
tone(piezo, note);
break;
}
else if (note > scale[j] && note < scale[j + 1]) {
note = scale[j];
tone(piezo, note);
break;
}
}
delay(30);
}
Letzte Aktualisierung am 2024-12-21 / Affiliate Links / Bilder von der Amazon Product Advertising API