Team Members: Shaohan Chen, Michael Craig, Eungchan Kim, Eddie Lee
Description
Our instrument attempts a novel take on the classic "Ladders" game. Three photocells control three percussion shakers attached to servo motors. Each time a user presses one (or several) of the photocells, a gray line (or lines) "climbs" to the top of the ladder in our Processing visualization. Wherever that line ends up at the top of the ladder determines which of the shakers will turn.
Also, a Piezo speaker, controlled by an FSR, plays a bass rhythm whenever the FSR is pressed. As an added game-like element, the Piezo plays an "ugly" sound whenever the FSR is pressed too hard.
Challenges
One unresolved challenge is the question of how to get the Piezo output to play without stopping the rotation of the shakers. As currently written, our code allows the speaker to play after the shakers have completed a full rotation (or continuously if the shakers aren't moving). This was the only way we found to integrate working serial reads for all four instruments into a single code file (and we think it makes for an interesting rhythmic effect in its own right!), but we had originally hoped to have the speaker sound backing up the shakers, not alternating with them. Any advice on how to achieve this would be much appreciated!
VIDEO
Components Used
1 - Arduino UNO
1 - Solderless Breadboard
3 - Photocells
3 - Servo Motors
1 - Force Sensitive Resistor
1 - Piezo Speaker
4 - 10k-ohm Resistors
Plastic Cups, Balsa Wood, Packaging Tape
Code
1. Arduino Code
Servo myservo ; // create servo object to control a servo
Servo myservo1 ; // create servo object to control a servo 1
Servo myservo2 ; // create servo object to control a servo 2
int servoPin [ 3 ] = { 6 , 7 , 8 };
int phoPin [ 3 ] = { A0 , A1 , A2 };
int pos = 0 ; // variable to store the servo position
int speed = 5 ; //5ms
int threshold = 500 ; // A0 --- pin 6 - white
int threshold1 = 350 ; // A1 ---- pin 7 - r
int threshold2 = 100 ; // A2 ---- pin 8
int val = 0 ;
int val1 = 0 ;
int val2 = 0 ;
int input_case = 0 ;
int output_case = 0 ;
//speaker
int speakerPin = 10 ;
int ledPin = 9 ;
int fsrpin = A3 ;
int fsrval = 0 ;
int speakerval = 0 ;
void setup ()
{
Serial . begin ( 9600 ); // connect to the serial port
myservo . attach ( servoPin [ 0 ]); // attaches the servo on pin 6 to the servo object
myservo1 . attach ( servoPin [ 1 ]); // attaches the servo on pin 7 to the servo object
myservo2 . attach ( servoPin [ 2 ]); // attaches the servo on pin 8 to the servo object
pinMode ( speakerPin , OUTPUT );
pinMode ( ledPin , OUTPUT );
// Serial.println("servo_serial_better ready");
}
void loop ()
{
val = analogRead ( phoPin [ 0 ]); // A0 --- pin 6
val1 = analogRead ( phoPin [ 1 ]); // A1 ---- pin 7
val2 = analogRead ( phoPin [ 2 ]); // A2 ---- pin 8
fsrval = analogRead ( fsrpin );
speakerFn ( fsrval );
// INPUT CASE
if ( val < threshold && val1 < threshold1 && val2 < threshold2 ){ input_case = 1 ;}
else if ( val < threshold && val1 > threshold1 && val2 > threshold2 ){ input_case = 2 ;}
else if ( val > threshold && val1 < threshold1 && val2 > threshold2 ){ input_case = 3 ;}
else if ( val > threshold && val1 > threshold1 && val2 < threshold2 ){ input_case = 4 ;}
else if ( val < threshold && val1 < threshold1 && val2 > threshold2 ){ input_case = 5 ;}
else if ( val < threshold && val1 > threshold1 && val2 < threshold2 ){ input_case = 6 ;}
else if ( val > threshold && val1 < threshold1 && val2 < threshold2 ){ input_case = 7 ;}
else input_case = 0 ;
Serial . println ( input_case );
delay ( 20 );
//send data only when you receive data:
if ( Serial . available () > 0 ) {
// read the incoming byte:
output_case = Serial . read ();
// say what you got:
// Serial.println(output_case, DEC);
// 3 on
if ( output_case == 1 ){
// speakerFn(fsrval);
for ( pos = 0 ; pos < 180 ; pos += 1 ) // goes from 0 degrees to 180 degrees
{ // in steps of 1 degree
myservo . write ( pos ); // tell servo to go to position in variable 'pos'
myservo1 . write ( pos ); // tell servo to go to position in variable 'pos'
myservo2 . write ( pos ); // tell servo to go to position in variable 'pos'
delay ( speed ); // waits 15ms for the servo to reach the position
}
for ( pos = 180 ; pos >= 1 ; pos -= 1 ) // goes from 180 degrees to 0 degrees
{
myservo . write ( pos ); // tell servo to go to position in variable 'pos'
myservo1 . write ( pos ); // tell servo to go to position in variable 'pos'
myservo2 . write ( pos ); // tell servo to go to position in variable 'pos'
delay ( speed ); // waits 15ms for the servo to reach the position
}
}
// Servo6 only on
else if ( output_case == 2 ){
// speakerFn(fsrval);
for ( pos = 0 ; pos < 180 ; pos += 1 ) // goes from 0 degrees to 180 degrees
{ // in steps of 1 degree
myservo . write ( pos ); // tell servo to go to position in variable 'pos'
delay ( speed ); // waits 15ms for the servo to reach the position
}
for ( pos = 180 ; pos >= 1 ; pos -= 1 ) // goes from 180 degrees to 0 degrees
{
myservo . write ( pos ); // tell servo to go to position in variable 'pos'
delay ( speed ); // waits 15ms for the servo to reach the position
}
}
// Servo7 only on
else if ( output_case == 3 ){
// speakerFn(fsrval);
for ( pos = 0 ; pos < 180 ; pos += 1 ) // goes from 0 degrees to 180 degrees
{ // in steps of 1 degree
myservo1 . write ( pos ); // tell servo to go to position in variable 'pos'
delay ( speed ); // waits 15ms for the servo to reach the position
}
for ( pos = 180 ; pos >= 1 ; pos -= 1 ) // goes from 180 degrees to 0 degrees
{
myservo1 . write ( pos ); // tell servo to go to position in variable 'pos'
delay ( speed ); // waits 15ms for the servo to reach the position
}
}
// Servo8 only on
else if ( output_case == 4 ){
// speakerFn(fsrval);
for ( pos = 0 ; pos < 180 ; pos += 1 ) // goes from 0 degrees to 180 degrees
{ // in steps of 1 degree
myservo2 . write ( pos ); // tell servo to go to position in variable 'pos'
delay ( speed ); // waits 15ms for the servo to reach the position
}
for ( pos = 180 ; pos >= 1 ; pos -= 1 ) // goes from 180 degrees to 0 degrees
{
myservo2 . write ( pos ); // tell servo to go to position in variable 'pos'
delay ( speed ); // waits 15ms for the servo to reach the position
}
}
// Servo6 and 7 on
else if ( output_case == 5 ){
// speakerFn(fsrval);
for ( pos = 0 ; pos < 180 ; pos += 1 ) // goes from 0 degrees to 180 degrees
{ // in steps of 1 degree
myservo . write ( pos ); // tell servo to go to position in variable 'pos'
myservo1 . write ( pos ); // tell servo to go to position in variable 'pos'
delay ( speed ); // waits 15ms for the servo to reach the position
}
for ( pos = 180 ; pos >= 1 ; pos -= 1 ) // goes from 180 degrees to 0 degrees
{
myservo . write ( pos ); // tell servo to go to position in variable 'pos'
myservo1 . write ( pos ); // tell servo to go to position in variable 'pos'
delay ( speed ); // waits 15ms for the servo to reach the position
}
}
// Servo6 and 8 on
else if ( output_case == 6 ){
// speakerFn(fsrval);
for ( pos = 0 ; pos < 180 ; pos += 1 ) // goes from 0 degrees to 180 degrees
{ // in steps of 1 degree
myservo . write ( pos ); // tell servo to go to position in variable 'pos'
myservo2 . write ( pos ); // tell servo to go to position in variable 'pos'
delay ( speed ); // waits 15ms for the servo to reach the position
}
for ( pos = 180 ; pos >= 1 ; pos -= 1 ) // goes from 180 degrees to 0 degrees
{
myservo . write ( pos ); // tell servo to go to position in variable 'pos'
myservo2 . write ( pos ); // tell servo to go to position in variable 'pos'
delay ( speed ); // waits 15ms for the servo to reach the position
}
}
// Servo7 and 8 on
else if ( output_case == 7 ){
// speakerFn(fsrval);
for ( pos = 0 ; pos < 180 ; pos += 1 ) // goes from 0 degrees to 180 degrees
{ // in steps of 1 degree
myservo1 . write ( pos ); // tell servo to go to position in variable 'pos'
myservo2 . write ( pos ); // tell servo to go to position in variable 'pos'
delay ( speed ); // waits 15ms for the servo to reach the position
}
for ( pos = 180 ; pos >= 1 ; pos -= 1 ) // goes from 180 degrees to 0 degrees
{
myservo1 . write ( pos ); // tell servo to go to position in variable 'pos'
myservo2 . write ( pos ); // tell servo to go to position in variable 'pos'
delay ( speed ); // waits 15ms for the servo to reach the position
}
}
}
}
void speakerFn ( int fsrval )
{
if ( 8 < fsrval && fsrval < 699 ){
tone ( speakerPin , 75 , 150 );
delay ( 150 );
tone ( speakerPin , 75 , 150 );
delay ( 150 );
tone ( speakerPin , 150 , 200 );
delay ( 200 );
}
else if ( 700 < fsrval ){
tone ( speakerPin , 75 , 50 );
delay ( 50 );
tone ( speakerPin , 800 , 80 );
delay ( 80 );
tone ( speakerPin , 125 , 50 );
delay ( 50 );
tone ( speakerPin , 75 , 50 );
delay ( 50 );
tone ( speakerPin , 800 , 80 );
delay ( 80 );
tone ( speakerPin , 125 , 50 );
delay ( 50 );
tone ( speakerPin , 75 , 50 );
delay ( 50 );
tone ( speakerPin , 800 , 80 );
delay ( 80 );
tone ( speakerPin , 125 , 50 );
delay ( 50 );
tone ( speakerPin , 3000 , 3000 );
delay ( 3000 );
}
else {
digitalWrite ( speakerPin , LOW );
}
}
2. Processing Code
float y = 100 ;
float angle1 = 0.0 ;
float segLength = 50 ;
int ladderheight , laddery , ladderspacing ;
int ladder1x , ladder2x , ladder3x , ladder4x , ladder5x , ladder6x , ladder7x ;
int [] ladder1randoms , ladder2randoms , ladder3randoms , ladder4randoms , ladder5randoms , ladder6randoms ;
int numRandom ;
int [] laddersx = new int [ 10 ];
int rectX , rectY ;
int traceX , traceY ;
int rectSize = 20 ;
boolean rectOver ;
boolean traceOver ;
import processing.serial.* ;
// Change this to the portname your Arduino board
String portname = "COM3" ;
String serial_input ;
Serial port ;
String buf = "" ;
int cr = 13 ; // ASCII return == 13
int lf = 10 ; // ASCII linefeed == 10
void setup () {
port = new Serial ( this , portname , 9600 );
port . bufferUntil ( '\n' );
size ( 700 , 360 );
}
void draw () {
update ( mouseX , mouseY );
}
// called whenever serial data arrives
void serialEvent ( Serial port ) {
serial_input = port . readStringUntil ( '\n' );
println ( serial_input );
int answer = runTrace ( Integer . parseInt ( trim ( serial_input )));
port . write ( answer );
}
void drawBase () {
color yellow = color ( 255 , 210 , 60 );
color blue = color ( 70 , 70 , 240 );
color red = color ( 245 , 50 , 50 );
noStroke ();
fill ( blue );
ellipse ( 42 , 30 , 10 , 10 );
ellipse ( 350 , 30 , 10 , 10 );
ellipse ( 540 , 30 , 10 , 10 );
ellipse ( 640 , 30 , 10 , 10 );
fill ( red );
ellipse ( 57 , 30 , 10 , 10 );
ellipse ( 250 , 30 , 10 , 10 );
ellipse ( 460 , 30 , 10 , 10 );
ellipse ( 655 , 30 , 10 , 10 );
fill ( yellow );
ellipse ( 71 , 30 , 10 , 10 );
ellipse ( 151 , 30 , 10 , 10 );
ellipse ( 445 , 30 , 10 , 10 );
ellipse ( 555 , 30 , 10 , 10 );
strokeWeight ( 10.0 );
stroke ( 255 , 200 );
ladder1x = 50 ;
laddery = 50 ;
ladderheight = 150 ;
ladderspacing = 100 ;
ladder2x = ladder1x + ladderspacing ;
ladder3x = ladder1x + 2 * ladderspacing ;
ladder4x = ladder1x + 3 * ladderspacing ;
ladder5x = ladder1x + 4 * ladderspacing ;
ladder6x = ladder1x + 5 * ladderspacing ;
ladder7x = ladder1x + 6 * ladderspacing ;
laddersx [ 0 ] = 0 ;
laddersx [ 1 ] = ladder1x ;
laddersx [ 2 ] = ladder2x ;
laddersx [ 3 ] = ladder3x ;
laddersx [ 4 ] = ladder4x ;
laddersx [ 5 ] = ladder5x ;
laddersx [ 6 ] = ladder6x ;
laddersx [ 7 ] = ladder7x ;
line ( ladder1x , laddery , ladder1x , laddery + ladderheight );
line ( ladder2x , laddery , ladder2x , laddery + ladderheight );
line ( ladder3x , laddery , ladder3x , laddery + ladderheight );
line ( ladder4x , laddery , ladder4x , laddery + ladderheight );
line ( ladder5x , laddery , ladder5x , laddery + ladderheight );
line ( ladder6x , laddery , ladder6x , laddery + ladderheight );
line ( ladder7x , laddery , ladder7x , laddery + ladderheight );
}
void update ( int x , int y ) {
if ( overRect ( rectX , rectY , rectSize , rectSize ) ) {
rectOver = true ;
traceOver = false ;
} else if ( overRect ( traceX , traceY , rectSize , rectSize )) {
traceOver = true ;
rectOver = false ;
} else {
rectOver = false ;
traceOver = false ;
}
}
void drawRandom1 ( int ladderheight , int laddery , int ladder1x , int ladder2x ) {
stroke ( 255 , 200 );
numRandom = 2 ;
ladder1randoms = new int [ numRandom ];
for ( int i = 0 ; i < numRandom ; i ++) {
int randomy = ( int ) random ( laddery , ladderheight + laddery );
// store the random y locations
ladder1randoms [ i ] = randomy ;
line ( ladder1x , randomy , ladder2x , randomy );
}
ladder2randoms = new int [ numRandom ];
for ( int i = 0 ; i < numRandom ; i ++) {
int randomy = ( int ) random ( laddery , ladderheight + laddery );
// store the random y locations
ladder2randoms [ i ] = randomy ;
line ( ladder2x , randomy , ladder3x , randomy );
}
ladder3randoms = new int [ numRandom ];
for ( int i = 0 ; i < numRandom ; i ++) {
int randomy = ( int ) random ( laddery , ladderheight + laddery );
// store the random y locations
ladder3randoms [ i ] = randomy ;
line ( ladder3x , randomy , ladder4x , randomy );
}
ladder4randoms = new int [ numRandom ];
for ( int i = 0 ; i < numRandom ; i ++) {
int randomy = ( int ) random ( laddery , ladderheight + laddery );
// store the random y locations
ladder4randoms [ i ] = randomy ;
line ( ladder4x , randomy , ladder5x , randomy );
}
ladder5randoms = new int [ numRandom ];
for ( int i = 0 ; i < numRandom ; i ++) {
int randomy = ( int ) random ( laddery , ladderheight + laddery );
// store the random y locations
ladder5randoms [ i ] = randomy ;
line ( ladder5x , randomy , ladder6x , randomy );
}
ladder6randoms = new int [ numRandom ];
for ( int i = 0 ; i < numRandom ; i ++) {
int randomy = ( int ) random ( laddery , ladderheight + laddery );
// store the random y locations
ladder6randoms [ i ] = randomy ;
line ( ladder6x , randomy , ladder7x , randomy );
}
}
int whichLadder ( int ladder ) {
if ( ladder == 1 ) {
return 2 ;
} else if ( ladder == 2 ) {
return 3 ;
} else if ( ladder == 3 ) {
return 4 ;
} else if ( ladder == 4 ) {
return 5 ;
} else if ( ladder == 5 ) {
return 6 ;
} else if ( ladder == 6 ) {
return 7 ;
} else if ( ladder == 7 ) {
return 7 ;
} else {
return 0 ;
}
}
int runTrace ( int starting ) {
if (!( starting == 0 )) {
background ( 200 );
drawRandom1 ( ladderheight , laddery , ladder1x , ladder2x );
drawBase ();
stroke ( 100 , 100 );
int sx , sy , ex , ey ;
int currentLadder = 1 ;
sy = laddery + ladderheight ;
if ( starting == 1 ) {
sx = ladder1x ; ex = ladder1x ; currentLadder = 1 ;
} else if ( starting == 2 ) {
sx = ladder2x ; ex = ladder2x ; currentLadder = 2 ;
} else if ( starting == 3 ) {
sx = ladder3x ; ex = ladder3x ; currentLadder = 3 ;
} else if ( starting == 4 ) {
sx = ladder4x ; ex = ladder4x ; currentLadder = 4 ;
} else if ( starting == 5 ) {
sx = ladder5x ; ex = ladder5x ; currentLadder = 5 ;
} else if ( starting == 6 ) {
sx = ladder6x ; ex = ladder6x ; currentLadder = 6 ;
} else if ( starting == 7 ) {
sx = ladder7x ; ex = ladder7x ; currentLadder = 7 ;
}
ladder1randoms = sort ( ladder1randoms );
ladder2randoms = sort ( ladder2randoms );
ladder3randoms = sort ( ladder3randoms );
ladder4randoms = sort ( ladder4randoms );
ladder5randoms = sort ( ladder5randoms );
ladder6randoms = sort ( ladder6randoms );
boolean notFinished = true ;
int [] heights = new int [ 5 ];
int [] heights2 = new int [ 5 ];
int currentHeight = sy ;
while ( notFinished ) {
if ( currentLadder == 1 ) {
heights = ladder1randoms ;
} else if ( currentLadder == 2 ) {
heights = ladder2randoms ;
heights2 = ladder1randoms ;
} else if ( currentLadder == 3 ) {
heights = ladder3randoms ;
heights2 = ladder2randoms ;
} else if ( currentLadder == 4 ) {
heights = ladder4randoms ;
heights2 = ladder3randoms ;
} else if ( currentLadder == 5 ) {
heights = ladder5randoms ;
heights2 = ladder4randoms ;
} else if ( currentLadder == 6 ) {
heights = ladder6randoms ;
heights2 = ladder5randoms ;
} else if ( currentLadder == 7 ) {
heights = ladder6randoms ;
} else {
println ( "ERROR CURRENT LADDER OUT OF BOUNDS" );
}
int tempHeight = currentHeight ;
for ( int i = numRandom - 1 ; i >= 0 ; i --) {
ey = heights [ i ];
if ( ey < currentHeight ) {
currentHeight = ey ;
sx = laddersx [ currentLadder ];
ex = sx ;
sy = tempHeight ;
line ( sx , sy , ex , ey );
currentLadder = whichLadder ( currentLadder );
int nx = laddersx [ currentLadder ];
line ( sx , ey , nx , ey );
if ( currentLadder == 1 ) {
heights = ladder1randoms ;
} else if ( currentLadder == 2 ) {
heights = ladder2randoms ;
} else if ( currentLadder == 3 ) {
heights = ladder3randoms ;
} else if ( currentLadder == 4 ) {
heights = ladder4randoms ;
} else if ( currentLadder == 5 ) {
heights = ladder5randoms ;
} else if ( currentLadder == 6 ) {
heights = ladder5randoms ;
}
break ;
}
}
if ( currentHeight == tempHeight ) {
int nx = 0 ;
ey = 0 ;
// check neighbors
int tempHeight2 = currentHeight ;
for ( int i = numRandom - 1 ; i >= 0 ; i --) {
ey = heights2 [ i ];
if ( ey < currentHeight ) {
currentHeight = ey ;
sx = laddersx [ currentLadder ];
ex = sx ;
sy = tempHeight2 ;
line ( sx , sy , ex , ey );
currentLadder = whichLadder ( currentLadder );
nx = laddersx [ currentLadder ];
line ( sx , ey , nx , ey );
if ( currentLadder == 1 ) {
heights = ladder1randoms ;
} else if ( currentLadder == 2 ) {
heights = ladder2randoms ;
} else if ( currentLadder == 3 ) {
heights = ladder3randoms ;
} else if ( currentLadder == 4 ) {
heights = ladder4randoms ;
} else if ( currentLadder == 5 ) {
heights = ladder5randoms ;
} else if ( currentLadder == 6 ) {
heights = ladder5randoms ;
}
break ;
}
}
notFinished = false ;
}
}
return currentLadder ;
}
return 0 ;
}
boolean overRect ( int x , int y , int width , int height ) {
if ( mouseX >= x && mouseX <= x + width &&
mouseY >= y && mouseY <= y + height ) {
return true ;
} else {
return false ;
}
}
void segment ( float x , float y , float a ) {
pushMatrix ();
translate ( x , y );
rotate ( a );
line ( 0 , 0 , segLength , 0 );
popMatrix ();
}