User login

Powered by Drupal, an open source content management system

Theory and Practice of Tangible User Interfaces

Jam Juggz! Actuated looping machine

Submitted by ngandomi on Thu, 11/13/2008 - 01:21

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:

Jug Jamz from Ljuba on Vimeo.

 

Materials:

 

  • arduino board
  • force sensor
  • potentiometer
  • 3 servo motors
  • 3 led lights (red, blue, green)
  • small dowels
  • modeling wax
  • rubber bands, tape
  • water jug
  • tin can

 

 

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