Assignment: Synthesis: Music Instrument (group work)
Collaborators:
Collaborators: Ljuba, David, Nathan
Jam Juggz is a musical instrument that allows users to record a rhythm that is actuated by three different servo motors on different objects. plays that rhythm back in a loop. Users turn a color-coded dial, cover the photosensor, record their own rhythm, and Jam Juggz will play that pattern on the corresponding servo along with previously recorded patterns.
Jam Juggz is customizable: users can tap short rhythms or long rhythms, and edit one pattern at a time. This allows for a creative and dynamic music-making experience.
Video:
Materials:
Code:
/* int servo1 = 10; // Control pin for servo motor int servo2 = 11; int servo3 = 12; int currentServo; int lastServo; int temp = true; int pulseWidth = 0; // Amount to pulse the servo long lastPulse = 0; // the time in millisecs of the last pulse int refreshTime = 20; // the time in millisecs needed in between pulses int minPulse = 500; // minimum pulse width int potPin = 1; int potVal; boolean on = false; // whether the beat signal is activated or not boolean start = true; int val = 0; // variable to store the value coming from the fsr int LED = 4; boolean hasPlayed = true; boolean recording = false; //are we in recording mode? unsigned long currentTime; long rests1[10] = {0,0,0,0,0,0,0,0,0,0}; long rests2[10] = {0,0,0,0,0,0,0,0,0,0}; long rests3[10] = {0,0,0,0,0,0,0,0,0,0}; void setup(){ Serial.begin(9600); pinMode(0, INPUT); //fsr pin pinMode(2, INPUT); //photocell pin pinMode(4, OUTPUT); pinMode(5, OUTPUT); pinMode(6, OUTPUT); pinMode(servo1, OUTPUT); // Set servo pin as an output pin pinMode(servo2, OUTPUT); // Set servo pin as an output pin pinMode(servo3, OUTPUT); // Set servo pin as an output pin pulseWidth = minPulse; // Set the motor position to the minimum } void loop(){ potVal = analogRead(potPin); if(potVal < 350){ LED = 4; currentServo = 1; } else if(potVal < 700 && potVal > 351){ LED = 5; currentServo = 2; } else{ LED = 6; currentServo = 3; } if(temp){ lastServo = currentServo; temp = false; } //Serial.println(analogRead(potPin)); //if the the photocell is covered, recording is on! if(analogRead(2) < 500){ recording = true; } else{ recording = false; } //recording mode if(recording){ digitalWrite(LED, HIGH); val = analogRead(0); //Serial.println(val); if(potVal < 350 && rests1[0] != 0 && hasPlayed){ resetRests(1); start = true; } else if(potVal < 700 && potVal > 351 && rests2[0] != 0 && hasPlayed){ resetRests(2); start = true; } else if(potVal > 701 && rests3[0] != 0 && hasPlayed) { resetRests(3); start = true; } //this starts the timer over when you switch servos if(lastServo != currentServo){ start = true; lastServo = currentServo; } hasPlayed = false; //if the beat has not already been detected, check to see if the value is greater than 100 if(on == false){ // if it is, check to see if it's the first beat if(val > 100) { // if so, start the timer now! if(start){ currentTime = millis(); start = false; } on = true; //register the beat add(millis() - currentTime, currentServo); //measure the length of the rest and adds it to the correct array currentTime = millis(); //reset the currentTime for the next rest //Serial.println(val); printRests(currentServo); } } else{ if(val == 0){ on = false; } } } //end if(recording) //playback mode else{ //Serial.println("playback"); hasPlayed = true; digitalWrite(LED, LOW); for(int i = 0; i < 10; i = i + 1){ if(rests1[i] != 0){ beatServo(servo1); delay(rests1[i]); Serial.println("1. beat"); } } for(int i = 0; i < 10; i = i + 1){ if(rests2[i] != 0){ beatServo(servo2); delay(rests2[i]); Serial.println("2. beat"); } } for(int i = 0; i < 10; i = i + 1){ if(rests3[i] != 0){ beatServo(servo3); delay(rests3[i]); Serial.println("3. beat"); } } } //end playback mode } //end loop() void add(unsigned long rest, int servoNum){ //go through the rests arrays and add the latest rest to the end for(int i = 0; i < 10; i = i + 1){ if(servoNum == 1){ if(rests1[i] == 0){ rests1[i] = rest; break; } } else if(servoNum == 2){ if(rests2[i] == 0){ rests2[i] = rest; break; } } else{ if(rests3[i] == 0){ rests3[i] = rest; break; } } } } void resetRests(int servoNum){ if(servoNum == 1){ for(int i = 0; i < 10; i = i + 1){ rests1[i] = 0; } } else if(servoNum == 2){ for(int i = 0; i < 10; i = i + 1){ rests2[i] = 0; } } else{ for(int i = 0; i < 10; i = i + 1){ rests3[i] = 0; } } } void printRests(int servoNum){ if(servoNum == 1){ Serial.print("1: "); for(int i = 0; i < 10; i = i + 1){ Serial.print(rests1[i]); Serial.print(" "); } } else if(servoNum == 2){ Serial.print("2: "); for(int i = 0; i < 10; i = i + 1){ Serial.print(rests2[i]); Serial.print(" "); } } else{ Serial.print("3: "); for(int i = 0; i < 10; i = i + 1){ Serial.print(rests3[i]); Serial.print(" "); } } Serial.println(); } void beatServo(int servoNum){ val = 0; // read the value from the sensor, between 0 - 1024 if (val > 0 && val <= 999 ) { pulseWidth = val*2 + minPulse; // convert angle to microseconds //Serial.print("moving servo to "); //Serial.println(pulseWidth,DEC); } updateServo(servoNum); // update servo position val = 999; // read the value from the sensor, between 0 - 1024 if (val > 0 && val <= 999 ) { pulseWidth = val*2 + minPulse; // convert angle to microseconds //Serial.print("moving servo to "); //Serial.println(pulseWidth,DEC); } updateServo(servoNum); // update servo position } // called every loop(). void updateServo(int servoNum) { // pulse the servo again if the refresh time (20 ms) has passed: if (millis() - lastPulse >= refreshTime) { digitalWrite(servoNum, HIGH); // Turn the motor on delayMicroseconds(pulseWidth); // Length of the pulse sets the motor position digitalWrite(servoNum, LOW); // Turn the motor off lastPulse = millis(); // save the time of the last pulse } }