Theremins are nifty electronic instruments. A musician can define frequency and amplitude by waving their hands over two distance-sensing antennas, resulting in a remarkably expressive sound. Building a real theremin isn’t trivial (they work by turning your body into a variable capacitor in an oscillator circuit!), but if you have an Arduino, a pressure sensor, a ping sensor, and a buzzer/speaker, you can put together an approximation in an afternoon.

This schematic describes how the toy theremin is implemented. Ping sensors gauge distance by sending out an ultrasonic pulse and measuring the time it takes for the pulse to return. Getting a continuous pitch response (like in a real theremin) is straightforward. Once we have a distance, we can use the Arduino map() function to convert distances into frequencies measured in Hz. For reference, the A above middle C is 440 Hz. Map your frequencies to a regime that sounds best for your buzzer. To generate the sound, we use the Arduino’s built-in pulse width modulation (PWM) which outputs a square wave at our desired frequency.
The problem is that continuous pitch mode is really hard to play. In a real instrument, say a violin, the length of the string isn’t linearly proportional to frequency like we programmed our theremin to be. This can be improved by using the real formula for the fundamental frequency of a string: , where
denotes length,
denotes string tension, and
represents the linear mass density. From some googling I found that, for a violin, reasonable values for
and
are 8 × 10-4 kg/m and 60 N, respectively.
I’m not a violinist though, so this trick won’t make me sound any better. Instead, we can choose to add a switch which we poll in software to toggle the theremin between continuous and discrete pitch modes. First we’ll map distance to an integer index i; 0 to 11 will give us an octave and a half. I want to play songs in the major scale, so let’s make a list of an octave and a half of the scale in terms of half steps: int scale[] = {0, 2, 4, 5, 7, 9, 11, 12, 14, 16, 17, 19};
. Now we have a procedure to convert distance to half steps: int n = scale[i];
! Finally, we can calculate the frequency with the formula , where n is the half step number and f0 is somewhere between 440 and 880 Hz (the reason this formula works is fascinating! Check out the MinutePhysics video on the subject).
Finally, it’s time to add dynamics so we can play with some soul. A pressure sensor is great because it’s just a variable resistor, so we can use it to modulate the amplitude of the PWM signal in hardware. There are a lot of ways to do this. The easiest is to just put the pressure sensor in series with the buzzer/speaker. Resistance is lower when you press it, so applying pressure will increase the voltage drop across the buzzer, causing louder output, making the instrument extremely intuitive to play. If you’re feeling fancier, you could instead incorporate the pressure sensor into the feedback circuit of an op-amp.
Without further ado, The First Noel on the theremin!