Maker Pro

DIY Arduino Musical Instrument-Theremin with 4 sound modes

July 19, 2021 by Mirko Pavleski

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

The Theremin is an electronic musical instrument controlled without physical contact by the thereminist (performer). It is named after its inventor, Leon Theremin, who patented the device in 1928.

This time I will show you how to make such an instrument that produces tones or sounds based on the light that falls on the surface of the Photoresistor. By moving your hand over the photoresistor, the intensity of light falling on it, changes, and that change the pitch. The device is very simple to build and can be successfully made by a beginner. It also does not require a separate power supply and is powered via the USB port of Arduino.


Contains only a few components:

- Arduino nano microcontroller

- Photoresistor

- Speaker

- Two trimmer potentiometers

- and two resistors

In the sketch, the measured brightness is assigned a minimum and a maximum tone frequency (pitchMin and pitchMax). However, these values ​​can still be changed during runtime with two trimmer potentiometers. An additional button switches between 4 different modes one after the other. When the program is started, a 440 Hz tone is output for 5 seconds. During this time, the LDR is calibrated, and the minimum and maximum incidence of light are measured. As soon as the calibration process is finished, the "no sound" mode starts and you only hear sounds when you have pressed the button.

Finally, the device is mounted in a suitable box made of PVC board, lined with colored wallpaper.

Untitled Sketch 2_bb.jpg
#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_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_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);

void loop()
    if ((millis() - lastPressedButton > 250) && digitalRead(PIN_BUTTON) == LOW) {
        lastPressedButton = millis();
        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) {
        } else if (buttonState == 3) {
        else if (buttonState == 4) {
    } else {

Related Content


You May Also Like