(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 ThereminFirst, 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!
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 itAfter 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 sketchNow 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. π
Comments
Please log in or sign up to comment.