Das Theremin (auch: Thereminvox, Thereminovox, Termenvox, ursprünglich Aetherophon, genannt auch Ätherwelleninstrument) ist ein 1920 erfundenes elektronisches Musikinstrument. Es ist das einzige verbreitete Musikinstrument, das berührungslos gespielt wird und dabei direkt Töne erzeugt. Sein Name geht auf den Erfinder, den Russen Lew Termen, zurück, der sich in den USA Leon Theremin nannte.
Ein Theremin besitzt ursprünglich zwei Antennen, wobei eine für die Veränderung der Lautstärke (engl. volume) und die andere für die Veränderung der Tonhöhe (engl. pitch) zuständig ist. Durch Annäherung/Entfernung der Hand verändert man leicht die Kapazität eines elektrischen Schwingkreises. Dadurch ändert sich auch die Frequenz des Schwingkreises. Mittels eines zweiten, unbeeinflussten Schwingkreises wird dann diese Frequenzänderung hörbar gemacht.
Mein mit dem Arduino umgesetztes Theremin verwendet anstelle der elektrischen Schwingkreise Abstandssensoren. Diese bestimmen den Abstand der Hände zum Sensor. Die beiden Abstände werden dann in eine Tonhöhe bzw. Lautstärke umgewandelt. Um die Lautstärke des Tons zu verändern, kommt ein digitales Potentiometer vom Typ MCP41010 zum Einsatz. Über dieses Potentiometer wird der auszugebende Ton an einen Audioverstärker (mit dem Chip LM386) weitergeleitet.
Als Abstandssensoren können entweder die beliebten Ultraschallsensoren vom Typ HC-SR04, oder Abstandssensoren vom Typ Sharp GP2Y0A41SK0F verwendet werden.

Bildquelle: Von Bettmann, Corbis – http://tygodnik.onet.pl/35,0,57107, sowiecki_faust, artykul.html (polish), https://commons.wikimedia.org/w/index.php?curid=24020691, public domain









Arduino-Code:
#include <SPI.h> // include the SPI library
#define CS_Pin 10 // CS_Pin of MCP41010
#define ECHOPIN_volume 2 // Pin to receive echo pulse
#define TRIGPIN_volume 3 // Pin to send trigger pulse
#define ECHOPIN_pitch 4 // Pin to receive echo pulse
#define TRIGPIN_pitch 5 // Pin to send trigger pulse
#define SPEAKER_Pin 6 // Pin für Lautsprecher
float frequency; // put out frequency
float volume; // put out volume
float distance_pitch; // distance for pitch-control
float distance_volume; // distance for volume-control
// ===================
// ====== SETUP ======
// ===================
void setup()
{
Serial.begin(9600);
pinMode (CS_Pin, OUTPUT); // CS_Pin is an output
pinMode(ECHOPIN_volume, INPUT);
pinMode(TRIGPIN_volume, OUTPUT);
pinMode(ECHOPIN_pitch, INPUT);
pinMode(TRIGPIN_pitch, OUTPUT);
pinMode(SPEAKER_Pin, OUTPUT);
SPI.begin(); // initialize SPI:
}
// ===========================
// ========== LOOP ===========
// ===========================
void loop()
{
// ==============================
// ultra sonic distance for pitch
// ==============================
digitalWrite(TRIGPIN_pitch, LOW); // Set the trigger pin to low for 2uS
delayMicroseconds(2);
digitalWrite(TRIGPIN_pitch, HIGH); // Send a 10uS high to trigger ranging
delayMicroseconds(10);
digitalWrite(TRIGPIN_pitch, LOW); // Send pin low again
distance_pitch = pulseIn(ECHOPIN_pitch, HIGH) / 58.0; // Read in times pulse
frequency = 4000.0 / (distance_pitch + 1.0);
//frequency = (1500.0 / 23.0) * (25.0 - distance_pitch); // points (2/1500) and (25/0)
if (frequency < 30)
{
frequency = 0.0;
}
if (frequency > 1400)
{
frequency = 1400.0;
}
// ===============================
// ultra sonic distance for volume
// ===============================
digitalWrite(TRIGPIN_volume, LOW); // Set the trigger pin to low for 2uS
delayMicroseconds(2);
digitalWrite(TRIGPIN_volume, HIGH); // Send a 10uS high to trigger ranging
delayMicroseconds(10);
digitalWrite(TRIGPIN_volume, LOW); // Send pin low again
distance_volume = pulseIn(ECHOPIN_volume, HIGH) / 58.0; // Read in times pulse
/*
volume = 255.0 / (distance_volume + 1.0);
if (volume > 255.0)
{
volume = 255.0;
}
*/
volume = (255.0 / 23.0) * (25.0 - distance_volume); // points (2/255) and (25/0)
if (volume > 255.0)
{
volume = 255.0;
}
if (volume < 0)
{
volume = 0.0;
}
Serial.print("d = ");
Serial.print(distance_pitch,0);
Serial.print(" f = ");
Serial.print(frequency,0);
Serial.print(" volume = ");
Serial.println(volume,0);
tone(SPEAKER_Pin,(int)frequency); // sending the pitch to the speaker-pin
digitalPotWrite((int)volume); // sending the volume to the digital poti
//delay(50); // Wait 50mS before next ranging
}
// ============================
// ======== SUBROUTINE ========
// ============================
void digitalPotWrite(byte value)
{
// take the SS pin low to select the chip:
digitalWrite(CS_Pin,LOW);
SPI.transfer(B00010001); // The command byte
SPI.transfer(value); // The data byte
// take the SS pin high to de-select the chip
digitalWrite(CS_Pin,HIGH);
}
