Concept:
Moeez and I collaborated on a project and aimed to push our limits. Our goal was to create a table piano using an ultrasonic sensor, a sensor we had never used before. As we reminisced about our experiences with musical instruments, we recognized the hassle the school music band encountered carrying bulky and expensive pianos around. To tackle this issue, we came up with a solution: a table piano. We attached the sensor and the Arduino to the table and marked lines on the table using a scale and a marker. A fixed point was established at the end to indicate the piano’s length. We divided the piano into seven notes and utilized the Serial Monitor to determine the distance for each “Piano Key.” Afterwards, we researched online and discovered the notes that play “Jingle Bells” and assigned them to the keys in the table piano. To enhance the piano’s functionality, we included two buttons – one to switch the sensor on and off and the other to play “Jingle Bells” automatically. The first button controlled the sensor and simultaneously controlled the LED as well. This was done to allow the user to know when the sensor is on and when it is off. The second button was implemented as an auto-tune feature to enable users to listen to the tune first and then practice the keys themselves to replicate the tune. The good thing about this piano is that you can add or remove as many keys as you want and practice on specific keys too. Additionally, it is beginner-friendly and portable.
Code and Circuit:
As we built-up upon previous class knowledge of how circuits and Arduino code works, we found the implementing process to be relatively easy. The code and circuit looks like this:
//Define the pins used for the ultrasonic sensor, buzzer, buttons, and LED const int pingPin = 2; //Trigger Pin of Ultrasonic Sensor const int echoPin = 3; //Echo Pin of Ultrasonic Sensor const int buzzerPin = 8; const int redButton = A3; const int yellowButton = A2; const int LEDbutton = 7; //Initialize variables used in the program int pressed = 0; long distance = 0; int redPosition = 0; int yellowPosition = 0; int redCount = 1; int yellowCount = 1; //Include the pitches library for generating tones #include "pitches.h" void setup() { //Start serial communication at 9600 baud Serial.begin(9600); //Set the ultrasonic sensor pins as output and input respectively pinMode(pingPin, OUTPUT); pinMode(echoPin, INPUT); //Set the button pins as inputs and the LED pin as an output pinMode(redButton, INPUT); pinMode(yellowButton, INPUT); pinMode(LEDbutton, OUTPUT); //Turn off the LED initially digitalWrite(LEDbutton, LOW); } void loop() { //Read the positions of the red and yellow buttons redPosition = digitalRead(redButton); delay(100); //add delay to avoid double reading accidentally yellowPosition = digitalRead(yellowButton); delay(100); //Increment the appropriate button count if a button is pressed if (redPosition == HIGH) { redCount++; } if (yellowPosition == HIGH) { yellowCount++; } //Play Jingle Bells and turn off the LED if both button counts are even (both buttons pressed) if (redCount % 2 == 0 && yellowCount % 2 == 0) { digitalWrite(LEDbutton, LOW); //LED turned off to tell that sensor turned off jingleBells(); } else if (redCount % 2 == 0) //if only the red button is pressed and the count is even { sensorReading(); //then start the sensor digitalWrite(LEDbutton, HIGH); //turn on LED to indicate the sensor is on } else if (yellowCount % 2 == 0) //if yellow button is pressed and is even { jingleBells(); //play Jingle Bells digitalWrite(LEDbutton, LOW); //turn off LED to indicate sensor is off } else { digitalWrite(LEDbutton, LOW); //if none of the buttons were pressed and no counter was even noTone(8); //play nothing } } //Function to read the ultrasonic sensor and play a tone based on the distance measured void sensorReading() { //Send a short low pulse digitalWrite(pingPin, LOW); delay(2); //delay to avoid complications digitalWrite(pingPin, HIGH); //sends a high pulse for 10 microseconds delay(10); digitalWrite(pingPin, LOW); distance = pulseIn(echoPin, HIGH); //Measure the duration of the ultrasonic pulse and calculate the distance distanceNotes(distance); //play the notes based on the distance delay(408); } //function that plays jingle bells automatically void jingleBells() { tone(buzzerPin, NOTE_E4, 400); delay(408); tone(buzzerPin, NOTE_E4, 400); delay(408); tone(buzzerPin, NOTE_E4, 400); delay(408); tone(buzzerPin, NOTE_E4, 400); delay(408); tone(buzzerPin, NOTE_E4, 400); delay(408); tone(buzzerPin, NOTE_E4, 400); delay(408); tone(buzzerPin, NOTE_E4, 400); delay(408); tone(buzzerPin, NOTE_G4, 400); delay(408); tone(buzzerPin, NOTE_C4, 400); delay(408); tone(buzzerPin, NOTE_D4, 400); delay(408); tone(buzzerPin, NOTE_E4, 400); delay(408); tone(buzzerPin, NOTE_F4, 400); delay(408); tone(buzzerPin, NOTE_F4, 400); delay(408); tone(buzzerPin, NOTE_F4, 400); delay(408); tone(buzzerPin, NOTE_F4, 400); delay(408); tone(buzzerPin, NOTE_F4, 400); delay(408); tone(buzzerPin, NOTE_F4, 400); delay(408); tone(buzzerPin, NOTE_E4, 400); delay(408); tone(buzzerPin, NOTE_E4, 400); delay(408); tone(buzzerPin, NOTE_E4, 400); delay(408); tone(buzzerPin, NOTE_E4, 400); delay(408); tone(buzzerPin, NOTE_D4, 400); delay(408); tone(buzzerPin, NOTE_D4, 400); delay(408); tone(buzzerPin, NOTE_E4, 400); delay(408); tone(buzzerPin, NOTE_D4, 400); delay(408); tone(buzzerPin, NOTE_G4, 400); delay(408); yellowCount++; //yellow count increments to stop the tune from playing again (not on loop) } void distanceNotes(long distance) { if (distance >= 1750) //if the distance is greater than 1750 { noTone(8); //then dont play anything pressed = 0; //reinitialize the key pressed variable to 0 so other keys can be pressed } else if (distance >= 1520 && pressed == 0) //for each distance, there is a specific note { tone(buzzerPin, NOTE_E4, 400); pressed = 1; //do this to avoid the same note being played repeatedly } else if (distance >= 1220 && pressed == 0) { tone(buzzerPin, NOTE_G4, 400); pressed = 1; } else if (distance >= 960 && pressed == 0) { tone(buzzerPin, NOTE_C4, 400); pressed = 1; } else if (distance >= 800 && pressed == 0) { tone(buzzerPin, NOTE_D4, 400); pressed = 1; } else if (distance >= 350 && pressed == 0) { tone(buzzerPin, NOTE_F4, 400); pressed = 1; } else if (distance < 350 && pressed == 0) { tone(buzzerPin, NOTE_B0, 400); pressed = 1; } }
Final Product:
The final circuit and implementation looks like this:
Future Improvements:
For the future, we would want to get better ranged sensors to increase the length of the piano. Moreover, an idea that came to our minds a bit too late was allowing the user to press a button and then record what they have played. Then pressing another button would play the tune they have played for them to fully analyze their progress. In the future, we would want to add other tunes that the user could access using different buttons for practice. Additionally, the user accessing different preset keys could also be a possible improvement. Apart from all of this, the Jingle Bells function could have been implemented better using an array and a for-loop.