ARDUINO PROJECT THE BEATLES MUSIC POSTER
DPL628 INTERFACE & INTERACTION DESIGN
INTRODUCTION For the beginning of this project we started by wanting to do something fun and tangible. We first observed for the things we have learnt in class, added to the interest and skills we both have. We both kept in mind that we wanted to be creative in the material and resource that we have. With both our graphic skills, the interested on music especially the Beatles, we wanted to take the most simple and historic media of time and turn it to an interface, which is the poster. A poster is a placard displayed in a public place, designed to be attached to a vertical surface. For over two hundred years, posters have been displayed in public places all over the world. Visually striking, they have been designed to attract the attention of passers-by, making us aware of a political viewpoint, enticing us to attend specific events, or encouraging us to purchase some product or service. Posters are designed to be both eye-catching and informative. Later on we found a new material that was tangible and have an artistic function, which is the conductive ink. With this material we can turn anything we draw in to a surface for interaction. The conductive ink will act as capacitive sensor.
MATERIALS USED IN PROCESS
Another element we had to combine with the work was music. We chose the MIDI (Musical Instrument Digital Interface). MIDI is a technical standard that describes a digital interface, allows a wide variety of electronic musical instruments, computers and other related devices to connect and communicate with one another. The reason we have chosen the MIDI rather than other is we need the interactive poster to be independent, and not need any connection to a computer device. One of us turn the Beatles' Song to a MIDI tone.
THE BEATLES' TONES Ticket to Ride f# a f# a f# a a b a C f# a a f#
f# a f# a f# a b a f#
f# a f# a f#
In My Life cdgfgaCa gagfdcaa cdgfgana gag fdcaa aaggffddfag aqagfdcaa aaggffdd fag cdgfdcaa Here Comes the Sun bgab bagegaged bgab babg babgeag bag
b a g e b a g f#
Two of Us degabag abag Cba degabag abag Cbaag abnb abnbb bnb note: "C" is for an higher octave
In between the process of the work, we have done many experiments before the completion of the project. By experimenting we gain more information little by little. This what we had experimented: WEEK 1 Try on the capacitive sensor code with conductive yarn, by giving result for turning on a LED. WEEK 2 Paint the conductive ink and use it as a conductive to turn a LED on. For the result, is you have to use enough amount of ink to make the surface conductive, and for the different section of surface, the paint should be connected with the other surface. WEEK 3 Building a Noise Maker with Bare Paint and a 555 timer. We built a simple circuit by using a 555 timer and a Bare Paint potentiometer to make an interactive noise-maker. No need to have an arduino. The sound coming out of the speaker will be able to change by changing the position of the slider on the painted potentiometer. By varying the resistance you change the pitch of the sound. WEEK 4 Testing the paint again by experiment on the distance between area painted, with other types of paint painted in between, on different types of paper. Now trying the conductive surface with the capacitive sensor code, giving result for turning the LED on.
WEEK 5 FINAL DESIGN &
TESTING MODIFIED CODE The Poster Design Our design was inspired from the graphic from the Yellow Submarine album. The goal on designing is to make it eye-catching and invites passers-by to interact with poster.
CONNECTING THE CIRCUIT When you touch a conductive object, you create a certain degree of capacitance. This increases the ability of the conductive material you touched to store a charge. Create a capacitive sensor by measuring how long it takes for a piece of conductive material to go from a grounded state to a higher potential state when pulled up to that higher state through a resistor. The higher the capacitance, the longer it will take the conductive material to be pulled up to the high state. Ink conducts electricity. Therefore, if we take our conductive ink, pull it to ground, then try and pull it to a higher state, we can measure how long it takes, and if we're touching the ink, it will take longer to get to a high state than usual. Conveniently, we can use the Arduino to automatically pull our trace to ground on and off. If we attach a pull-up resistor to our line, when the ground connection inside the Arduino is turned off, everything attached to the pin will start to be pulled up to VCC. The circuit diagram will look something like this. We use an external pull-up resistor rather than the Arduino's internal pin pull-up resistors since we need much more resistance than the 30K ohm internal ones, otherwise, the resistance of the ink tends to dominate and prevent the sensor from working.
MODIFYING THE CODE Basically, the code was combined with two main code. First was the Melody Tone which we had learnt in one of our class. Second was the Capacitive Sensor. The Melody Tone code only play the song we input and uploaded repeatedly. We found some complications on this section. Firstly, is the flat and sharp tones for in the Arduino website did not mention for the flat and sharp notes. The calculation of the tones is made following the mathematical operation: timeHigh = period / 2 = 1 / (2 * toneFrequency) where the different tones are described as in the table: note c c# d d# e f f# g g# a a# b C
frequency 261 Hz 277 Hz 294 Hz 311 Hz 329 Hz 349 Hz 370 Hz 392 Hz 415 Hz 440 Hz 466 Hz 493 Hz 523 Hz
period 3830 3610 3400 3215 3038 2864 2702 2550 2409 2272 2145 2028 1912
timeHigh 1915 1805 1700 1608 1519 1432 1351 1275 1205 1136 1073 1014 956
Secondly, is the Arduino does not read f# as a whole character. It read as a "f" and a "#". Arduino also read "space" as a character, in this situation is a rest for the notes. For that we had to replace with another character. So we replace the original notes as below. c# = s g# = t
d# = w a# = q
f# = r C=n
ORIGINAL CODE OF THE MELODY TONE Jingle Bell Song
int speakerPin = 9; int length = 15; // the number of notes char notes[] = "ccggaagffeeddc "; // a space represents a rest int beats[] = { 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 4 }; int tempo = 300; void playTone(int tone, int duration) { for (long i = 0; i < duration * 1000L; i += tone * 2) { digitalWrite(speakerPin, HIGH); delayMicroseconds(tone); digitalWrite(speakerPin, LOW); delayMicroseconds(tone); } } void playNote(char note, int duration) { char names[] = { 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C' }; int tones[] = { 1915, 1700, 1519, 1432, 1275, 1136, 1014, 956 }; // play the tone corresponding to the note name for (int i = 0; i < 8; i++) { if (names[i] == note) { playTone(tones[i], duration); } } } void setup() { pinMode(speakerPin, OUTPUT); } void loop() { for (int i = 0; i < length; i++) { if (notes[i] == ' ') { delay(beats[i] * tempo); // rest } else { playNote(notes[i], beats[i] * tempo); } // pause between notes delay(tempo / 2); } }
Source: www.arduino.cc
For the Capacitive Sensor code is for getting the input when we come in contact with the sensor. We later found out that a pencil can be use as a conductor, for the graphite.
THE CAPACITIVE SENSOR CODE // Pin for the LED int LEDPin = 13; // Pin to connect to your drawing int capSensePin = 2; // This is how high the sensor needs to read in order // to trigger a touch. You'll find this number // by trial and error, or you could take readings at // the start of the program to dynamically calculate this. int touchedCutoff = 60; void setup(){ Serial.begin(9600); // Set up the LED pinMode(LEDPin, OUTPUT); digitalWrite(LEDPin, LOW); } void loop(){ // If the capacitive sensor reads above a certain threshold, // turn on the LED if (readCapacitivePin(capSensePin) > touchedCutoff) { digitalWrite(LEDPin, HIGH); } else { digitalWrite(LEDPin, LOW); } // Every 500 ms, print the value of the capacitive sensor if ( (millis() % 500) == 0){ Serial.print("Capacitive Sensor on Pin 2 reads: "); Serial.println(readCapacitivePin(capSensePin)); } } // readCapacitivePin // Input: Arduino pin number // Output: A number, from 0 to 17 expressing // how much capacitance is on the pin // When you touch the pin, or whatever you have // attached to it, the number will get higher // In order for this to work now, // The pin should have a 1+Megaohm resistor pulling // it up to +5v. uint8_t readCapacitivePin(int pinToMeasure){ // This is how you declare a variable which
// will hold the PORT, PIN, and DDR registers // on an AVR volatile uint8_t* port; volatile uint8_t* ddr; volatile uint8_t* pin; // Here we translate the input pin number from // Arduino pin number to the AVR PORT, PIN, DDR, // and which bit of those registers we care about. byte bitmask; if ((pinToMeasure >= 0) && (pinToMeasure <= 7)){ port = &PORTD; ddr = &DDRD; bitmask = 1 << pinToMeasure; pin = &PIND; } if ((pinToMeasure > 7) && (pinToMeasure <= 13)){ port = &PORTB; ddr = &DDRB; bitmask = 1 << (pinToMeasure - 8); pin = &PINB; } if ((pinToMeasure > 13) && (pinToMeasure <= 19)){ port = &PORTC; ddr = &DDRC; bitmask = 1 << (pinToMeasure - 13); pin = &PINC; } // Discharge the pin first by setting it low and output *port &= ~(bitmask); *ddr |= bitmask; delay(1); // Make the pin an input WITHOUT the internal pull-up on *ddr &= ~(bitmask); // Now see how long the pin to get pulled up int cycles = 16000; for(int i = 0; i < cycles; i++){ if (*pin & bitmask){ cycles = i; break; } } // Discharge the pin again by setting it low and output // It's important to leave the pins low if you want to // be able to touch more than 1 sensor at a time - if // the sensor is left pulled high, when you touch // two sensors, your body will transfer the charge between // sensors. *port &= ~(bitmask); *ddr |= bitmask; return cycles; } source: instructables.com/id/Turn-a-pencil-drawing-into-a-capacitive-sensor-for
THE MODIFIED MIDI POSTER CODE black color is for part modified int int int int int int int
speakerPin = 9; // not necessary LEDPin = 13; capSensePin = 2; capSensePin2 = 3; capSensePin3 = 4; capSensePin4 = 6; touchedCutoff = 60;
// Ticket to Ride int length1 = 30; // the number of tone incuding rest char notes1[] = "rararaab rararabar rararanraar"; int beats1[] = { 2, 1, 1, 1, 1, 1, 2, 3, 1, 2, 1, 1, 1, 1, 1, 2, 2, 3, 1, 2, 1, 1, 1, 1, 1, 4, 1, 1, 2, 4}; // In My Life int length2 = 78; byte notes2[] = "cdgfgana gagfdcaa cdgfgana gagfdcaa aaggffddfag aqagfdcaa aaggffddfag cdgfdcaa"; int beats2[] = { 2, 2, 3, 3, 3, 3, 2, 4, 2, 2, 2, 4, 3, 3, 2, 2, 4, 2, 2, 2, 3, 3, 3, 3, 2, 4, 2, 2, 2, 4, 3, 3, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 4, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 3, 4, 4, 2, 2, 4}; // Here Comes the Sun int length3 = 45; char notes3[] = "bgab bagegaged bgab int beats3[] = { 1, 1, 1, 3, 3, 1, 1, 1, 1, 3, 3, 1, 1, 3, 3, 4, 3, 1, 4,};
bagebagr 3, 3, 3, 3, 3, 3, 3, 3, 4,
babg babgeag bag"; 3, 3, 3, 2, 3, 3, 2, 3, 3, 4, 3, 3, 3, 4, 3, 3, 3,
// Two of Us int length4 = 50; char notes4[] = "degabag abag nba degabag abag nbaag abnb abnb bbnb"; int beats4[] = { 2, 2, 4, 4, 3, 3, 4, 2, 4, 3, 3, 4, 2, 4, 4, 4, 3, 2, 2, 4, 4, 3, 3, 4, 2, 4, 3, 3, 4, 2, 4, 4, 4, 4, 4, 3, 2, 2, 4, 4, 2, 2, 2, 4, 4, 2, 2, 2, 4, 4}; int tempo = 120; void playTone(int tone, int duration) { for (long i = 0; i < duration * 1000L; i += tone * 2) { digitalWrite(speakerPin, HIGH); delayMicroseconds(tone);
digitalWrite(speakerPin, LOW); delayMicroseconds(tone); } } void playNote(char note, int duration) { char names[] = { 'c','s', 'd','w', 'e', 'f', 'r','g', 't','a', 'q','b', 'n' }; int tones[] = { 1915, 1805, 1700, 1608, 1519, 1432, 1351, 1275, 1205, 1136, 1073, 1014, 956}; // play the tone corresponding to the note name for (int i = 0; i < 13; i++) { //the amount of tone mentioned if (names[i] == note) { playTone(tones[i], duration); } } } void setup(){ Serial.begin(57600); pinMode(speakerPin, OUTPUT); pinMode(LEDPin, OUTPUT); digitalWrite(LEDPin, LOW); } void loop(){ //----Ticket to Ride----if (readCapacitivePin(capSensePin) > touchedCutoff) { digitalWrite(LEDPin, HIGH); Serial.println("Ticket to Ride"); delay(300); for (int i = 0; i < length1; i++) { if (notes1[i] == ' ') { delay(beats1[i] * tempo); // rest } else { playNote(notes1[i], beats1[i] * tempo); } delay(tempo / 2); } } else { digitalWrite(speakerPin, LOW); digitalWrite(LEDPin, LOW); } //----In My Life----if (readCapacitivePin(capSensePin2) > touchedCutoff) { digitalWrite(LEDPin, HIGH); Serial.println("In My Life"); delay(300);
for (int i = 0; i < length2; i++) { if (notes2[i] == ' ') { delay(beats2[i] * tempo); // rest } else { playNote(notes2[i], beats2[i] * tempo); } delay(tempo / 2); } } else { digitalWrite(speakerPin, LOW); digitalWrite(LEDPin, LOW); } //----3Here Comes the Sun----if (readCapacitivePin(capSensePin3) > touchedCutoff) { digitalWrite(LEDPin, HIGH); Serial.println("Here Comes the Sun"); delay(300); for (int i = 0; i < length3; i++) { if (notes3[i] == ' ') { delay(beats3[i] * tempo); // rest } else { playNote(notes3[i], beats3[i] * tempo); } delay(tempo / 2); } } else { digitalWrite(speakerPin, LOW); digitalWrite(LEDPin, LOW); } //----4Two ofUs----if (readCapacitivePin(capSensePin4) > touchedCutoff) { digitalWrite(LEDPin, HIGH); Serial.println("Here Comes the Sun"); delay(300); for (int i = 0; i < length4; i++) { if (notes4[i] == ' ') { delay(beats4[i] * tempo); // rest } else { playNote(notes4[i], beats4[i] * tempo); } delay(tempo / 2); } } else { digitalWrite(speakerPin, LOW); digitalWrite(LEDPin, LOW); }
} uint8_t readCapacitivePin(int pinToMeasure){ volatile uint8_t* port; volatile uint8_t* ddr; volatile uint8_t* pin; byte bitmask; if ((pinToMeasure >= 0) && (pinToMeasure <= 7)){ port = &PORTD; ddr = &DDRD; bitmask = 1 << pinToMeasure; pin = &PIND; } if ((pinToMeasure > 7) && (pinToMeasure <= 13)){ port = &PORTB; ddr = &DDRB; bitmask = 1 << (pinToMeasure - 8); pin = &PINB; } if ((pinToMeasure > 13) && (pinToMeasure <= 19)){ port = &PORTC; ddr = &DDRC; bitmask = 1 << (pinToMeasure - 13); pin = &PINC; } *port &= ~(bitmask); *ddr |= bitmask; delay(1); *ddr &= ~(bitmask); int cycles = 16000; for(int i = 0; i < cycles; i++){ if (*pin & bitmask){ cycles = i; break; } } *port &= ~(bitmask); *ddr |= bitmask; return cycles; }
EXTRA EXPERIMENT Aside from the MIDI poster we also experiment on the Adobe Flash version. For this version, it is essential to connect the Arduino with a computer device. There are two section for this version. First part is for the Arduino. When you press one of the sensor, it generates a character, which will be the input for action script in flash later. The second part is the action script for Flash which take action by playing a piece of .mp3 or .wav when a certain character has been input. int LEDPin = 13; int capSensePin2 = 3; int capSensePin4 = 6;
int capSensePin = 2; int capSensePin3 = 4; int touchedCutoff = 60;
void setup(){ Serial.begin(57600); pinMode(LEDPin, OUTPUT); digitalWrite(LEDPin, LOW); } void loop(){ //----a----if (readCapacitivePin(capSensePin) > touchedCutoff) { digitalWrite(LEDPin, HIGH); Serial.println("a"); delay(300); } else { digitalWrite(LEDPin, LOW); } //----b----if (readCapacitivePin(capSensePin2) > touchedCutoff) { digitalWrite(LEDPin, HIGH); Serial.println("b"); delay(300); } else { digitalWrite(LEDPin, LOW);} //----c----if (readCapacitivePin(capSensePin3) > touchedCutoff) { digitalWrite(LEDPin, HIGH); Serial.println("c"); delay(300); } else { digitalWrite(LEDPin, LOW); }
//----d----if (readCapacitivePin(capSensePin4) > touchedCutoff) { digitalWrite(LEDPin, HIGH); Serial.println("d"); delay(300); } else { digitalWrite(LEDPin, LOW); }} uint8_t readCapacitivePin(int pinToMeasure){ volatile uint8_t* port; volatile uint8_t* ddr; volatile uint8_t* pin; byte bitmask; if ((pinToMeasure >= 0) && (pinToMeasure <= 7)){ port = &PORTD; ddr = &DDRD; bitmask = 1 << pinToMeasure; pin = &PIND; } if ((pinToMeasure > 7) && (pinToMeasure <= 13)){ port = &PORTB; ddr = &DDRB; bitmask = 1 << (pinToMeasure - 8); pin = &PINB; } if ((pinToMeasure > 13) && (pinToMeasure <= 19)){ port = &PORTC; ddr = &DDRC; bitmask = 1 << (pinToMeasure - 13); pin = &PINC; } *port &= ~(bitmask); *ddr |= bitmask; delay(1); *ddr &= ~(bitmask); int cycles = 16000; for(int i = 0; i < cycles; i++){ if (*pin & bitmask){ cycles = i; break; } } *port &= ~(bitmask); *ddr |= bitmask; return cycles; }
For the action script in Flash find it here www.mikechambers.com
Trapond Hiransalee 56120700001 & Thiencharas Wongpisethkul 54451006