Arduino Theremin

Wikipedia …

The theremin originally known as the ætherphone/etherphone, thereminophone or termenvox/thereminvox is an early electronic musical instrument controlled without discernible physical contact from the player.

It is named after the westernized-name of its Russian inventor, Léon Theremin, who patented the device in 1928. The controlling section usually consists of two metal antennas which sense the position of the player’s hands and control oscillators for frequency with one hand, and amplitude (volume) with the other, so it can be played without being touched. The electric signals from the theremin are amplified and sent to a loudspeaker.

Having played about with the HC-SR04 Ultrasonic Ranger, I though this would be a quick and easy demo to my ever patient family of it’s uses.  There was a bit more to this project than I first expected.  I re-learned (after over 25 years) how to make an audio oscillator from a 555 astable multivibrator.  Then control the pitch of the tone using a digital potentiometer over the SPI interface of the Arduino.

The pitch of the tone is varied over a range of detected distances of the ultrasonic ranger.  Too close or too far and the tone is disabled by taking the reset pin of the 555 timer low.

The controlling pins from the Arduino are as follows:

  • Control of the HC-SR04 Ultrasonic Range Sensor:
    • D2 – Echo
    • D3 – Trigger
  • SPI control of the MCP4131 digital potentiometer:
    • D10 – Chip Select
    • D11 – SDI/SDO
    • D13 – SCK
  • Control of 555 Timer:
    • D12 – Reset

The schematic is shown below:

Figure 1 - Schematic

Below is the Arduino sketch:

#include <SPI.h>
#include <NewPing.h>

// set pin 10 as the slave select for the digital pot:
const int slaveSelectPin = 10;
// set pin 12 as the reset pin for the 555 timer
const int timerEnablePin = 12;

// Arduino pin tied to trigger pin on the ultrasonic sensor.
#define TRIGGER_PIN  3
// Arduino pin tied to echo pin on the ultrasonic sensor.
#define ECHO_PIN     2
// Maximum distance we want to ping for (in centimeters). Check device datasheet.
#define MAX_DISTANCE 4000

NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.

int level = 0;
int distance = 0;

void setup()
{
	// set the slaveSelectPin as an output:
	pinMode (slaveSelectPin, OUTPUT);
	// set the 555 timer enable pin to output
	pinMode (timerEnablePin, OUTPUT);
	// disable the 555 timer
	digitalWrite(timerEnablePin, LOW);

	// initialize SPI:
	SPI.begin();

	// Open serial monitor at 115200 baud to see ping results.
	Serial.begin(115200);
}

void loop()
{
	// Send ping, get ping time in microseconds (uS).
	unsigned int uS = sonar.ping();
	// Convert ping time to distance
	distance = uS / US_ROUNDTRIP_CM;

	// Print distance to serial console
	Serial.print("Ping: ");
	Serial.print(uS / US_ROUNDTRIP_CM);
	Serial.println("cm");

	if (distance < 11)
	{
		// too close - disable the 555 timer
		digitalWrite(timerEnablePin, LOW);
	}
	else if (distance > 52)
	{
		// too far - disable the 555 timer
		digitalWrite(timerEnablePin, LOW);
	}
	else
	{
		// set potentiometer level to a value proportional to distance
		level = int ((distance - 10) * 3) + 1;
		digitalPotWrite(level);
		// enable the 555 timer
		digitalWrite(timerEnablePin, HIGH);
	}
	delay(100);
}

// SPI transation to set the value of the digital pot
int digitalPotWrite(int value)
{
  //take the SS pin low to select the chip:
  digitalWrite(slaveSelectPin, LOW);
  //send in the address and value via SPI:
  SPI.transfer(0);
  SPI.transfer(value);
  // take the SS pin high to de-select the chip:
  digitalWrite(slaveSelectPin, HIGH);
}

2 thoughts on “Arduino Theremin

    • Unfortunately not as I’ve disassembled it & am using the parts for other things. The sound, to be honest, wasn’t the greatest. But it was a fun experiment.

Leave a Reply

Your email address will not be published. Required fields are marked *