User login

Powered by Drupal, an open source content management system

Theory and Practice of Tangible User Interfaces

Lab 5: Can Make Music

Submitted by Becky on Wed, 10/08/2008 - 20:52

Assignment: Input / Output Coincidence Lab Assignment

Collaborators:

Description: In this lab, we used analog input to create digital output in a Piezo speaker.  For the in-class assignment, we used three different sets of code.  The first to test the speaker; the second to produce notes from the speaker from typed information into the serial monitor; the third to create a theremin using a photocell.  In my home exploration, I created a musical instrument using three photocells and the piezo.  When a cell is occluded, the speaker plays a note.  For each of the combinations of covered and uncovered cells, a different note plays.  So this project is a 7-note instrument; embedded in a can.

Materials:

  • Arduino
  • piezo
  • 3 photocells
  • 1 led (for testing)
  • wire
  • computer
  • usb cable
  • aluminum can

Code:

/* Instrument
* --------
*
* Created 7 Oct 2008
* Adapted from Theremin and Sound Serial by Tod Kurt, tod@todbot.com)
*/

int photoPinX = 0; // select the input pin for the photocell
int photoPinY = 1;
int photoPinZ = 2;
int speakerPin = 7;
int ledPin = 13;
int valX = 0;
int valY = 0;
int valZ = 0;
int playX = 0;
int playY = 0;
int playZ = 0;
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(speakerPin, OUTPUT);
beginSerial(9600);
Serial.println("ready");
}


// note names and their corresponding half-periods
byte names[] ={ 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C'};
int tones[] = { 1915, 1700, 1519, 1432, 1275, 1136, 1014, 956};

int serByte = -1;
int ledState = LOW;
int count = 0;

void loop() {
valX = analogRead(photoPinX); // read the value from the sensor, between 0 - 1024
valY = analogRead(photoPinY); // read the value from the sensor, between 0 - 1024
valZ = analogRead(photoPinZ); // read the value from the sensor, between 0 - 1024
Serial.println(valZ); //for testing; to check that analog values are being read

if (valX>900){playX=0;}else if(valX<900){playX=1;} //set threshold values based on ambient lighting situation
if (valY>900){playY=0;}else if(valY<900){playY=1;}
if (valZ>500){playZ=0;}else if(valZ<500){playZ=1;}

//if (valX>970){
if(playX==0 && playY==0 && playZ==0){
digitalWrite(ledPin, LOW); // write to LED
digitalWrite(speakerPin,LOW);

}else if(playX==1 && playY==0 && playZ==0){
int toneVar=1915;
digitalWrite(speakerPin, LOW);
for( int i=0; i<200; i++ ) { // play it for 200 cycles
digitalWrite(speakerPin, HIGH);
delayMicroseconds(toneVar);
digitalWrite(speakerPin, LOW);
delayMicroseconds(toneVar);
}}else if(playX==1 && playY==1 && playZ==0){
int toneVar=1700;
digitalWrite(speakerPin, LOW);
for( int i=0; i<200; i++ ) { // play it for 200 cycles
digitalWrite(speakerPin, HIGH);
delayMicroseconds(toneVar);
digitalWrite(speakerPin, LOW);
delayMicroseconds(toneVar);
}}else if(playX==1 && playY==1 && playZ==1){
int toneVar=1519;
digitalWrite(speakerPin, LOW);
for( int i=0; i<200; i++ ) { // play it for 200 cycles
digitalWrite(speakerPin, HIGH);
delayMicroseconds(toneVar);
digitalWrite(speakerPin, LOW);
delayMicroseconds(toneVar);
}}else if(playX==1 && playY==0 && playZ==1){
int toneVar=1432;
digitalWrite(speakerPin, LOW);
for( int i=0; i<200; i++ ) { // play it for 200 cycles
digitalWrite(speakerPin, HIGH);
delayMicroseconds(toneVar);
digitalWrite(speakerPin, LOW);
delayMicroseconds(toneVar);
}}else if(playX==0 && playY==1 && playZ==0){
int toneVar=1275;
digitalWrite(speakerPin, LOW);
for( int i=0; i<200; i++ ) { // play it for 200 cycles
digitalWrite(speakerPin, HIGH);
delayMicroseconds(toneVar);
digitalWrite(speakerPin, LOW);
delayMicroseconds(toneVar);
}}else if(playX==0 && playY==1 && playZ==1){
int toneVar=1136;
digitalWrite(speakerPin, LOW);
for( int i=0; i<200; i++ ) { // play it for 200 cycles
digitalWrite(speakerPin, HIGH);
delayMicroseconds(toneVar);
digitalWrite(speakerPin, LOW);
delayMicroseconds(toneVar);
}}else if(playX==0 && playY==0 && playZ==1){
int toneVar=1014;
digitalWrite(speakerPin, LOW);
for( int i=0; i<200; i++ ) { // play it for 200 cycles
digitalWrite(speakerPin, HIGH);
delayMicroseconds(toneVar);
digitalWrite(speakerPin, LOW);
delayMicroseconds(toneVar);
}
}

//next part for testing with typed input
digitalWrite(speakerPin, LOW);
serByte = Serial.read();
if (serByte != -1) {
Serial.print(serByte,BYTE);
ledState = !ledState; // flip the LED state
digitalWrite(ledPin, ledState); // write to LED
}
for (count=0;count<=8;count++) { // look for the note
if (names[count] == serByte) { // ahh, found it
for( int i=0; i<50; i++ ) { // play it for 50 cycles
digitalWrite(speakerPin, HIGH);
delayMicroseconds(tones[count]);
digitalWrite(speakerPin, LOW);
delayMicroseconds(tones[count]);
}
}
}

}
PhotoCell: Note Mapping (0 photocell is uncovered; 1 photocell is covered)
CellX CellY CellZ Tone Note
0 0 0 null silent
1 0 0 1915 c
1 1 0 1700 d
1 1 1 1519 e
1 0 1 1432 f
0 1 0 1275 g
0 1 1 1136 a
0 0 1 1014 b

Images:

IMG_1702

Can Make Music; connected and ready to be played.

grasp and play

Can in hand; being played.

IMG_1689

The circuit set up for testing, before installation in can.

IMG_1693

Close-up of board.

Observations/Conclusions:

It is possible to play 7 different notes using this object. I have found that the mapping of notes is not very intuitive -- neither for users other than me, nor for me, eventhough I know what the mapping is. In future iterations, I would adjust this.

I chose the can because I thought it would be a comfortable object to hold and play with one hand. It was difficult to keep the photocells flush with the side of the can.

In future iterations, I would experiment with more shapes -- perhaps embedding the photocells in a mound of material with give so that a user could rest her hand on the material and it would mold to the shape of her hand; and so that the user could rest her hand on a horizontal surface while playing.

The wires on the photocells are long and are prone to touching. When the wires of the photocells touch (short), the resistance of the cell goes to zero and the reading goes to 1024, so that sensor is effectively removed from use in playing notes.

In combing Input and Output in the same object, I found securing the sensor, speaker, and connecting wires challenging. In the future, I may look for different means of affixing these elements to the object.