Building a Simple Arduino Theremin

Created: 2024-12-28 17:20:55 | Last updated: 2024-12-28 17:20:55 | Status: Public

This guide will walk you through building a simple electronic theremin using an Arduino. The theremin uses an ultrasonic sensor for pitch control and a photoresistor for volume control, creating an intuitive musical instrument that responds to hand movements.

Required Components

  • Arduino Uno or similar microcontroller
  • HC-SR04 ultrasonic distance sensor
  • Piezo buzzer
  • Photoresistor
  • 10kΩ resistor
  • Breadboard
  • Jumper wires

Circuit Diagrams

Logical Connection Diagram

The following Mermaid.js diagram shows the logical connections between components:

graph LR A[Arduino Uno] --- P1[Pin 5V] A --- P2[Pin GND] A --- P3[Pin 11] A --- P4[Pin 12] A --- P5[Pin 8] A --- P6[Pin A0] US[HC-SR04 Sensor] --- US1[VCC] US --- US2[GND] US --- US3[TRIG] US --- US4[ECHO] PB[Piezo Buzzer] --- PB1[+] PB --- PB2[-] PR[Photoresistor] --- PR1[Pin 1] PR --- PR2[Pin 2] R[10kΩ Resistor] --- R1[Pin 1] R --- R2[Pin 2] %% Connections P1 === US1 P2 === US2 P3 === US3 P4 === US4 P5 === PB1 P2 === PB2 P1 === PR1 PR2 === P6 PR2 === R1 R2 === P2 classDef arduino fill:#e6ccff,stroke:#333,stroke-width:2px classDef component fill:#b3ffcc,stroke:#333,stroke-width:2px classDef pin fill:#ffcc99,stroke:#333,stroke-width:1px class A arduino class US,PB,PR,R component class P1,P2,P3,P4,P5,P6,US1,US2,US3,US4,PB1,PB2,PR1,PR2,R1,R2 pin

Technical Circuit Diagram

Here’s a more detailed technical diagram showing the physical connections:




Arduino
Uno

<!-- Pin labels -->
<text x="260" y="200" font-family="Arial" font-size="12">5V</text>
<text x="260" y="240" font-family="Arial" font-size="12">GND</text>
<text x="260" y="280" font-family="Arial" font-size="12">11</text>
<text x="260" y="320" font-family="Arial" font-size="12">12</text>
<text x="260" y="360" font-family="Arial" font-size="12">8</text>
<text x="260" y="400" font-family="Arial" font-size="12">A0</text>

<!-- HC-SR04 Sensor -->
<rect x="500" y="50" width="120" height="80" fill="#b3ffcc" stroke="#333" stroke-width="2"/>
<text x="515" y="90" font-family="Arial" font-size="12">HC-SR04</text>
<text x="480" y="70" font-family="Arial" font-size="10">VCC</text>
<text x="480" y="90" font-family="Arial" font-size="10">GND</text>
<text x="480" y="110" font-family="Arial" font-size="10">TRIG</text>
<text x="480" y="130" font-family="Arial" font-size="10">ECHO</text>

<!-- Piezo Buzzer -->
<circle cx="500" cy="250" r="30" fill="#b3ffcc" stroke="#333" stroke-width="2"/>
<text x="480" y="255" font-family="Arial" font-size="12">Buzzer</text>

<!-- Photoresistor -->
<path d="M 500 400 L 540 400 L 560 380 L 580 420 L 600 380 L 620 420 L 640 400 L 680 400" 
      fill="none" stroke="#333" stroke-width="2"/>
<circle cx="500" cy="400" r="3" fill="#333"/>
<circle cx="680" cy="400" r="3" fill="#333"/>
<text x="550" y="440" font-family="Arial" font-size="12">Photoresistor</text>

<!-- 10k Resistor -->
<path d="M 500 500 L 540 500 L 560 480 L 580 520 L 600 480 L 620 520 L 640 500 L 680 500" 
      fill="none" stroke="#333" stroke-width="2"/>
<text x="560" y="540" font-family="Arial" font-size="12">10kΩ</text>

<!-- Connections -->
<!-- 5V connections -->
<path d="M 250 200 L 400 200 L 400 70 L 500 70" fill="none" stroke="red" stroke-width="1.5"/>
<path d="M 400 200 L 400 400 L 500 400" fill="none" stroke="red" stroke-width="1.5"/>

<!-- GND connections -->
<path d="M 250 240 L 350 240 L 350 90 L 500 90" fill="none" stroke="#333" stroke-width="1.5"/>
<path d="M 350 240 L 350 280 L 470 280" fill="none" stroke="#333" stroke-width="1.5"/>
<path d="M 350 240 L 350 500 L 500 500" fill="none" stroke="#333" stroke-width="1.5"/>

<!-- Signal connections -->
<path d="M 250 280 L 300 280 L 300 110 L 500 110" fill="none" stroke="blue" stroke-width="1.5"/>
<path d="M 250 320 L 320 320 L 320 130 L 500 130" fill="none" stroke="blue" stroke-width="1.5"/>
<path d="M 250 360 L 470 360 L 470 280" fill="none" stroke="blue" stroke-width="1.5"/>
<path d="M 250 400 L 280 400 L 280 450 L 680 450 L 680 400" fill="none" stroke="blue" stroke-width="1.5"/>

<!-- Connection between photoresistor and resistor -->
<path d="M 680 400 L 680 500" fill="none" stroke="blue" stroke-width="1.5"/>

<!-- Legend -->
<rect x="50" y="50" width="150" height="80" fill="white" stroke="#333"/>
<text x="60" y="70" font-family="Arial" font-size="12">Legend:</text>
<line x1="60" y1="85" x2="100" y2="85" stroke="red" stroke-width="1.5"/>
<text x="110" y="90" font-family="Arial" font-size="12">Power (5V)</text>
<line x1="60" y1="105" x2="100" y2="105" stroke="#333" stroke-width="1.5"/>
<text x="110" y="110" font-family="Arial" font-size="12">Ground</text>
<line x1="60" y1="125" x2="100" y2="125" stroke="blue" stroke-width="1.5"/>
<text x="110" y="130" font-family="Arial" font-size="12">Signal</text>

Assembly Instructions

  1. Connect the HC-SR04 ultrasonic sensor:
    - VCC → Arduino 5V
    - GND → Arduino GND
    - TRIG → Pin 11
    - ECHO → Pin 12

  2. Connect the piezo buzzer:
    - Positive lead → Pin 8
    - Negative lead → GND

  3. Create the photoresistor circuit:
    - Connect one leg of photoresistor → 5V
    - Connect other leg → both analog pin A0 and the 10kΩ resistor
    - Connect other end of 10kΩ resistor → GND

Arduino Code

// Simple Arduino Theremin using an ultrasonic sensor and piezo buzzer
// Hardware needed:
// - Arduino Uno or similar
// - HC-SR04 ultrasonic sensor
// - Piezo buzzer
// - Photoresistor
// - 10kΩ resistor
// - Jumper wires

const int TRIG_PIN = 11;    // Ultrasonic sensor trigger pin
const int ECHO_PIN = 12;    // Ultrasonic sensor echo pin
const int BUZZER_PIN = 8;   // Piezo buzzer pin
const int LIGHT_PIN = A0;   // Photoresistor analog pin

// Frequency range for the theremin (in Hz)
const int MIN_FREQ = 100;
const int MAX_FREQ = 2000;

// Distance range for hand detection (in cm)
const int MIN_DIST = 5;
const int MAX_DIST = 50;

void setup() {
  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
  pinMode(BUZZER_PIN, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  // Get distance from ultrasonic sensor
  long duration, distance;
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);

  duration = pulseIn(ECHO_PIN, HIGH);
  distance = duration * 0.034 / 2;  // Convert to centimeters

  // Get light level from photoresistor
  int lightLevel = analogRead(LIGHT_PIN);
  int volume = map(lightLevel, 0, 1023, 0, 255);

  // Map distance to frequency
  if (distance >= MIN_DIST && distance <= MAX_DIST) {
    int frequency = map(distance, MIN_DIST, MAX_DIST, MAX_FREQ, MIN_FREQ);

    // Apply volume control using photoresistor
    if (volume > 10) {  // Threshold to prevent noise
      tone(BUZZER_PIN, frequency);
    } else {
      noTone(BUZZER_PIN);
    }

    // Debug output
    Serial.print("Distance: ");
    Serial.print(distance);
    Serial.print("cm, Frequency: ");
    Serial.print(frequency);
    Serial.print("Hz, Volume: ");
    Serial.println(volume);
  } else {
    noTone(BUZZER_PIN);
  }

  delay(50);  // Small delay to stabilize readings
}

How It Works

The theremin operates using two main controls:

  1. Pitch Control: The ultrasonic sensor detects hand distance between 5-50cm and maps it to frequencies between 100-2000 Hz. Moving your hand closer produces higher pitches, while moving it away produces lower pitches.

  2. Volume Control: The photoresistor detects light levels and controls the volume. Covering the photoresistor reduces the volume, while uncovering it increases the volume. This creates a natural gesture-based volume control.

Troubleshooting

If you encounter issues:

  1. Check all connections match the circuit diagrams exactly
  2. Verify the Arduino code was uploaded successfully
  3. Open the Serial Monitor (9600 baud) to view debug information
  4. Ensure the room has adequate lighting for the photoresistor
  5. Verify the ultrasonic sensor is not obstructed

Extensions

Some possible modifications to enhance the theremin:

  1. Add a second ultrasonic sensor for independent volume control
  2. Implement different waveforms for varied sound qualities
  3. Add LED indicators that respond to pitch and volume
  4. Include preset scales or modes for more musical control
  5. Add a calibration routine for different lighting conditions

Safety Notes

  • The piezo buzzer can produce high-frequency sounds. Start testing at lower frequencies and volumes.
  • While this circuit uses safe voltage levels, always disconnect power before making changes to the circuit.
  • Keep the components and Arduino away from moisture and conductive materials.