For the assignment we were required to use an analog sensor and a digital sensor to create a musical instrument. We came up with the idea of using an ultrasonic sensor as our analog input and also incorporated the servo motor to add a physical dimension to the instrument. The overall concept of our project is inspired from a music box that is wound to play the music.
We created a disc with small stick figures placed around at different distances and attached it to the servo motors. As the servo motor rotates the different positions of the figures serve as an input to the sensor to change the delay between the notes of the tune being played through the piezo speaker. Additionally, we have used a button as the digital sensor to restart the rotation of the disc from its initial position.
#include <Servo.h> #define TRIG_PIN 7 #define ECHO_PIN 6 #define SPEAKER_PIN 8 #define BUTTON_PIN 2 Servo myservo; bool soundProduced = false; int servoSpeed = 3; // Initial servo speed unsigned long debounceDelay = 50; unsigned long lastButtonPress = 0; bool buttonState; bool lastButtonState = LOW; void setup() { Serial.begin(9600); pinMode(TRIG_PIN, OUTPUT); pinMode(ECHO_PIN, INPUT); pinMode(SPEAKER_PIN, OUTPUT); pinMode(BUTTON_PIN, INPUT_PULLUP); myservo.attach(9); } void loop() { // Read the button state buttonState = digitalRead(BUTTON_PIN); // Check for button press if (buttonState == HIGH && lastButtonState == LOW && millis() - lastButtonPress > debounceDelay) { // Change servo speed servoSpeed += 1; // Increase servo speed by 1 degree lastButtonPress = millis(); } lastButtonState = buttonState; // Rotate the servo in a carousel motion with adjustable speed for (int pos = 0; pos <= 360; pos += servoSpeed) { myservo.write(pos % 180); // Limit the position within the 0-180 degrees range delay(5); checkDistanceAndSound(); } } void checkDistanceAndSound() { int duration, distance; digitalWrite(TRIG_PIN, LOW); delayMicroseconds(2); digitalWrite(TRIG_PIN, HIGH); delayMicroseconds(10); digitalWrite(TRIG_PIN, LOW); duration = pulseIn(ECHO_PIN, HIGH); distance = (duration * 0.0343) / 2; // Play different melodies for different distance ranges if (distance > 0 && distance <= 5 && !soundProduced) { playMelody1(); soundProduced = true; delay(2000); } else if (distance > 5 && distance <= 10 && !soundProduced) { playMelody2(); soundProduced = true; delay(2000); } else if (distance > 10 && distance <= 20 && !soundProduced) { playMelody3(); soundProduced = true; delay(2000); } else { noTone(SPEAKER_PIN); soundProduced = false; } } void playMelody1() { int melody[] = {262, 294, 330, 349, 392, 440, 494, 523}; // First melody int noteDurations[] = {250, 250, 250, 250, 250, 250, 250, 250}; for (int i = 0; i < 8; i++) { tone(SPEAKER_PIN, melody[i], noteDurations[i]); delay(noteDurations[i]); } } void playMelody2() { int melody[] = {392, 440, 494, 523, 587, 659, 698, 784}; // Second melody int noteDurations[] = {200, 200, 200, 200, 200, 200, 200, 200}; for (int i = 0; i < 8; i++) { tone(SPEAKER_PIN, melody[i], noteDurations[i]); delay(noteDurations[i]); } } void playMelody3() { int melody[] = {330, 330, 392, 392, 440, 440, 330, 330}; // Third melody int noteDurations[] = {500, 500, 500, 500, 500, 500, 1000, 500}; for (int i = 0; i < 8; i++) { tone(SPEAKER_PIN, melody[i], noteDurations[i]); delay(noteDurations[i]); } }
It was an interesting experience to use the ultrasonic sensor with the speaker and I hope to explore their working in more detail in future projects.