Mirko Pavleski
Published © GPL3+

DIY Arduino Musical Instrument-Theremin with 4 Sound Modes

This instrument produces tones or sounds based on the light that falls on the surface of the photoresistor.

BeginnerFull instructions provided4,889
DIY Arduino Musical Instrument-Theremin with 4 Sound Modes

Things used in this project

Hardware components

Arduino Nano R3
Arduino Nano R3
×1
Speaker: 0.25W, 8 ohms
Speaker: 0.25W, 8 ohms
×1
Photo resistor
Photo resistor
×1
Single Turn Potentiometer- 100k ohms
Single Turn Potentiometer- 100k ohms
×2
Resistor 10k ohm
Resistor 10k ohm
×1
Pushbutton Switch, Momentary
Pushbutton Switch, Momentary
×1

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
Solder Wire, Lead Free
Solder Wire, Lead Free

Story

Read more

Schematics

Schematic diagram

Code

Arduino code

C/C++
#define PIN_PIEZO    9
#define PIN_BUTTON   2
#define PIN_LDR      A0
#define PIN_POTI_MIN A1
#define PIN_POTI_MAX A2

#define CALIBRATION_DURATION 5 // in seconds

// Pitch definitions in Hz
#define PITCH_MIN_LOWER 5
#define PITCH_MIN_UPPER 170
#define PITCH_MAX_LOWER 20
#define PITCH_MAX_UPPER 1000

int sensorValue = 0, sensorMin = 700, sensorMax = 0;
int pitchMin = PITCH_MIN_LOWER, pitchMax = PITCH_MAX_LOWER;
unsigned long lastPressedButton = 0;
byte buttonState = 0;

void setup()
{
    pinMode(PIN_PIEZO, OUTPUT);
    pinMode(PIN_BUTTON, INPUT_PULLUP);
    pinMode(PIN_POTI_MIN, INPUT);
    pinMode(PIN_POTI_MAX, INPUT);

    tone(PIN_PIEZO, 440);
    while (millis() < (CALIBRATION_DURATION * 1000)) {
        sensorValue = analogRead(PIN_LDR);
        sensorMax = max(sensorValue, sensorMax);
        sensorMin = min(sensorValue, sensorMin);
    }
    noTone(PIN_PIEZO);
}

void loop()
{
    if ((millis() - lastPressedButton > 250) && digitalRead(PIN_BUTTON) == LOW) {
        lastPressedButton = millis();
        buttonState++;
        buttonState %= 5;
    }

    pitchMin = PITCH_MIN_LOWER + map(analogRead(PIN_POTI_MIN), 0, 1023, 0, PITCH_MIN_UPPER);
    pitchMin = constrain(pitchMin, PITCH_MIN_LOWER, PITCH_MIN_UPPER);
    pitchMax = PITCH_MAX_LOWER + map(analogRead(PIN_POTI_MAX), 0, 1023, 0, PITCH_MAX_UPPER);
    pitchMax = constrain(pitchMax, PITCH_MAX_LOWER, PITCH_MAX_UPPER);

    if (buttonState > 0) {
        sensorValue = analogRead(PIN_LDR);

        // apply the calibration to the sensor reading
        sensorValue = map(sensorValue, sensorMin, sensorMax, pitchMin, pitchMax);

        // in case the sensor value is outside the range seen during calibration
        sensorValue = constrain(sensorValue, pitchMin, pitchMax);

        tone(PIN_PIEZO, sensorValue);

        if (buttonState == 2) {
            delay(160);
        } else if (buttonState == 3) {
            delay(50);
        }
        else if (buttonState == 4) {
            delay(250);
        }
    } else {
        noTone(PIN_PIEZO);
    }
}

Credits

Mirko Pavleski

Mirko Pavleski

150 projects • 1283 followers

Comments