Project tutorial
Arduino Theremin with A Minor Pentatonic

Arduino Theremin with A Minor Pentatonic © CC BY-NC-ND

In this project you will learn how to build a simple Arduino Theremin with a piezo buzzer and the HC-SR04 ultrasonic sensor.

  • 749 views
  • 0 comments
  • 5 respects

Components and supplies

Apps and online services

About this project

(Translated with DeepL)

In this project you will learn how to build a simple Arduino Theremin with a piezo buzzer and the HC-SR04 ultrasonic sensor. But that's not all - so that even inexperienced musicians can inspire their friends, this theremin plays only tones in the popular A minor pentatonic scale. ūüôā

The A minor pentatonic scale consists of 5 (greek penta) tones that fit together very well and is very popular in rock, pop and blues. Since this Arduino Theremin only plays these notes (over several octaves), it is almost impossible to make a mistake.

Even better, you can use it to accompany many songs you know from the radio - including the evergreen "Stairway To Heaven" by Led Zeppelin.The A minor pentatonic scale consists of 5 (greek penta) tones that fit together very well and is very popular in rock, pop and blues. Since this Arduino Theremin only plays these notes (over several octaves), it is almost impossible to make a mistake.

The construction of the Arduino Theremin

First, connect the four wires to your ultrasonic sensor.

Connect the cables for VCC and GND to your Arduino Uno with 5V and GND.

The cable from the echo pin on the sensor is connected to digital pin 4, Trig is connected to digital pin 5.First, connect the four wires to your ultrasonic sensor.
Connect the cables for VCC and GND to your Arduino Uno with 5V and GND.

The connected ultrasonic sensor should look like this:


Next, plug the piezo buzzer directly into the Arduino at the opposite pin header. Plug one leg into GND and the other into digital pin 10.

Please note: If the legs of your piezo buzzer are further apart or closer together, you can also plug one of them into pin 9 or 11. But then you have to take care to adjust your sketch accordingly. More about this later.

And that's it. Your theremin's hardware is ready to go!

Upload the sketch and play your first piece of music

If the sketch is uploaded successfully, you will have 5 seconds to calibrate your theremin. To do this, place your hand in front of the sensor and slowly move it away from the sensor to increase the distance to the sensor. The distance at the end of the calibration should be at least 50 cm to make your theremin easy to use.

The distance from the sensor to the maximum distance of your hand is now your "playing area". You can think of it like the keys of a piano, which are distributed at different distances between your sensor and your hand.

Don't worry, if you missed your entry for calibration, just press Reset on your Arduino and the calibration will start all over again.

Immediately after calibration, your Theremin will start playing. Slowly move your hand towards the sensor and back again. Can you feel how the distance between your hands produces different sounds?

In the beginning you will play the different tones more or less randomly, but the more you practice, the more familiar the function of the theremin becomes.

As mentioned earlier, you cannot make mistakes - all the notes belong to A minor pentatonic scale.

Print out the box and assemble it

After your first experiments it is time for a real box, because that is what makes your Theremin a real musical instrument. Inside the box the hardware disappears, so that only the ultrasonic sensor is visible (and the cable for the power supply of course).

First print out the template on sturdy paper or cardboard with at least 160g/sqm. Make sure you print out the box in full size.

Then cut out the template along the solid line. On the front of the box, cut out the two holes for the "eyes" of the ultrasonic sensor. Last but not least, you need a hole for the power supply: Make sure to cut out the hole for the USB port. It is possible that the tabs cover the holes for USB or 9V. Just shorten them so they don't get in the way of your connections.

If you want to power your Arduino via USB as well, you don't need to cut the hole for the 9V battery.

Now bend the template 90¬į at each dotted line. Finally, apply some glue to the glue tab and make your box ... a box.

You can already close the bottom side (with the hole for the power supply). Now put the sensor into the box and press its "eyes" from the inside through the two corresponding holes. Now slide your Arduino with the USB port to the front and close the box behind it.

Understanding the sketch

Now let's take a closer look at the sketch for your Arduino Theremin.

1) Variables and Constants

First of all, you define a few variables and constants that you will need later in your sketch:

const‚Äč ‚Äčint‚Äč trigger = ‚Äč5‚Äč; 
const‚Äč ‚Äčint‚Äč echo = ‚Äč4‚Äč;
const‚Äč ‚Äčint‚Äč piezo = ‚Äč10‚Äč;

int‚Äč distance = ‚Äč0‚Äč;
int‚Äč distanceHigh = ‚Äč0‚Äč;
int‚Äč lengthOfScale = ‚Äč0‚Äč;
int‚Äč note = ‚Äč0‚Äč;

The constants ‚Äčtrigger and ‚Äčecho define the corresponding pins to which you have connected the ultrasonic sensor on your Arduino.

The constant ‚Äčpiezo defines the pin where you have plugged the second leg of your piezo buzzer. ‚ÄčIf this is not pin 10 for you, enter the correct pin here.

You need the following four variables to store more information:

  • distance:‚Äč The current distance of your hand to the sensor.
  • distanceHigh: The maximum distance of your hand, as you defined it in the calibration.
  • lengthOfScale: The number of notes in the scale you are currently using for your Theremin. Initially this is the A minor pentatonic scale, but you can use any other scale with any number of notes later.
  • note: ‚ÄčThe note that your theremin has detected and will play next.


2) Scales

Your Theremin initially plays the A minor pentatonic, which looks like this in your sketch:

//A minor pentatonic
int‚Äč scale[] = {
‚Äč147‚Äč, ‚Äč165‚Äč, ‚Äč196‚Äč, ‚Äč220‚Äč, ‚Äč262‚Äč, ‚Äč294‚Äč, ‚Äč330‚Äč, ‚Äč392‚Äč, ‚Äč440‚Äč, ‚Äč523‚Äč, ‚Äč587‚Äč, ‚Äč659‚Äč, ‚Äč784‚Äč, ‚Äč880‚Äč, ‚Äč1047‚Äč, ‚Äč1175‚Äč, ‚Äč1319‚Äč, ‚Äč1568‚Äč, ‚Äč1760‚Äč, ‚Äč2093‚Äč, ‚Äč2349
};

This is an array containing a total of 21 notes of the A minor pentatonic: A‚Äč-C-D-E-G

Note: How many tones and octaves you use in a scale is up to you. The variable ‚ÄčlengthOfScale‚Äč, which you defined above, makes sure that your Theremin can handle it.


3) Setup and calibration of your theremin

Next, let's look at the first part of the setup function:

void setup() {
pinMode(trigger, OUTPUT);
pinMode(echo, INPUT);

while (millis() < 5000) {
digitalWrite(trigger, HIGH);
digitalWrite(trigger, LOW);
distance = pulseIn(echo, HIGH);

if (distance > distanceHigh) {
distanceHigh = distance;
}
}

Here you first define the functionality of the two pins of the ultrasonic sensor, which you have defined as constants in the sketch above: The pin trigger gives the sensor the command to emit an ultrasonic wave, therefore ‚ÄčOUTPUT‚Äč. At pin ‚Äčecho,‚Äč the signal returned by your hand arrives again, therefore ‚ÄčINPUT‚Äč.

In the following ‚Äčwhile loop the calibration takes place. For five seconds, your ultrasonic sensor repeatedly sends out an ultrasonic wave and receives it again after it has been reflected by your hand. Your Arduino measures the time elapsed between sending and receiving.

Let's take a closer look at this:

In the condition of the while loop you will find the function millis().‚Äč It measures the time since the start or reset of your Arduino. The loop is executed until five seconds ( = 5000 milliseconds) have passed.

while‚Äč (‚Äčmillis‚Äč() < ‚Äč5000‚Äč) {

In the loop itself you first set the ‚Äčtrigger to HIGH with the function ‚ÄčdigitalWrite() and send an ultrasonic wave. Immediately after that you turn thetrigger off again with L‚ÄčOW‚Äč.

With the function ‚Äčpulsein() you measure the time in microseconds that the wave needs to reach the sensor again and set the pin echo to ‚ÄčHIGH.‚Äč This time span is stored in the variable d‚Äčistance‚Äč.

digitalWrite‚Äč(trigger, ‚ÄčHIGH‚Äč); 
digitalWrite‚Äč(trigger, ‚ÄčLOW‚Äč);
distance = ‚ÄčpulseIn‚Äč(echo, ‚ÄčHIGH‚Äč);

Now comes the important part. You don't just want to measure the distance to your hand for five seconds, but you want to define the maximum distance and thus your "playing area".

For this purpose you defined the variable ‚ÄčdistanceHigh at the beginning of the sketch, in which this maximum distance is stored during the calibration.

If your Arduino detects in the loop that your hand is just further away from the sensor than in the last measurement, it sets the variable d‚ÄčistanceHigh‚Äč to the new maximum distance.

if‚Äč (distance > distanceHigh) { 
distanceHigh = distance;
}

See the Arduino reference for more details on ‚Äčwhile loops,‚Äč digitalWrite()‚Äč, m‚Äčillis()‚Äč and p‚Äčulsein()‚Äč.


4) Calculate the length of the scale

In your sketch the default scale is the A minor pentatonic with 21 notes. But you can also add more tones if you want. Or even another scale with fewer single notes. Or all tones of the world!

So that you don't have to write the length of your scales and their lowest and highest notes manually in your sketch, your Arduino does it for you.

for (‚Äčbyte i = ‚Äč0‚Äč; i < (‚Äčsizeof‚Äč(scale) / ‚Äčsizeof(‚Äč scale[‚Äč0‚Äč])); i++) {
lengthOfScale += ‚Äč1‚Äč;
}

Here another type of loop comes into play: the ‚Äčfor loop.‚Äč It goes through the array with your scale entry by entry and counts in the variable ‚ÄčlengthOfScale how many entries it finds there by increasing the variable by 1 with each check.

Unfortunately, in the C++ programming language this is only possible with a trick: First you calculate the length of the array in bytes with the function ‚Äčsizeof() and then divide it by the length of the first element in the array.

In case you are wondering about the 0 between the brackets []: Your sketch does not start counting at 1 in an array, but at 0, so it finds the first element with the ‚Äčindex [0]‚Äč.

sizeof‚Äč(scale) / ‚Äčsizeof‚Äč(scale[‚Äč0‚Äč])

In the preset A minor pentatonic scale, the loop finds a total of 21 notes and stores this number in the variable. In the next step of the sketch this number is used right away.

5) Finding the (approximately) right tone

In the meantime we have arrived at the loop function in your sketch. Here you first use the function map() to determine the note that your theremin should play.

note = ‚Äčmap‚Äč(distance, ‚Äč250‚Äč, distanceHigh, scale[‚Äč0‚Äč], scale[lengthOfScale - ‚Äč1‚Äč]);

To execute the function ‚Äčmap(),‚Äč you need five so-called parameters:

  • distance:‚Äč The current distance of your hand.
  • 250: The smallest possible distance from the sensor. This is in the range of 250, which is why we simply define it as fixed here.
  • distanceHigh: The maximum distance of your hand, as you defined it in the calibration at the beginning.
  • scale[0]: ‚ÄčThe lowest note in your scale. This is the first entry in your array that you can read with the i‚Äč ndex [0]‚Äč.
  • scale[lengthOfScale - 1]: The highest note in your scale. The default A minor pentatonic scale has a length of 21 notes - since you start counting at 0, you have to subtract 1 at the end to read the last note.


Now the function does the following:

It first takes the current distance in the variable ‚Äčdistance,‚Äč which according to parameters is in a range from 250 to the maximum distance of your hand. Then it "maps" this range to your scale, which in turn extends from the first entry in the array ‚Äčscale[0] to the last entry scale[lengthOfScale - 1].

This way it maps the current distance of your hand to a frequency and thus to approximately one note in the scale. But of course we are not satisfied with approximately, because your

Arduino Theremin with A Minor Pentatonic Scale ‚Äčpollux labs Arduino Theremin is supposed to play exactly the notes of the scale. ‚ÄčFor this we need another for loop.


6) Strike the right note

So let's get to the last part of the sketch. Here you determine with a for loop and two statements exactly the note your Arduino Theremin should play - and finally play it.

for‚Äč (‚Äčbyte‚Äč j = ‚Äč0‚Äč; j < (lengthOfScale); j++) {
‚Äč if‚Äč (note == scale[j]) { ‚Äčtone‚Äč(piezo, note) ‚Äčbreak‚Äč;
}
‚Äčelse‚Äč ‚Äčif‚Äč (note > scale[j] && note < scale[j + ‚Äč1‚Äč]) {
note = scale[j]; ‚Äčtone‚Äč(piezo, note); ‚Äčbreak‚Äč;
}
}

Let's take a closer look at the code. First, in the condition of the for loop, you specify that it should (if necessary) go through all notes of the scale. Then follow two statements that search for a matching correct note here and play it as soon as it is found:

The first ‚Äčif statement is for professional players. If your hand and the note found by the function ‚Äčmap() matches exactly one note of the scale, your piezo buzzer gets a command with the function ‚Äčtone() to play this note immediately and end the loop with b‚Äčreak‚Äč.

The following else if statement works like this: If the note found by the ‚Äčmap() function is between two notes in the array, the piezo buzzer will play the lower of the two. This statement will probably come up in most cases, unless you always hit the right distance to the sensor.

And that's it! Turn on your Arduino Theremin, calibrate it and play some music. ūüôā

Code

Gist

Custom parts and enclosures

Theremin Box
A box where you can store your Theremin in.

Comments

Similar projects you might like

Real Theremin Using Open.Theremin Shield for Arduino

Project showcase by Urs Gaudenz

  • 20,166 views
  • 9 comments
  • 26 respects

Hand Glove Light Theremin

by Hamlet

  • 2,838 views
  • 0 comments
  • 10 respects

I2S Theremin

Project tutorial by Arduino_Genuino

  • 22,870 views
  • 3 comments
  • 26 respects

Arduino Bluetooth Robot for Android Device

Project showcase by aip06

  • 4,947 views
  • 2 comments
  • 19 respects

Light Sensitive Theremin

Project tutorial by 3 developers

  • 2,820 views
  • 0 comments
  • 3 respects

Theremino

Project showcase by opus9

  • 2,543 views
  • 3 comments
  • 5 respects
Add projectSign up / Login