Building a Theremin-Style Musical Instrument with Arduino

For this week’s assignment, I built a simple musical instrument using an Arduino SparkFun RedBoard. The goal was to make something you actually play in real time, not just a melody that runs on its own.

The Idea

I wanted the instrument to feel intentional. You turn a knob to pick a pitch, then press a button to sound it. Release the button and it goes silent. It is a small but satisfying loop that mimics the feel of a real instrument. The design was loosely inspired by a theremin, where pitch is continuous and the player decides when to trigger sound.

Components

The build uses five parts: a SparkFun RedBoard, a piezo buzzer, a 10k ohm potentiometer, a tactile push button, and a breadboard with jumper wires. The potentiometer is the analog sensor and the button is the digital sensor, which together satisfy both requirements for the assignment.

Demo

The Code

The sketch reads the potentiometer value on every loop, maps it to one of 22 notes across a C major scale from C3 to C6, and plays that note with tone() only while the button is held down. No extra libraries are needed beyond pitches.h for the note frequencies.

#include "pitches.h"

const int BUZZER_PIN = 8;
const int BUTTON_PIN = 2;
const int POT_PIN    = A0;

int scale[] = {
  NOTE_C3, NOTE_D3, NOTE_E3, NOTE_F3, NOTE_G3, NOTE_A3, NOTE_B3,
  NOTE_C4, NOTE_D4, NOTE_E4, NOTE_F4, NOTE_G4, NOTE_A4, NOTE_B4,
  NOTE_C5, NOTE_D5, NOTE_E5, NOTE_F5, NOTE_G5, NOTE_A5, NOTE_B5,
  NOTE_C6
};
const int SCALE_SIZE = sizeof(scale) / sizeof(scale[0]);

void setup() {
  pinMode(BUZZER_PIN, OUTPUT);
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  Serial.begin(9600);
}

void loop() {
  bool buttonHeld = (digitalRead(BUTTON_PIN) == LOW);
  int  potValue   = analogRead(POT_PIN);
  int  noteIndex  = map(potValue, 0, 1023, 0, SCALE_SIZE - 1);
  int  currentNote = scale[noteIndex];

  if (buttonHeld) {
    tone(BUZZER_PIN, currentNote);
  } else {
    noTone(BUZZER_PIN);
  }

  delay(20);
}

How It Works

The potentiometer outputs a voltage between 0V and 5V as the knob turns. analogRead() converts that into a number from 0 to 1023, and map() scales it down to an index between 0 and 21, selecting a note from the scale array. The button uses Arduino’s built-in INPUT_PULLUP setting, so it reads HIGH when open and LOW when pressed, with no external resistor required. While the button is held, tone() drives the buzzer at the selected frequency. Letting go calls noTone() and the sound stops immediately.

Reflections

The trickiest part was getting comfortable with the breadboard layout. Once that clicked, the wiring became straightforward. If I were to extend this project, I would add a second button to switch between different scales, which would open up more musical variety without much added complexity.

Leave a Reply