Week 10 – Assignment – Music Box

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.

Leave a Reply