Mini Piano

Concept

Initially, Aigerim and I set out to create a tool similar to Singing Horses using Arduino. We envisioned a project with multiple buzzers that could produce a unique melody when played together. However, we quickly realized that Arduino does not have built-in functionality to play music on multiple buzzers simultaneously. This was a challenge we needed to overcome if we wanted to create the tool we had envisioned.

Complications

After some brainstorming, we decided to switch gears and create a mini piano instead. We programmed the mini piano with three buttons, each of which would play a specific note when pressed. We also incorporated a pressure sensor that could modify the frequency of the note when pressure was applied to a pin.

To make this work, we had to tinker with the pressure sensor, buttons, and Arduino board. It took some time to figure out the best way to program each button to play its assigned note and adjust the frequency when pressure was applied. But with some experimentation and perseverance, we were able to make it work.

Creating this mini piano required some creative problem-solving and coding skills. While we had to adjust our original plan, we were pleased with the final outcome. The addition of a pressure-sensitive pin adds a unique element to the mini piano, making it a fun and interactive tool to play with.

Music with Distance

Concept.

How would playing the piano with the feet at an arcade center look on a small scale? That was how I arrived at this mini-project. To make it easier for any user, I specifically picked notes (of Fur Elise) in ascending order of distance (cm).

Implementation.

The distance instrument works simply by moving an obstacle in front of an ultrasonic sensor at an interval of 1cm. This was implemented using if-else statements.

Tools Used.

The project features an ultrasonic sensor, a buzzer, jumper wires, a 10k ohm resistor, and a switch.

Challenges

Some challenges I encountered while undertaking this project involved difficulty in figuring out the specific notes to make up the music used. Once that was figured out, all the was left was to provide the best if-else condition statement to control the notes.

 

Code

/*Assignment

Author: Aaron Wajah
Concept: Making Fur Elise melody with arduino
Date: 11-04-2023

*/


// Define pins for ultrasonic sensor, switch, and buzzer.
const int trigPin = 10;
const int echoPin = 11;
const int switchPin = 2;
const int buzzerPin = 8;

// Define variables
long duration;
int distance;
int switchState = LOW;
int prevswitchState=0;

bool buttonPressed=false;

//defining notes for melody. 
const int notes[] = { 659, 622, 659, 622, 659, 494, 587, 523, 440};

const int quarterNote = 250;
// Define durations for each note (in quarter notes)
const int durations[] = { 4, 8, 8, 4, 8, 8, 4, 8, 8 };


void setup() {
  // Initialize serial communication
  Serial.begin(9600);

  // Set pins as input/output
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(switchPin, INPUT_PULLUP); // Use internal pull-up resistor
  pinMode(buzzerPin, OUTPUT);
}

void loop() {
  // Read switch state
  switchState = digitalRead(switchPin);

  // Only take a measurement if switch is pressed
  if (switchState == HIGH ) {
    

    int duration =  quarterNote*1.2;

    // Send a pulse to trigger the sensor
    digitalWrite(trigPin, LOW);
    delayMicroseconds(2);
    digitalWrite(trigPin, HIGH);
    delayMicroseconds(10);
    digitalWrite(trigPin, LOW);

    // Measure the duration of the echo pulse
    duration = pulseIn(echoPin, HIGH);

    // Calculate distance in centimeters
    distance = duration / 58;

    // Print distance to serial monitor
    Serial.print("Distance: ");
    Serial.print(distance);
    Serial.println(" cm");


    if(distance==2){
      tone(buzzerPin, notes[0], duration);
      delay(duration * 1.3);
    }
    if(distance==3){
      tone(buzzerPin, notes[1], duration);
      delay(duration * 1.3);
    }
    if(distance==4){
      tone(buzzerPin, notes[2], duration);
      delay(duration * 1.3);
    }
    if(distance==5){
      tone(buzzerPin, notes[3], duration);
      delay(duration * 1.3);
    }
    if(distance==6){
      tone(buzzerPin, notes[4], duration);
      delay(duration * 1.3);
    }
    if(distance==7){
      tone(buzzerPin, notes[5], duration);
      delay(duration * 1.3);
    }
    if(distance==8){
      tone(buzzerPin, notes[6], duration);
      delay(duration * 1.3);
    }
    if(distance==9){
      tone(buzzerPin, notes[7], duration);
      delay(duration * 1.3);
    }
    if(distance==10){
      tone(buzzerPin, notes[8], duration);
      delay(duration * 1.3);
    }
    
    noTone(8);
  
  }
  
  // Wait before taking another measurement
  delay(500);
}

 

Week 10 – Table Piano

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.

Week 10 – Table Piano

Concept:

Zaid 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. 

 

Week 10 – Musical Instrument

Concept and Implementation

For this assignment, we wanted to make a musical instrument that was controlled by a user’s motion. So, we came up with the idea of changing the output tone based on the input from a flex sensor. For this, we attached a flex sensor to a glove so that when a user wears the glove and bends their hand, the input changes, and depending on how much the user bends their hand, the tone changes. To implement this, we saved a number of notes in an array. The input from the flex sensor is mapped to values between 0 and the size of the array so that for different measurements of the ‘bend’ of the hand, a different number is obtained after mapping and a note is picked from the array at that number. Moreover, we used a switch to play another tone, so that when the switch is turned on, a different tone made up of a set of notes is played. When the switch is turned off, the user can control the output melody using their hand. We played with different durations and frequencies until we found the one we liked.

Schematic

Video

Code

#include "pitches.h"
const int Buzzer1=3;
const int flexPin = A0;
int value; 
//array of notes
int melody[] = {
  NOTE_E5, NOTE_D5, NOTE_C5, NOTE_D5, NOTE_E5, NOTE_E5, NOTE_E5,
  NOTE_D5, NOTE_D5, NOTE_D5, NOTE_E5, NOTE_G5, NOTE_G4, NOTE_E5,
  NOTE_D5, NOTE_C5, NOTE_D5, NOTE_E5, NOTE_E5, NOTE_E5, NOTE_E5,
  NOTE_D5, NOTE_D5, NOTE_E5, NOTE_D5, NOTE_C5
};
void setup()
{
  Serial.begin(9600);
  pinMode(Buzzer1, OUTPUT);
  pinMode(A2, INPUT);
}
void loop()
{
  int button = digitalRead(A2);
  //when button is pressed, play a predefined tone (happy brithday music)
  if (button == HIGH)
  {
    Serial.print("SWITCH ON\n");
    //tone(Buzzer1, 200, 1200);
    // play a melody using tone()
  tone(Buzzer1, NOTE_C4, 250); delay(250);
  tone(Buzzer1, NOTE_C4, 250); delay(250);
  tone(Buzzer1, NOTE_D4, 500); delay(500);
  tone(Buzzer1, NOTE_C4, 500); delay(500);
  tone(Buzzer1, NOTE_F4, 500); delay(500);
  tone(Buzzer1, NOTE_E4, 1000); delay(1000);
 
  tone(Buzzer1, NOTE_C4, 250); delay(250);
  tone(Buzzer1, NOTE_C4, 250); delay(250);
  tone(Buzzer1, NOTE_D4, 500); delay(500);
  tone(Buzzer1, NOTE_C4, 500); delay(500);
  tone(Buzzer1, NOTE_G4, 500); delay(500);
  tone(Buzzer1, NOTE_F4, 1000); delay(1000);
  }
  //if button is not pressed, read value from flex sensor
  //map the value to a number that is within 0 and the max index of array melody
  //use this mapped value as an index and play the note from that particular index 
  else if (button == LOW)
  {
    Serial.print("OFF\n");
  
  value= analogRead(flexPin);
  // Serial.print("\nvalue is: ");
  // Serial.print(value);
  int size = sizeof(melody)/sizeof(melody[0]);
  value = map(value, 850, 1050, 0, size);
  
  tone(Buzzer1,melody[value],1200);
  //Serial.print("\n Note is: " );
  //Serial.print(melody[value]);
  delay(300);
  }
}

Future Improvements

For later, we can improve by first attaching the flex sensor inside the glove more securely so that the instrument produces more consistent sounds. Also, we can add an additional buzzer with the switch to play a sound continuously in the back while the user uses the flex sensor to add more sounds on top of it.

Groupmate: Ramsha Bilal

 

Assignment 7: Music Composer

Concept

As part of the 7th Assignment for Introduction to Interactive Media, we were tasked with producing a Musical Instrument with the usage of at least one digital sensor, and at least one analog sensor.

Given the requirements, we brainstormed the most sensible application of an analog sensor and concluded that utilizing a potentiometer as a versatile music mixer would be ideal. To add to its functionality, we also explored incorporating various DJ-inspired modes, which proved to be an exciting prospect.

As a result, we decided to pursue this idea further, making it to be somewhat of a mini make-do music composer – where you could produce sounds as well as play music!

Implementation

We decided to start off with a button (red colored) that was solely for the purposes of changing, or flipping through the different modes of the composer. Then, there would be a Piezo Buzzer that produced sound, but controlled by 2 additional Buttons and a Potentiometer, alongside a Servo Motor which would act as a Drum Stick.

Since Arduino does not have any specific mode for switching ‘off’, we decided to have the first mode as an ‘inactive’ state. Then, when the button is pressed, it becomes a music player which plays Melodies that can be essentially changed by the potentiometer. For this, the values of the Potentiometer are mapped to a range of 100-1000, and then there are ‘if’ conditions to check if it is between certain ranges, and so corresponding music would play.

Moving forward, our next mode, the Creative Mode, is very intriguing. It activates the Servo Motor to function as a Drum Stick, and in our case, instead of drums, we utilized a steel mug and a ceramic mug to produce sounds of different quality and pitch. The other two buttons in our circuit would be controlling the direction of the stick, whether it would hit the ceramic, or the steel mug. On top of this, in this mode, the Potentiometer would have its Analog Values mapped to multiples of 50 in the range from 100-1000, and would subsequently have the capacity to produce additional sounds, adding some composure.

The last mode, is the Piano Mode, where the Two Buttons would simply act as Keyboard Keys, and would be limited to produce two types of sounds. However, the Potentiometer would essentially fluctuate these values using a formula. With this, we could fluctuate the Potentiometer like a Mixer and use the two buttons as keys to produce interesting continuous sounds.

With this, we have demonstrated how only the usage of 2 buttons, a Piezo Buzzer and a Potentiometer can be used in different permutations and produce varying types of sounds. The flexibility offered by the Arduino with a breadboard offers limitless opportunities.

Demo Video

A demo video, in detail, can be seen here:

Pictures of Circuit

Difficulties

The first difficulty that we faced was to replace the traditional usage of ‘delays’ to be replaced with a consistently running timer. This was particularly in the first mode, the music player mode, wherein we would have to switch to another mode by pressing the red button, however having pressed that during a delay would have caused issue. We catered to this using one of the Arduino’s standard examples of ‘BlinkWithoutDelay’ and utilized the millis() function to keep a track of time on our own.

Moreover, the project was becoming a complex state machine, and difficult to manage. We wanted to add more buttons for the Piano, however there was a choice between going for a complex looking and difficult to manage circuit, or actually utilizing minimal equipment in creative ways.

Being new to Arduino, we initially thought of keeping loose wires, instead of buttons, which would trigger the piano notes. However, after spending hours of trying out ways with which we would have loose pins connected to the arduino where a connection would play a not, we improvised the usage of the same buttons to play the notes.

Improvements

With such a project, the perception becomes very subjective with multiple ways of improvement. However, something that we definitely see is making the project more easy to use and adding more options in each stage. More melodies in the first mode, more options to create in the second mode, and more piano buttons in the third mode.

Code

Specific Segments

Starting off with the General State Machine, we have used the click of a button, tracked by a previous state and a current state which calculates if there is a change in the state of button (when its pressed again, not held). Once a change occurs, the value of the button state is set such that an appropriate mode is switched on:

// To change the MODES of the Instrument
if(lastredButtonState == HIGH && currentredButtonState == LOW) {
  Serial.print("RED Button is pressed: ");

  Serial.println(redButtonState);

  // Change the state of LED
  if(redButtonState == 0) {
    redButtonState = 1;  
    Serial.println("Opening the Infinite Playing Mode");
  }
  else if (redButtonState == 1){
    redButtonState = 2;
    Serial.println("Changing to the Creative Mode");
  }
  else if (redButtonState == 2){
    redButtonState = 3;
    Serial.println("Changing to the Piano Mode");
  }
  else{
    redButtonState = 0;
    Serial.println("Switching the Instrument off");
  } 
}

When a button state is set, there is another condition in the loop() function which repeatedly checks if that mode is switched on. In the case that the state is 1, we have to play music of two different melodies depending on the potentiometer’s value. However, the important thing is to ensure we dont use delays since we could be changing the mode while the music is playing, and do not want to have to wait.

Therefore, the following piece of code makes use of the millis() function and keeps track of an internal timer.

if (redButtonState == 1){
  // Beginning of an Infinite Playing Mode
  val = map(val, 0, 1023, 100, 1000);     // scale it for use with the servo (value between 0 and 180)

  currentMillis = millis();
  if (currentMillis - previousMillis >= noteDuration + pauseBetweenNotes) {
    previousMillis = currentMillis;
    // stop the previous note
    noTone(8);

    if (val>450){
      // play the next note
      noteDuration = 1000 / noteDurations[noteIndex];
      tone(8, melody[noteIndex], noteDuration);
      pauseBetweenNotes = noteDuration * 0.30;
      // move to the next note
      noteIndex = (noteIndex + 1) % melodyLength;
    }
    else{
      // play the next note
      noteDuration = 1000 / noteDurations2[noteIndex];
      tone(8, melody2[noteIndex], noteDuration);
      pauseBetweenNotes = noteDuration * 0.30;
      // move to the next note
      noteIndex = (noteIndex + 1) % melodyLength2;
    }

  }
  // add a small delay to avoid overloading the processor
  delay(1);
  // End of the Infinite Playing Mode
}

For our creative mode, we simply move the motor in the specified directions with the following code, alongside playing a continuous tone that just varies with the value of the potentiometer.

else if (redButtonState == 2){
  // Serial.println("Creative Mode");
// BEGINNING OF CREATIVE MODE

  // check if the pushbutton is pressed. If it is, the buttonState is HIGH:
  if (yelButtonState == HIGH) {
    // print out the value you read:
    Serial.println("YELLOW PRESSED");
    myservo.write(180); 
  } 
  else if (bluButtonState == HIGH)
  {
    // print out the value you read:
    Serial.println("NOT YELLOW");
    myservo.write(0); 
  }
  else 
  {
    myservo.write(90);
  }

  val = map(val, 0, 1023, 100, 1000);     // scale it for use with the servo (value between 0 and 180)
  val = 50 * ((val + 49) / 50);
  if(val>250){
    tone(8, val, 200);
  }

// END OF CREATIVE MODE
}
Overall Code

While the specific segments are highlighted above, the entire code may give more insights of the project:

/*
  Musical Instrument
  Created 10 April, 2023
  by Ishmal Khalid and Zunair Viqar
*/

#include <Servo.h>
#include "pitches.h"

int melody[] = {
  // Pink Panther theme
  // Score available at https://musescore.com/benedictsong/the-pink-panther
  // Theme by Masato Nakamura, arranged by Teddy Mason
  REST, REST, REST, NOTE_DS4, 
  NOTE_E4, REST, NOTE_FS4, NOTE_G4, REST, NOTE_DS4,
  NOTE_E4, NOTE_FS4,  NOTE_G4, NOTE_C5, NOTE_B4, NOTE_E4, NOTE_G4, NOTE_B4,
  NOTE_AS4, NOTE_A4, NOTE_G4, NOTE_E4, NOTE_D4, 
  NOTE_E4, REST, REST, NOTE_DS4,

  NOTE_E4, REST, NOTE_FS4, NOTE_G4, REST, NOTE_DS4,
  NOTE_E4, NOTE_FS4, NOTE_G4, NOTE_C5, NOTE_B4, NOTE_G4, NOTE_B4, NOTE_E5,
  NOTE_DS5,   
  NOTE_D5, REST, REST, NOTE_DS4,
  NOTE_E4, REST, NOTE_FS4, NOTE_G4, REST, NOTE_DS4,
  NOTE_E4, NOTE_FS4, NOTE_G4, NOTE_C5, NOTE_B4, NOTE_E4, NOTE_G4, NOTE_B4,
  
  NOTE_AS4, NOTE_A4, NOTE_G4, NOTE_E4, NOTE_D4,
  NOTE_E4, REST,
  REST, NOTE_E5, NOTE_D5, NOTE_B4, NOTE_A4, NOTE_G4, NOTE_E4,
  NOTE_AS4, NOTE_A4, NOTE_AS4, NOTE_A4, NOTE_AS4,NOTE_A4,NOTE_AS4,NOTE_A4,
  NOTE_G4, NOTE_E4, NOTE_D4, NOTE_E4, NOTE_E4, NOTE_E4
};

int noteDurations[] = {
  // Pink Panther theme
  // Score available at https://musescore.com/benedictsong/the-pink-panther
  // Theme by Masato Nakamura, arranged by Teddy Mason
  2,4,8,8, 
  4 ,8,8,4,8,8,
  8 ,8, 8,8,8,8,8,8,   
  2 ,16,16,16,16,
  2 ,4,8,4,

  4,8,8,4,8,8,
  8,8,8,8,8,8,8,8,
  1,   
  2,4,8,8, 
  4,8,8,4,8,8,
  8,8, 8,8,8,8,8,8,   
  
  2,16,16,16,16, 
  4,4,
  4,8,8,8,8,8,8,
  16,8,16,8,16,8,16,8,   
  16,16,16,16,16,2
};

// notes in the melody:
int melody2[] = {
  NOTE_C4, NOTE_G3, NOTE_G3, NOTE_A3, NOTE_G3, 0, NOTE_B3, NOTE_C4
};

// note durations: 4 = quarter note, 8 = eighth note, etc.:
int noteDurations2[] = {
  4, 8, 8, 4, 4, 4, 4, 4
};

Servo myservo;  // create servo object to control a servo
// constants won't change. They're used here to set pin numbers:
const int yelButtonPin = 2;  // the number of the yellow pushbutton pin
const int bluButtonPin = 4;    // the number of the blue pushbutton pin
const int redButtonPin = 7;    // the number of the red pushbutton pin
const int LIGHT_SENSOR_PIN = A0;

// variables will change:
int yelButtonState = 0;  // variable for reading the pushbutton status
int bluButtonState = 0; 
int redButtonState = 0;
int lastredButtonState; // the previous state of the light button
int currentredButtonState; // the current state of the light button

int potpin = A0;  // analog pin used to connect the potentiometer
int val;    // variable to read the value from the analog pin
int val2;  // variable to map the val value to the piano
int pos = 90;    // variable to store the servo position

// Declarations for playing the melodies, without using delay
unsigned long currentMillis = 0;
unsigned long previousMillis = 0;  // will store last time LED was updated
int noteDuration = 0; // Duration of each note to be played, taken from the array
int pauseBetweenNotes = 0; // duration between notes - arbitrary
int noteIndex = 0; // Keeping track of the note to play since we dont use for loop
// The lengths of each Melody
int melodyLength = sizeof(melody) / sizeof(int);
int melodyLength2 = sizeof(melody2) / sizeof(int);

void setup() {
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object

  // initialize the pushbutton pin as an input:
  pinMode(yelButtonPin, INPUT);
  // initialize the pushbutton pin as an input:
  pinMode(bluButtonPin, INPUT);
  // initialize the pushbutton pin as an input:
  pinMode(redButtonPin, INPUT);
  
  currentredButtonState = digitalRead(redButtonPin);

  // initialize the tone library
  pinMode(8, OUTPUT);

  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
}

void loop() {
  lastredButtonState  = currentredButtonState; // Store Previous State of the light button
  currentredButtonState = digitalRead(redButtonPin); // Get new state of the light button

  // read the state of the yellow pushbutton value:
  yelButtonState = digitalRead(yelButtonPin);
  // read the state of the blue pushbutton value:
  bluButtonState = digitalRead(bluButtonPin);

  val = analogRead(potpin);            // reads the value of the potentiometer (value between 0 and 1023)
  val2 = map(val, 0, 1023, 50, 5000);     // scale it for use with the servo (value between 0 and 180)

  // To change the MODES of the Instrument
  if(lastredButtonState == HIGH && currentredButtonState == LOW) {
    Serial.print("RED Button is pressed: ");

    Serial.println(redButtonState);
  
    // Change the state of LED
    if(redButtonState == 0) {
      redButtonState = 1;  
      Serial.println("Opening the Infinite Playing Mode");
    }
    else if (redButtonState == 1){
      redButtonState = 2;
      Serial.println("Changing to the Creative Mode");
    }
    else if (redButtonState == 2){
      redButtonState = 3;
      Serial.println("Changing to the Piano Mode");
    }
    else{
      redButtonState = 0;
      Serial.println("Switching the Instrument off");
    } 
  }

  if (redButtonState == 1){
    // Beginning of an Infinite Playing Mode
    val = map(val, 0, 1023, 100, 1000);     // scale it for use with the servo (value between 0 and 180)

    currentMillis = millis();
    if (currentMillis - previousMillis >= noteDuration + pauseBetweenNotes) {
      previousMillis = currentMillis;
      // stop the previous note
      noTone(8);

      if (val>450){
        // play the next note
        noteDuration = 1000 / noteDurations[noteIndex];
        tone(8, melody[noteIndex], noteDuration);
        pauseBetweenNotes = noteDuration * 0.30;
        // move to the next note
        noteIndex = (noteIndex + 1) % melodyLength;
      }
      else{
        // play the next note
        noteDuration = 1000 / noteDurations2[noteIndex];
        tone(8, melody2[noteIndex], noteDuration);
        pauseBetweenNotes = noteDuration * 0.30;
        // move to the next note
        noteIndex = (noteIndex + 1) % melodyLength2;
      }

    }
    // add a small delay to avoid overloading the processor
    delay(1);
    // End of the Infinite Playing Mode
  }
  else if (redButtonState == 2){
    // Serial.println("Creative Mode");
  // BEGINNING OF CREATIVE MODE

    // check if the pushbutton is pressed. If it is, the buttonState is HIGH:
    if (yelButtonState == HIGH) {
      // Moves the motor in the one direction
      Serial.println("YELLOW PRESSED");
      myservo.write(180); 
    } 
    else if (bluButtonState == HIGH)
    {
      // Moves the motor to the other direction
      Serial.println("NOT YELLOW");
      myservo.write(0); 
    }
    else 
    {
      // otherwise brings the motor to the center
      myservo.write(90);
    }
    // Maps the value read from the Analog Sensor
    val = map(val, 0, 1023, 100, 1000);     // scale it for use (value between 100 and 1000)
    // Takes multiples of 50s only, this is used since we needed distinguishable notes, not a linear shift in the notes.
    val = 50 * ((val + 49) / 50);
    // Allows us to switch the Potentiometer notes to be 'off'
    if(val>250){
      tone(8, val, 200);
    }

  // END OF CREATIVE MODE
  }
  else if (redButtonState == 3){
    // Serial.println("Add Piano Mode");
  // BEGINNING OF PIANO MODE
    // The yellow button tone played in the PIANO Mode
    if (yelButtonState == HIGH) {
      tone(8, 4000-val2, 5); // the 4000-val2 was done by trial and error to reach a value that varies
    } 
    // The blue button tone played in the PIANO Mode
    else if (bluButtonState == HIGH)
    {
      tone(8, 1000+val2, 5); // the 1000+val2 was done by trial and error to reach a value that varies
    }


  // END OF PIANO MODE
  }
  else if (redButtonState == 0){
    Serial.println("Switched Off");
  }
}

 

Assignment 7: Music Composer

Concept

As part of the 7th Assignment for Introduction to Interactive Media, we were tasked with producing a Musical Instrument with the usage of at least one digital sensor, and at least one analog sensor.

Given the requirements, we brainstormed the most sensible application of an analog sensor and concluded that utilizing a potentiometer as a versatile music mixer would be ideal. To add to its functionality, we also explored incorporating various DJ-inspired modes, which proved to be an exciting prospect.

As a result, we decided to pursue this idea further, making it to be somewhat of a mini make-do music composer – where you could produce sounds as well as play music!

Implementation

We decided to start off with a button (red colored) that was solely for the purposes of changing, or flipping through the different modes of the composer. Then, there would be a Piezo Buzzer that produced sound, but controlled by 2 additional Buttons and a Potentiometer, alongside a Servo Motor which would act as a Drum Stick.

Since Arduino does not have any specific mode for switching ‘off’, we decided to have the first mode as an ‘inactive’ state. Then, when the button is pressed, it becomes a music player which plays Melodies that can be essentially changed by the potentiometer. For this, the values of the Potentiometer are mapped to a range of 100-1000, and then there are ‘if’ conditions to check if it is between certain ranges, and so corresponding music would play.

Moving forward, our next mode, the Creative Mode, is very intriguing. It activates the Servo Motor to function as a Drum Stick, and in our case, instead of drums, we utilized a steel mug and a ceramic mug to produce sounds of different quality and pitch. The other two buttons in our circuit would be controlling the direction of the stick, whether it would hit the ceramic, or the steel mug. On top of this, in this mode, the Potentiometer would have its Analog Values mapped to multiples of 50 in the range from 100-1000, and would subsequently have the capacity to produce additional sounds, adding some composure.

The last mode, is the Piano Mode, where the Two Buttons would simply act as Keyboard Keys, and would be limited to produce two types of sounds. However, the Potentiometer would essentially fluctuate these values using a formula. With this, we could fluctuate the Potentiometer like a Mixer and use the two buttons as keys to produce interesting continuous sounds.

With this, we have demonstrated how only the usage of 2 buttons, a Piezo Buzzer and a Potentiometer can be used in different permutations and produce varying types of sounds. The flexibility offered by the Arduino with a breadboard offers limitless opportunities.

Demo Video

A demo video, in detail, can be seen here:

Pictures of Circuit

Difficulties

The first difficulty that we faced was to replace the traditional usage of ‘delays’ to be replaced with a consistently running timer. This was particularly in the first mode, the music player mode, wherein we would have to switch to another mode by pressing the red button, however having pressed that during a delay would have caused issue. We catered to this using one of the Arduino’s standard examples of ‘BlinkWithoutDelay’ and utilized the millis() function to keep a track of time on our own.

Moreover, the project was becoming a complex state machine, and difficult to manage. We wanted to add more buttons for the Piano, however there was a choice between going for a complex looking and difficult to manage circuit, or actually utilizing minimal equipment in creative ways.

Being new to Arduino, we initially thought of keeping loose wires, instead of buttons, which would trigger the piano notes. However, after spending hours of trying out ways with which we would have loose pins connected to the arduino where a connection would play a not, we improvised the usage of the same buttons to play the notes.

Improvements

With such a project, the perception becomes very subjective with multiple ways of improvement. However, something that we definitely see is making the project more easy to use and adding more options in each stage. More melodies in the first mode, more options to create in the second mode, and more piano buttons in the third mode.

Code

Specific Segments

Starting off with the General State Machine, we have used the click of a button, tracked by a previous state and a current state which calculates if there is a change in the state of button (when its pressed again, not held). Once a change occurs, the value of the button state is set such that an appropriate mode is switched on:

// To change the MODES of the Instrument
if(lastredButtonState == HIGH && currentredButtonState == LOW) {
  Serial.print("RED Button is pressed: ");

  Serial.println(redButtonState);

  // Change the state of LED
  if(redButtonState == 0) {
    redButtonState = 1;  
    Serial.println("Opening the Infinite Playing Mode");
  }
  else if (redButtonState == 1){
    redButtonState = 2;
    Serial.println("Changing to the Creative Mode");
  }
  else if (redButtonState == 2){
    redButtonState = 3;
    Serial.println("Changing to the Piano Mode");
  }
  else{
    redButtonState = 0;
    Serial.println("Switching the Instrument off");
  } 
}

When a button state is set, there is another condition in the loop() function which repeatedly checks if that mode is switched on. In the case that the state is 1, we have to play music of two different melodies depending on the potentiometer’s value. However, the important thing is to ensure we dont use delays since we could be changing the mode while the music is playing, and do not want to have to wait.

Therefore, the following piece of code makes use of the millis() function and keeps track of an internal timer.

if (redButtonState == 1){
  // Beginning of an Infinite Playing Mode
  val = map(val, 0, 1023, 100, 1000);     // scale it for use with the servo (value between 0 and 180)

  currentMillis = millis();
  if (currentMillis - previousMillis >= noteDuration + pauseBetweenNotes) {
    previousMillis = currentMillis;
    // stop the previous note
    noTone(8);

    if (val>450){
      // play the next note
      noteDuration = 1000 / noteDurations[noteIndex];
      tone(8, melody[noteIndex], noteDuration);
      pauseBetweenNotes = noteDuration * 0.30;
      // move to the next note
      noteIndex = (noteIndex + 1) % melodyLength;
    }
    else{
      // play the next note
      noteDuration = 1000 / noteDurations2[noteIndex];
      tone(8, melody2[noteIndex], noteDuration);
      pauseBetweenNotes = noteDuration * 0.30;
      // move to the next note
      noteIndex = (noteIndex + 1) % melodyLength2;
    }

  }
  // add a small delay to avoid overloading the processor
  delay(1);
  // End of the Infinite Playing Mode
}

For our creative mode, we simply move the motor in the specified directions with the following code, alongside playing a continuous tone that just varies with the value of the potentiometer.

else if (redButtonState == 2){
  // Serial.println("Creative Mode");
// BEGINNING OF CREATIVE MODE

  // check if the pushbutton is pressed. If it is, the buttonState is HIGH:
  if (yelButtonState == HIGH) {
    // print out the value you read:
    Serial.println("YELLOW PRESSED");
    myservo.write(180); 
  } 
  else if (bluButtonState == HIGH)
  {
    // print out the value you read:
    Serial.println("NOT YELLOW");
    myservo.write(0); 
  }
  else 
  {
    myservo.write(90);
  }

  val = map(val, 0, 1023, 100, 1000);     // scale it for use with the servo (value between 0 and 180)
  val = 50 * ((val + 49) / 50);
  if(val>250){
    tone(8, val, 200);
  }

// END OF CREATIVE MODE
}
Overall Code

While the specific segments are highlighted above, the entire code may give more insights of the project:

/*
  Musical Instrument
  Created 10 April, 2023
  by Ishmal Khalid and Zunair Viqar
*/

#include <Servo.h>
#include "pitches.h"

int melody[] = {
  // Pink Panther theme
  // Score available at https://musescore.com/benedictsong/the-pink-panther
  // Theme by Masato Nakamura, arranged by Teddy Mason
  REST, REST, REST, NOTE_DS4, 
  NOTE_E4, REST, NOTE_FS4, NOTE_G4, REST, NOTE_DS4,
  NOTE_E4, NOTE_FS4,  NOTE_G4, NOTE_C5, NOTE_B4, NOTE_E4, NOTE_G4, NOTE_B4,
  NOTE_AS4, NOTE_A4, NOTE_G4, NOTE_E4, NOTE_D4, 
  NOTE_E4, REST, REST, NOTE_DS4,

  NOTE_E4, REST, NOTE_FS4, NOTE_G4, REST, NOTE_DS4,
  NOTE_E4, NOTE_FS4, NOTE_G4, NOTE_C5, NOTE_B4, NOTE_G4, NOTE_B4, NOTE_E5,
  NOTE_DS5,   
  NOTE_D5, REST, REST, NOTE_DS4,
  NOTE_E4, REST, NOTE_FS4, NOTE_G4, REST, NOTE_DS4,
  NOTE_E4, NOTE_FS4, NOTE_G4, NOTE_C5, NOTE_B4, NOTE_E4, NOTE_G4, NOTE_B4,
  
  NOTE_AS4, NOTE_A4, NOTE_G4, NOTE_E4, NOTE_D4,
  NOTE_E4, REST,
  REST, NOTE_E5, NOTE_D5, NOTE_B4, NOTE_A4, NOTE_G4, NOTE_E4,
  NOTE_AS4, NOTE_A4, NOTE_AS4, NOTE_A4, NOTE_AS4,NOTE_A4,NOTE_AS4,NOTE_A4,
  NOTE_G4, NOTE_E4, NOTE_D4, NOTE_E4, NOTE_E4, NOTE_E4
};

int noteDurations[] = {
  // Pink Panther theme
  // Score available at https://musescore.com/benedictsong/the-pink-panther
  // Theme by Masato Nakamura, arranged by Teddy Mason
  2,4,8,8, 
  4 ,8,8,4,8,8,
  8 ,8, 8,8,8,8,8,8,   
  2 ,16,16,16,16,
  2 ,4,8,4,

  4,8,8,4,8,8,
  8,8,8,8,8,8,8,8,
  1,   
  2,4,8,8, 
  4,8,8,4,8,8,
  8,8, 8,8,8,8,8,8,   
  
  2,16,16,16,16, 
  4,4,
  4,8,8,8,8,8,8,
  16,8,16,8,16,8,16,8,   
  16,16,16,16,16,2
};

// notes in the melody:
int melody2[] = {
  NOTE_C4, NOTE_G3, NOTE_G3, NOTE_A3, NOTE_G3, 0, NOTE_B3, NOTE_C4
};

// note durations: 4 = quarter note, 8 = eighth note, etc.:
int noteDurations2[] = {
  4, 8, 8, 4, 4, 4, 4, 4
};

Servo myservo;  // create servo object to control a servo
// constants won't change. They're used here to set pin numbers:
const int yelButtonPin = 2;  // the number of the yellow pushbutton pin
const int bluButtonPin = 4;    // the number of the blue pushbutton pin
const int redButtonPin = 7;    // the number of the red pushbutton pin
const int LIGHT_SENSOR_PIN = A0;

// variables will change:
int yelButtonState = 0;  // variable for reading the pushbutton status
int bluButtonState = 0; 
int redButtonState = 0;
int lastredButtonState; // the previous state of the light button
int currentredButtonState; // the current state of the light button

int potpin = A0;  // analog pin used to connect the potentiometer
int val;    // variable to read the value from the analog pin
int val2;  // variable to map the val value to the piano
int pos = 90;    // variable to store the servo position

// Declarations for playing the melodies, without using delay
unsigned long currentMillis = 0;
unsigned long previousMillis = 0;  // will store last time LED was updated
int noteDuration = 0; // Duration of each note to be played, taken from the array
int pauseBetweenNotes = 0; // duration between notes - arbitrary
int noteIndex = 0; // Keeping track of the note to play since we dont use for loop
// The lengths of each Melody
int melodyLength = sizeof(melody) / sizeof(int);
int melodyLength2 = sizeof(melody2) / sizeof(int);

void setup() {
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object

  // initialize the pushbutton pin as an input:
  pinMode(yelButtonPin, INPUT);
  // initialize the pushbutton pin as an input:
  pinMode(bluButtonPin, INPUT);
  // initialize the pushbutton pin as an input:
  pinMode(redButtonPin, INPUT);
  
  currentredButtonState = digitalRead(redButtonPin);

  // initialize the tone library
  pinMode(8, OUTPUT);

  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
}

void loop() {
  lastredButtonState  = currentredButtonState; // Store Previous State of the light button
  currentredButtonState = digitalRead(redButtonPin); // Get new state of the light button

  // read the state of the yellow pushbutton value:
  yelButtonState = digitalRead(yelButtonPin);
  // read the state of the blue pushbutton value:
  bluButtonState = digitalRead(bluButtonPin);

  val = analogRead(potpin);            // reads the value of the potentiometer (value between 0 and 1023)
  val2 = map(val, 0, 1023, 50, 5000);     // scale it for use with the servo (value between 0 and 180)

  // To change the MODES of the Instrument
  if(lastredButtonState == HIGH && currentredButtonState == LOW) {
    Serial.print("RED Button is pressed: ");

    Serial.println(redButtonState);
  
    // Change the state of LED
    if(redButtonState == 0) {
      redButtonState = 1;  
      Serial.println("Opening the Infinite Playing Mode");
    }
    else if (redButtonState == 1){
      redButtonState = 2;
      Serial.println("Changing to the Creative Mode");
    }
    else if (redButtonState == 2){
      redButtonState = 3;
      Serial.println("Changing to the Piano Mode");
    }
    else{
      redButtonState = 0;
      Serial.println("Switching the Instrument off");
    } 
  }

  if (redButtonState == 1){
    // Beginning of an Infinite Playing Mode
    val = map(val, 0, 1023, 100, 1000);     // scale it for use with the servo (value between 0 and 180)

    currentMillis = millis();
    if (currentMillis - previousMillis >= noteDuration + pauseBetweenNotes) {
      previousMillis = currentMillis;
      // stop the previous note
      noTone(8);

      if (val>450){
        // play the next note
        noteDuration = 1000 / noteDurations[noteIndex];
        tone(8, melody[noteIndex], noteDuration);
        pauseBetweenNotes = noteDuration * 0.30;
        // move to the next note
        noteIndex = (noteIndex + 1) % melodyLength;
      }
      else{
        // play the next note
        noteDuration = 1000 / noteDurations2[noteIndex];
        tone(8, melody2[noteIndex], noteDuration);
        pauseBetweenNotes = noteDuration * 0.30;
        // move to the next note
        noteIndex = (noteIndex + 1) % melodyLength2;
      }

    }
    // add a small delay to avoid overloading the processor
    delay(1);
    // End of the Infinite Playing Mode
  }
  else if (redButtonState == 2){
    // Serial.println("Creative Mode");
  // BEGINNING OF CREATIVE MODE

    // check if the pushbutton is pressed. If it is, the buttonState is HIGH:
    if (yelButtonState == HIGH) {
      // Moves the motor in the one direction
      Serial.println("YELLOW PRESSED");
      myservo.write(180); 
    } 
    else if (bluButtonState == HIGH)
    {
      // Moves the motor to the other direction
      Serial.println("NOT YELLOW");
      myservo.write(0); 
    }
    else 
    {
      // otherwise brings the motor to the center
      myservo.write(90);
    }
    // Maps the value read from the Analog Sensor
    val = map(val, 0, 1023, 100, 1000);     // scale it for use (value between 100 and 1000)
    // Takes multiples of 50s only, this is used since we needed distinguishable notes, not a linear shift in the notes.
    val = 50 * ((val + 49) / 50);
    // Allows us to switch the Potentiometer notes to be 'off'
    if(val>250){
      tone(8, val, 200);
    }

  // END OF CREATIVE MODE
  }
  else if (redButtonState == 3){
    // Serial.println("Add Piano Mode");
  // BEGINNING OF PIANO MODE
    // The yellow button tone played in the PIANO Mode
    if (yelButtonState == HIGH) {
      tone(8, 4000-val2, 5); // the 4000-val2 was done by trial and error to reach a value that varies
    } 
    // The blue button tone played in the PIANO Mode
    else if (bluButtonState == HIGH)
    {
      tone(8, 1000+val2, 5); // the 1000+val2 was done by trial and error to reach a value that varies
    }


  // END OF PIANO MODE
  }
  else if (redButtonState == 0){
    Serial.println("Switched Off");
  }
}

 

Week 10 – Musical Instrument

Concept and Implementation

For this assignment, we wanted to make a musical instrument that was controlled by a user’s motion. So, we came up with the idea of changing the output tone based on the input from a flex sensor. For this, we attached a flex sensor to a glove so that when a user wears the glove and bends their hand, the input changes, and depending on how much the user bends their hand, the tone changes. To implement this, we saved a number of notes in an array. The input from the flex sensor is mapped to values between 0 and the size of the array so that for different measurements of the ‘bend’ of the hand, a different number is obtained after mapping and a note is picked from the array at that number. Moreover, we used a switch to play another tone, so that when the switch is turned on, a different tone made up of a set of notes is played. When the switch is turned off, the user can control the output melody using their hand. We played with different durations and frequencies until we found the one we liked.

Schematic

Video

Code

#include "pitches.h"

const int Buzzer1=3;
const int flexPin = A0;
int value; 

//array of notes
int melody[] = {
  NOTE_E5, NOTE_D5, NOTE_C5, NOTE_D5, NOTE_E5, NOTE_E5, NOTE_E5,
  NOTE_D5, NOTE_D5, NOTE_D5, NOTE_E5, NOTE_G5, NOTE_G4, NOTE_E5,
  NOTE_D5, NOTE_C5, NOTE_D5, NOTE_E5, NOTE_E5, NOTE_E5, NOTE_E5,
  NOTE_D5, NOTE_D5, NOTE_E5, NOTE_D5, NOTE_C5
};

void setup()
{
  Serial.begin(9600);
  pinMode(Buzzer1, OUTPUT);
  pinMode(A2, INPUT);
}

void loop()
{
  int button = digitalRead(A2);
  //when button is pressed, play a predefined tone (happy brithday music)
  if (button == HIGH)
  {
    Serial.print("SWITCH ON\n");
    //tone(Buzzer1, 200, 1200);
    // play a melody using tone()
  tone(Buzzer1, NOTE_C4, 250); delay(250);
  tone(Buzzer1, NOTE_C4, 250); delay(250);
  tone(Buzzer1, NOTE_D4, 500); delay(500);
  tone(Buzzer1, NOTE_C4, 500); delay(500);
  tone(Buzzer1, NOTE_F4, 500); delay(500);
  tone(Buzzer1, NOTE_E4, 1000); delay(1000);
 
  tone(Buzzer1, NOTE_C4, 250); delay(250);
  tone(Buzzer1, NOTE_C4, 250); delay(250);
  tone(Buzzer1, NOTE_D4, 500); delay(500);
  tone(Buzzer1, NOTE_C4, 500); delay(500);
  tone(Buzzer1, NOTE_G4, 500); delay(500);
  tone(Buzzer1, NOTE_F4, 1000); delay(1000);
  }
  //if button is not pressed, read value from flex sensor
  //map the value to a number that is within 0 and the max index of array melody
  //use this mapped value as an index and play the note from that particular index 
  else if (button == LOW)
  {
    Serial.print("OFF\n");
  
  value= analogRead(flexPin);
  // Serial.print("\nvalue is: ");
  // Serial.print(value);
  int size = sizeof(melody)/sizeof(melody[0]);
  value = map(value, 850, 1050, 0, size);
  
  tone(Buzzer1,melody[value],1200);
  //Serial.print("\n Note is: " );
  //Serial.print(melody[value]);
  delay(300);
  }
}

Future Improvements

For later, we can improve by first attaching the flex sensor inside the glove more securely so that the instrument produces more consistent sounds. Also, we can add an additional buzzer with the switch to play a sound continuously in the back while the user uses the flex sensor to add more sounds on top of it.

Groupmate: Mohid Raza

HW 7: Musical Instrument – Irem Naz Celen & Swostik Pati

If you have ever wondered how it would be to a starting DJ, this design is for you!

Link to Video

Inspiration

The inspiration for this project comes from a DJ controller. We wanted to design a physical interface that would allow a range of motions by the DJ. Our focus was on an easy and intuitive design that would mimic a basic DJ controller. The 2 requirements that had to be fulfilled were a beat-making mechanism as well as a musical mechanism in which the frequency can be controlled.

Concept

In order to make our inspiration become a reality, we have decided to produce the musical notes in different frequencies of 7 tones through the buzzer while making a beat maker using the servo. A push button connected to the servo slams the handle on the wooden surface imitating the beat sound. On the other side, another button is used to switch between 7 different notes that are played in the buzzer. Potentiometer that feeds back to the buzzer allows the frequency of the tone that the buzzer is playing to go higher when it is twisted right, and lower when twisted left.

Implementation

In the implementation of the project an Arduino Uno, a servo, 2 push buttons, a buzzer, and a potentiometer are used. Servo’s rotating wing is taped to plastic handled screwdriver while the servo itself is fixed on a wooden plate.

The first push-button retains information on the occasions where it is pressed. A push that is recorded prompts the screwdriver that is connected to the rotating wing of the servo to switch from a levitating position to slam on the wooden fixation plate. The sound produced is similar to a beat sound that can be achieved from an electronic device. On the other side of the board, the push button and potentiometer both record information that changes the state of the buzzer. The buzzer is constantly creating sound. The range of sound is modeled from a piano’s octaves, and therefore there are 7 keys in 7 different octaves that can be produced from this buzzer according to the code. The frequencies of these notes are numerically written into the notes double array.  The push button for the buzzer (stationed towards the right side of the breadboard) switches between the 7 notes in the order of B, C,D,E,F,G, and A. Potentiometer on the other hand, switches into higher pitch/frequency of the same note, visually can be thought of as higher octave of the same note on the piano, when turned towards the right. There are again 7 octaves possible, in which the most left position of the potentiometer is the lowest frequency the note exists in while the most right position is the highest frequency of the note.

This is the code for the said implementation.

//Include Servo Library
#include <Servo.h>

//servo
int servoPin = 9;
int pos1 = 40;
int pos2 = 110;
int dt = 100;
Servo myServo;


//pushButton for servo
int pbPin = 13;
bool pbFlag = true;

//pushButton for note change
int notePin = 2;
bool nbFlag = true;
int currNoteI = 0;
int mappedValue;

//potentiometer
int potPin = A0;

//notes array
int tones[7][7] = {{31, 62, 123, 494, 988, 1976, 3951}, {33, 65, 131, 262, 523, 1047, 2093}, {37, 73, 147, 294, 587, 1175, 2349}, {41, 82, 165, 330, 659, 1319, 2637},
  {44, 87, 175, 349, 698, 1397, 2794}, {49, 98, 196, 392, 784, 1568, 3136}, {55, 110, 220, 440, 880, 1760, 3520}
};

//buzzer
int tonePin = 4;

void moveServo() {
  delay(dt);
  myServo.write(pos1);
  delay(dt);
  myServo.write(pos2);
  delay(dt);
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);

  //  setting up servos
  myServo.attach(servoPin);
  myServo.write(pos2);

  //  setting up pushbutton
  pinMode(pbPin, INPUT);

  //  setting up buzzer
  pinMode(tonePin, OUTPUT);


}

void loop() {
  // put your main code here, to run repeatedly:
  //pushbutton and servo implementation
  int pbVal = digitalRead(pbPin);
  if (pbVal == 1 && pbFlag) {
    //high
    moveServo();
    pbFlag = false;
  }
  else if (pbVal == 0) {
    pbFlag = true;
  }

  //potentiometer implementation
  int potValue = analogRead(potPin);
  mappedValue = map(potValue, 0, 1023, 6, -1);
  //  Serial.println(mappedValue);
  //  Serial.println(potValue);

  //  pushbutton and note change implementation
  int nbVal = digitalRead(notePin);
  if (nbVal == 1 && nbFlag) {
    //high
    if (currNoteI < 6) {
      currNoteI++;
    }
    else {
      currNoteI = 0;
    }
    Serial.print("The current note is: ");
    Serial.println(currNoteI);
    nbFlag = false;
  }
  else if (nbVal == 0) {
    nbFlag = true;
  }

  //buzzer
  tone(tonePin, tones[currNoteI][mappedValue]);

}

Schematic Diagram

Challenges

The main challenge that we have come across was making the location of the push buttons and the potentiometer user-friendly while taking wires into consideration. We had to play around with different versions of the breadboard construction multiple times to make sure the musical instrument was approachable and easy to use.

Moreover, we also considered multiple circuit designs for the buzzer in order to control the volume by adding resistors. Upon multiple trials, we have decided not to add a resistor for maximum volume and clarity.

For servo attachment, we looked around for a considerable time to find the most suitable extension to make the optimum beat sound. Before deciding on attaching the screwdriver to the rotational component of the servo, we considered using plastic and wooden extensions. For gaining the right sound of a beat, we realized we needed more weight for the attached piece, hence the final screwdriver extension was chosen. Putting a wooden plate below enhanced the experience, after our trial and error.

Another consideration was given to the response time of the servo, by adjusting the delay time in the moveServo() function. The final adjusted value of the delay was given according to what sounded natural according to the frequency at which the push button of the servo was pushed.

Reflections

Making this project together as a group was very enjoyable, which made the design process more exciting and fun. A part to improve on in the next projects would be in terms of having more power in choosing which tone to play on the buzzer rather than having to follow the set order that is programmed in the current version of the code. On a more general note, we would love to improve our ability to follow up what is happening in the circuit as it gets more complex, and making the schematic together definitely allowed us to work on that.

Surprise Birthday party- Music Machine

Music Machine:

The ultimate surprise party gadget. I have had this idea after my friend’s surprise birthday party. This gadget detects when the person passes in front of the ultrasonic motion sensor and automatically plays the famous birthday song tune and lights up three LEDs that create the festive vibes. The music machine also played a different tune depending on where the detected person (or teddy bear) is situated. Thus, the gadget will play different tune depending on the where the person is. This allows the music machine to keep playing different melodies throughout the party and set the party mood.

circuit :

the circuit includes ultrasonic motion sensor, buzzer, 3 LEDs, 3 resistors, variable resistor, Arduino uno.

I have included the variable resistor as it allows to adjust the volume of the buzzer. The LEDs are wired in parallel as it allow to for the LEDs to light up alternatively and create a light pattern. The diagram below describes all the wiring in the circuit:

Arduino script:

The biggest challenge I found while setting the script was making the LEDs light up simultaneously as the buzzer is on, but also creating some sort of pattern when the LED light up. I ended up solving that problem by creating a function Playtune() that gets called from inside the void Loop(). This allows both tasks to be done with interfering with each other.

int trig = 10;
int echo = 11;
long duration;
long distance;

// Define the LED pins
int led1 = 6;
int led2 = 7;
int led3 = 8;

// Define the Happy Birthday tune
int tune1[] = {264, 264, 297, 264, 352, 330};
int tune2[] = {264, 264, 297, 264, 396, 352};
int Newtune[] = {392, 330, 330, 349, 392, 392, 392, 440, 392, 349, 330, 294};


int tune1Length = sizeof(tune1) / sizeof(tune1[0]);
int tune2Length = sizeof(tune2) / sizeof(tune2[0]);
int NewtuneLength = sizeof(jaws) / sizeof(Newtune[0]);

void lightUpLed(int led, int duration) {
  digitalWrite(led, HIGH);
  delay(duration);
  digitalWrite(led, LOW);
}

void playTune(int tune[], int tuneLength) {
  for (int i = 0; i < tuneLength; i++) {
    tone(12, tune[i]);
    
    // Light up the LEDs in a rhythmic pattern
    lightUpLed(led1, 150);
    lightUpLed(led2, 150);
    lightUpLed(led3, 150);

    noTone(12);
    delay(50);
  }
}

void setup() {
  pinMode(echo, INPUT);
  pinMode(trig, OUTPUT);
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  digitalWrite(trig, LOW);
  delayMicroseconds(2);
  digitalWrite(trig, HIGH);
  delayMicroseconds(10);
  digitalWrite(trig, LOW);
  duration = pulseIn(echo, HIGH);
  distance = (duration / 2) * .0344;    // 344 m/s = speed of sound. We're converting into cm

  if (distance > 0 && distance <= 35) {
    if (distance <= 15) {
      playTune(tune1, tune1Length);
      playTune(tune2, tune2Length);
    } 
    else {
       playTune(Newtune, NewtuneLength);
    }
  }
}