Description:
This is an instrument (don’t ask me the name) in which the user can play by utilizing a straight object and locating it at a certain position to play a note. The user can also distort that sound by turning the cup if so they wish.
Idea:
I actually got the inspiration from the clarinet. I wanted something that would be able to play in between the ranges of notes. However, at the end I think that I tried to simulate a piano more. I wanted to use the ultrasonic sensor to play the main notes and then have something similar to a pedal to change them. Now it is more of a distorter than a pedal, but the idea is there.
This is how the project looks like from the player’s perspective.
Process
I started by adding an ultrasonic sensor and a speaker to the circuit. (Please ignore the capacitor, it was there for class). I learned how to send and receive waves with the sensor in order to calculate distance. Afterwards, I made an array of sounds (middle C section) and mapped the distance to the number of notes in the array in order to assign a specific note to each distance. I then tested it out with my hand.
The sensor did not gave perfect values so there was a need to clean the information that it was getting. Even then there were still values that were off and I found it better to use a straight surface rather than my hand to make the sounds.
It was very difficult to control when a sound would change only with that so I added a button so that the instrument plays only when the button is pressed.
I thought that it would be interesting if the user could modify the pitch of the note by using some sort of additional feature and after much pondering, I decided to use the photosensor. To have better control of the amount of light received I choose to put the photosensor inside a cup. It was a very weird thing to do, specially with all the tape and I had to use female jumper wires for this.
Then I put it all together: the code for the ultrasonic sensor and that for the distortion (photosensor). This part was by far the hardest because merging them messed up some of the sounds and I had to find a way to make the notes sound normal when the photosensor is in the rest position. It took a lot of experimentation and debugging to get this part right. I still think there are better ways of doing what I did, but it works.
This is how it looked at the end:
For a better user experience, I decided to add the location of each of the notes as can be seen in the first image of this post.
Challenges:
SO MANY. This was a very stressful process because one moment something was working and the next everything was crashing.
- Figuring out what to do for the project in the first place.
- My ultrasonic sensor throws random values most of the time, even when I refined the noise there still were some values that were off, but 7amdullah it didn’t interfere with the program that much for playing. I also used a straight surface rather than my hand to play from the distance sensor side which helped regulate the values.
- Been able to play a melody without the program crashing
- The button sometimes continued to read pressed even though it wasn’t (specially after a couple minutes of running the program).
- Combining the distortion effect of the photosensor with the actual note been played from the distance.
- Just figuring out how to do things in general. (So many ideas, so few good ones ;-; cries in Arduino)
- I am very bad with tape and keeping the photosensor in contact with the wire.
- I had other problems (as you will noticed from all the prints in my code) but I am so glad that it now works that I don’t want to remember the trauma.
- Not my most aesthetic project: There are wires everywhere!
Circuit
*Note: in this image the ultrasonic sensor is inverted because I could’t flip its image. Furthermore, there is not cup for the photosensor since TinkerCad doesn’t have that feature
Final Result
Code
# include "pitches.h" int echoPin = 5; //pin of the echo of the distance sensor: receives the wave int trigPin = 6; //pin of the trigger of the distance sensor: sends the wave long duration; //duration of sending and receiving the wave long distance; //distance calculate by the sensor int buttonPin = 2; //pin of the button const int numReadings = 10; //number of readings to get the average int readings[numReadings]; // the readings from the analog input int readIndex = 0; // the index of the current reading int total = 0; // the running total int average = 0; // the average int noteFreq = 0; // the final frequency used to play the note int photocensorPin = A0; //pin of the photosensor float photoValue; //value received from the photosensor void setup() { pinMode(echoPin, INPUT); pinMode(trigPin, OUTPUT); pinMode(buttonPin, INPUT); pinMode(photocensorPin, INPUT); //int notes[8] = {NOTE_C4,NOTE_D4,NOTE_E4,NOTE_F4,NOTE_G4, NOTE_A4, NOTE_B4, NOTE_C5}; //int sound = 0; //tone(11, notes[sound]); // you have to round this // it allows you to access the //you go up one note to change to a Sharp/bemol // (pow(2,(noteNumber-69.)/12.)*440) // initialize all the readings to 0 for (int thisReading = 0; thisReading < numReadings; thisReading++) { readings[thisReading] = 0; } Serial.begin(9600); } void loop() { //PROGRAMMING THE ULTRASONIC SENSOR--------------------------------------------------------- //send the wave and receive it digitalWrite(trigPin, LOW); delayMicroseconds(2); digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); //collect the data of the duration of the pulse duration = pulseIn(echoPin, HIGH); //convert the duration to distance //0.340 is the speed (centimeters per microseconds) distance = (duration / 2) * .0340; //Serial.println(distance); //GETTING VALUES FROM THE PHOTOSENSOR------------------------------------------------------- photoValue = analogRead(photocensorPin); //Serial.println(photoValue); int distortion = map(photoValue, 300, 800, 0, 50); //int noteNumber = map(photoValue, 0, 1023, 0, 120); //int note = (pow(2, (noteNumber - 69.) / 12.) * 440); // tone(11, note); //UPLOAD NOTES----------------------------------------------------------------------------- //make an array with the note pitches int notes[8] = {NOTE_C4, NOTE_D4, NOTE_E4, NOTE_F4, NOTE_G4, NOTE_A4, NOTE_B4, NOTE_C5}; //if the parst ten values are some note and it doesn't change, then leave that note //if the note changes for more than 3 than change the note //CHECK BUTTON STATE----------------------------------------------------------------------- bool currButtonState = digitalRead(buttonPin); //Serial.println(currButtonState); //PLAY INSTRUMENT-------------------------------------------------------------------------- // if button is not pressed and distance is not within range, don't play anything if (distance < 0 && distance > 20 && !currButtonState) { noTone(11); } //play the note else { //this variable changed the distance to a value for the array int sound = map(distance, 0, 20, 0, 8); //Serial.println("Distance"); //Serial.println(distance); //Serial.println("Sound"); //Serial.println(sound); total = total - readings[readIndex]; // read from the sensor: readings[readIndex] = sound; // add the reading to the total: total = total + readings[readIndex]; // advance to the next position in the array: readIndex = readIndex + 1; // if we're at the end of the array... if (readIndex >= numReadings) { // ...wrap around to the beginning: readIndex = 0; } // calculate the average: average = total / numReadings; //Serial.print(sound); //Serial.print(" "); //Serial.println(average); //Serial.println(distortion); //Change NOTE FREQUENCY //if there it distortion if (distortion > 0, distortion < 50) { //add the distotion to the note noteFreq = notes[average] + distortion; } else { //just have the note without distortion noteFreq = notes[average]; } //if button is pressed if (currButtonState) { //play the note tone(11, noteFreq, 100); } //tone(11, notes[average], 100); //Serial.println(average); } }
Nice performance! Twinkle twinkle little strange star…. Great job!