Week 11 – Serial Communication

Task 1:

make something that uses only one sensor on arduino and makes the ellipse in p5 move on the horizontal axis, in the middle of the screen, and nothing on arduino is controlled by p5

Code:

For the code, I used the Arduino and p5js code that was given to us in the class and edited it to suit my needs of moving the horizontal object with the help of a potentiometer. The code shown below is what I wrote in order to move the ellipse on the horizontal axis. As the task was quite simple, I also made the background change colors and gave the ellipse a “trail” effect by changing the transparency.

function draw() {
  var var1 = map(map(rVal,0, 1023, 0, width/2), 0, width/2, 150, 200);
  var var2 = map(map(rVal,0, 1023, 0, width/2), 0, width/2, 200, 50)
  background(var1, var2, var2, 0.9)

  if (!serialActive) {
    fill("black")
    text("Press Space Bar to select Serial Port", 20, 30);
  } else {

    noStroke()
    ellipse(map(rVal, 0, 1023, 50, width-50), height/2, map(rVal, 0, 1023, 5, 50))
  }
}

Picture of the circuit (The LEDs are used to check the wiring):

Task 2:

make something that controls the LED brightness from p5

Code:

As with the previous task, I used the already given code in order to change the brightness of the LED from p5js. However, I changed the digitalWrite() of the right LED (which was connected to pin 5 and could thus produce analog output) to analogWrite(). To change the brightness, I used a HTML slider in p5js. By extracting the value of the slider and sending the data to the right LED, I was able to change the brightness. Additionally, I changed the background color from black to white depending on the brightness of the LED such that the code is more intuitive.

function setup() {
  createCanvas(640, 480);
  textSize(18);
  
  slider = createSlider(0, 255, 0); // indicate the value range for slider
  slider.position(width/2-150, height/2);
  slider.style('width', '300px');
}

function draw() {
  var brightness_ = map(slider.value(), 0, 255, 0, 255);

  background(brightness_)
  
  if (!serialActive) {
  } else {
    right = brightness_;
  } 
}

The circuit looks the same as the one of the previous task but without the potentiometer.

Task 3:

take the gravity wind example and make it so every time the ball bounces one led lights up and then turns off, and you can control the wind from one analog sensor

Code:

Combined with the code given in class before, I used the gravity example code for the assignment. By allowing for minor changes, I was able to establish communication from both p5js to Arduino (LED lighting up) and vice versa (potentiometer controlling the wind). While most of the code is from the example, I have annotated the parts which I have added below.

/* Week 11.2 bidi serial example
 * Originally by Aaron Sherwood
 * Modified by Mangtronix
 *
 * Add this library to Sketch files
 *  https://github.com/mangtronix/IntroductionToInteractiveMedia/blob/master/code/p5.web-serial.js files
 *
 * You must include this line in your index.html (in Sketch Files) to load the
 * web-serial library
 *
 *     <script src="p5.web-serial.js"></script>
 *
 * Arduino code:
 * https://github.com/mangtronix/IntroductionToInteractiveMedia/blob/master/code/Week11Serial.ino
 */

let left = 0;
let right = 0;
let rVal = 0;

function setup() {
  createCanvas(640, 480);
  textSize(18);
}


let velocity;
let gravity;
let position;
let acceleration;
let wind;
let drag = 0.99;
let mass = 50;

function setup() {
  createCanvas(640, 360);
  noFill();
  position = createVector(width/2, 0);
  velocity = createVector(0,0);
  acceleration = createVector(0,0);
  gravity = createVector(0, 0.5*mass);
  wind = createVector(0,0);
}

function draw() {
  background(255);
  applyForce(wind);
  applyForce(gravity);
  velocity.add(acceleration);
  velocity.mult(drag);
  position.add(velocity);
  acceleration.mult(0);
  // CONSTRAIN ELLIPSE SUCH THAT IT DOES NOT MOVE OFF SCREEN
  ellipse(constrain(position.x,mass/2, width-mass/2),position.y,mass,mass);
  if (position.y > height-mass/2) {
      // LIGHT UP LED ON COLLISION
      right = 1;

      velocity.y *= -0.9;  // A little dampening when hitting the bottom
      position.y = height-mass/2;
    }
  else{
    // LED SWITCHES OFF WHEN THERE IS NO COLLISON
    right = 0;
  }
  
  // CONTROL WIND WITH POTENTIOMETER READING
  if(!serialActive){
  }
  else{
    wind.x = map(rVal, 0, 1023, -1, 1)
  }
}

function applyForce(force){
  // Newton's 2nd law: F = M * A
  // or A = F / M
  let f = p5.Vector.div(force, mass);
  acceleration.add(f);
}

function keyPressed(){
  if (keyCode==UP_ARROW){
    mass=random(15,80);
    position.y=-mass;
    velocity.mult(0);
  }

  // REMOVED RIGHT AND LEFT KEY FOR WIND

  //  CONNECTING TO PORT
  if (key == " ") {
    setUpSerial();
  }
}

// CODE FROM CLASS
function readSerial(data) {
  ////////////////////////////////////
  //READ FROM ARDUINO HERE
  ////////////////////////////////////

  if (data != null) {
    // make sure there is actually a message
    // split the message
    let fromArduino = split(trim(data), ",");
    // if the right length, then proceed
    if (fromArduino.length == 1) {
      // only store values here
      // do everything with those values in the main draw loop
      
      // We take the string we get from Arduino and explicitly
      // convert it to a number by using int()
      // e.g. "103" becomes 103
      rVal = int(fromArduino[0]);
      // alpha = int(fromArduino[1]);
    }

    //////////////////////////////////
    //SEND TO ARDUINO HERE (handshake)
    //////////////////////////////////
    let sendToArduino = left + "," + right + "\n";
    writeSerial(sendToArduino);
  }
}

Video:

Reflection:

This assignment, although not as creative as the rest, was quite interesting. Setting up serial communication between p5js and the Arduino is something I found quite hard to understand in class, but since the assignment involved three Tasks, it became quite easy to navigate both the code and hardware side of things. One of the challenges I faced was failing to remember that Arudino does not work on Safari and that I need to re-compile code in order for it to run. It took me quite some time to remember that I needed to switch browsers for my code to run. However, I take both of these as valuable lessons and hope that I will not forget such details in the future, just to save myself from stressing as much as I did when beginning this project. All in all, I wish to do more creative stuff with the two components, which I hope can be seen in my final project.

Final Project Idea Proposal

Group: Vladimir, Dariga

Idea

A rhythm game where you are given instructions on which notes to play from a song. You must use our physical controller to play these sounds. You must keep up the tempo and always play the correct notes. We plan to prepare one to three songs for the player, which they will be able to select. Also, we can add a ‘freestyle’ mode where the song is generated at every moment.

Arduino: We have a square wooden box with the top open. We also have a ball or other smooth object which we place inside the box. We intend to use 2-4 ultrasonic sensors to track the position of the ball inside the box. For example in case of 2 sensors, one should track X position and the other should track Y position.

p5js: The canvas will be divided to include multiple colored regions that will correspond to a particular sound. Placement of the physical ball within the particular region will trigger a sound to play. One way to define the regions is by a 3×3 grid:

1 2 3
4 5 6
7 8 9

Here the cell 5 could not play a sound but the other ones would.

We haven’t decided yet on the particular sounds to play, with the preliminary idea for sounds to represent pre-defined notes.

On the screen, we also show the instructions (sequence of notes) that the player has to play. We can also color code the notes to make it easier to remember.

When the player misses enough notes they lose. Without missed notes, the player completes their music experience and may restart the game.

 

 

 

In-class Arduino + p5 exercises

Team: Dariga, Vladimir

First exercise

“Make something that uses only one sensor on arduino and makes the ellipse in p5 move on the horizontal axis, in the middle of the screen, and nothing on arduino is controlled by p5”

Arduino code, p5 code

Second exercise

“Make something that controls the LED brightness from p5”

Arduino code, p5 code

Third exercise

“take the gravity wind example and make it so every time the ball bounces one led lights up and then turns off, and you can control the wind from one analog sensor”

Arduino code, p5 code

 

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);
}

 

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");
  }
}

 

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.

Musical Instrument

Concept

I worked on this project with Akhat, and we wanted to create a tool similar to Singing Horses where each horse has its tone and frequency, can be turned on/off, and acts as an element of melody that creates a unique tune when played together with other horses. In our project, a similar idea can be seen: we have multiple buzzers each with its tune that is played when pressed on a corresponding button. One special thing about this project is that we also use a pressure sensor to change the tone just a little and create some more variation and uniqueness in each play.

Process/Challenges

We started off by testing out different parts separately – first, we got the pressure sensor working (which did not work in the beginning because of hardware, but then we switched to a different pressure sensor which worked much better). After that, when connecting buzzers and buttons, we ran into an issue where multiple buzzers were not playing at the same time. Initially, our idea was to play them simultaneously with different tunes, but apparently, Arduino does not allow that (i.e buzzers must be played one at a time). Our workaround for this problem was that instead of playing tunes simultaneously, we had them play one at a time when the switch is pressed down. Lastly, it was a lot of experimentation of what notes worked best for us given that we were changing the frequency based on the pressure sensor.

Circuit PictureThe circuit

Circuit Diagram

Week 10 – Musical Instrument

by Ajla and Hana

Concept

This week’s assignment was to create a simple musical instrument using the Arduino. Hana and Ajla decided to create a simplified piano and drum. In order to do so, we utilized switches and a servo motor. We controlled the speed of the servo motor using a potentiometer. The notes are played by pressing the buttons. The buttons stop producing noise when released.

Servo circuit

 

Implementation

To implement our musical instrument, we used a potentiometer, switches, a piezoelectric buzzer, resistors, wires and an Arduino. By connecting the switches in parallel we were able to preserve voltage across all components. Even though it was possible to connect everything on one breadboard, we decided to separate it in order to make the instrument user friendly. Furthermore, since many digital inputs were used, the separation ensured that there would not be any overcrowding while presenting the final product.The sketches below show both the two Arduino setup we used and one Arduino setup.

The code was written for both Arduino. Hana wrote the code for the switches and Ajla wrote the code for the drum. The drum was made using a metal screw, silk ribbon and tape which was attached to the servo hand. By pressing the four switches, notes, stored in an array, were played. The drum hit a piece of cardboard in order to produce noise.

Two Arduino
One Arduino

Here is the code for playing the notes:

// if button1 is pressed, plays first note
  if(button1State==1) {
    tone(9, notes[0]);
  }

// if button2 is pressed, plays second note

  if(button2State==1) {
    tone(9, notes[1]);
  }

// if button3 is pressed, plays third note

  if(button3State==1) {
    tone(9, notes[2]);
  }

// if button4 is pressed, plays fourth note

  if(button4State==1) {
    tone(9, notes[3]);
  }

// if buttons are release, no note is played

  if(button1State==0 && button2State==0  && button3State==0 && button4State==0) {
    noTone(9);
  }
  
  
  delay(1);  // delay in between reads for stability

Here is the code that ran the servo in a 90 degree range:

void loop() {
  int p_value  = analogRead(p_meter);

  int value = map(p_value, 0, 1024, 10, 20);
  for (int i=45; i<90; i += value) {
    pos1 = 0 + (i*2);          // servo1 from 0 to 90 degrees
    myservo1.write(pos1);      // move the servo
    delay(50);  
  }
 
  for (int i=45; i<90; i += value) {
    pos1 = 90 - i*2;           // servo1 from 90 to 0 degrees
    myservo1.write(pos1);      // move the servo
    delay(50);
  }
}

Challenges

The assignment came with a few challenges. Firstly, since the piezoelectric buzzer cannot take multiple inputs at once, it was important to play each note once, without pressing others since that would destroy the quality of the sound. Secondly, the notes play continuously if the button is pressed, even once. That is why we added the last if statement that checks whether all buttons are not pressed, in which case it plays no sound. Thirdly, the servo is quite tricky to use at high speeds. It gets more imprecise as the speed goes up. So, controlling it with the potentiometer was quite hard to do precisely. Lastly, since the angle of motion changes as the speed increases, it was hard to mount the servo on anything as it would immediately fall down once the speed was changed. This became quite frustrating that we decided to just hold the servo in the end to showcase the tempo of the “drum”. All in all, this assignment came with quite a few challenges. Some of them we tried to attempt and won, such as the notes, but some of them remain to be defeated due to the lack of time and materials we had at the time of making this project.

Reflection

Our team went back and forth on ideas on what to do as an instrument because neither of us are musically inclined. However, we landed on this idea after a few iterations. We struggled quite a bit to get everything right, as was mentioned in the challenges above, but we overcame them with solutions such as only playing one note at a time, and having to hold the servo since it would not stay mounted. Overall, it was a great learning experience, but I realized that for the final project I will most probably not delve into anything sound or music related since my creativity is a lot more limited.