Description:
We wanted to make a musical instrument we could seemingly touch and manipulate. We liked the idea of somehow touching or interacting with water to produce music. We ended up making a water instrument which is an aquarium of water that can be played by any interaction which creates ripples in the water. In our demo, we are using a water bottle to drip water into the tank.
The aquarium is rested on top of a styrofoam board. We've embeded six photocell sensors which rest underneath the aquarium. They are attached to 12 alligator wires which are wired to our arduino board. When the photocells detect change in light above a certain threshold, it plays a noise, which is also mapped to a visualization through processing. The ripple generate midi sounds now, which can feed into garage band or any midi synths to create sounds.
Material:
6 photocell sensors
12 alligator clips
styrofoam board
wires
arbuino board
Code:
Processing code:
import processing.serial.*;
import themidibus.*;
MidiBus myBus; // The MidiBus
Timer[] timers = new Timer[6];
int[] counters = new int[6];
String portname = "/dev/tty.usbmodemfa131"; ///dev/cu.usbmodemfa131
Serial port;
String buf="";
int cr = 13; // ASCII return == 13
int lf = 10; // ASCII linefeed == 10
void setup()
{
//size(400,260);
size(1280, 800);
println(Serial.list());
port = new Serial(this, portname, 9600);
port.write("65");
//movies[0].play();
MidiBus.list();
//myBus = new MidiBus(this, 0, "");
myBus = new MidiBus(this, "", 0);
for (int i = 0; i < timers.length; i = i+1) {
timers[i] = new Timer(400);
counters[i] = 1;
}
noStroke();
background(0,0,0);
}
void draw()
{
for (int i = 0; i < timers.length; i = i+1) {
if (timers[i].started & timers[i].isFinished()) {
noteOff(i+1);
}
}
fill(232,255,240, 5);
rect(0,0, width, height);
}
void noteOn(int i) {
timers[i-1].start();
//counters[i-1] += 1;
myBus.sendNoteOn(0, (i+10) * 5, 150);
draw_note(i);
}
void draw_note(int i) {
int row = 2;
int pos = i;
fill(57, 121, 148);
if( i > 3 ) {
row = 1;
pos = i - 3;
}
ellipse(width/3 * (pos-1) + width/6, height/4 * row + (width/6 * (row - 1)) , width/6, width/6);
}
void noteOff(int i) {
myBus.sendNoteOff(0, (i+10) * 5, 150);
timers[i-1].started = false;
// if(counters[i-1] > 1) {
// counters[i-1] -= 1;
// }
//
// if(counters[i-1] > 10) {
// counters[i-1] = 0;
// }
}
void keyPressed() {
// if(key == '1') {
// myBus.sendNoteOn(0, 60, 127);
// }
if(key == '1') {
noteOn(1);
}
if(key == '2') {
noteOn(2);
}
if(key == '3') {
noteOn(3);
}
if(key == '4') {
noteOn(4);
}
if(key == '5') {
noteOn(5);
}
if(key == '6') {
noteOn(6);
}
}
void keyReleased() {
// if(key == '1') {
// myBus.sendNoteOff(0, 60, 127);
// }
if (keyCode == ENTER) {
println("Rebase");
port.write(65);
fill(0);
rect(0,0, width, height);
}
}
// called whenever serial data arrives
void serialEvent(Serial p) {
int c = port.read();
if (c != lf && c != cr) {
buf += char(c);
// println(buf);
}
if (c == lf) {
int val = int(buf);
//println("val="+val);
if(val < 7) {
noteOn(val);
println("play: " + val);
}else{
//noteOff(val-6);
println("pause: " + (val-6));
}
buf = "";
}
}
timer:
// Learning Processing
// Daniel Shiffman
// http://www.learningprocessing.com
// Example 10-5: Object-oriented timer
class Timer {
int savedTime; // When Timer started
int totalTime; // How long Timer should last
boolean started = false;
Timer(int tempTotalTime) {
totalTime = tempTotalTime;
}
// Starting the timer
void start() {
// When the timer starts it stores the current time in milliseconds.
savedTime = millis();
started = true;
}
void stop() {
started = false;
}
// The function isFinished() returns true if 5,000 ms have passed.
// The work of the timer is farmed out to this method.
boolean isFinished() {
// Check how much time has passed
int passedTime = millis()- savedTime;
if (passedTime > totalTime) {
started = false;
return true;
} else {
return false;
}
}
}
Arduino code:
int sensorPin[] = {0,1,2,3,4,5};
int numOfSensor = 6;
int sensorBase[] = {300,300,300,300,300,300};
boolean sensorState[] = {false, false, false, false, false, false};
int threshold = 5;
void setup() {
Serial.begin(9600);
}
void loop() {
if (Serial.available() > 0 ) {
base();
}
for(int i=0; i<numOfSensor; i++) {
check(i);
}
}
void check(int s) {
int val = analogRead(sensorPin[s]); // read the value from the sensor, between 0 - 1024
// Serial.print(s);
// Serial.print(": ");
// Serial.println(val);
if (val > sensorBase[s] + threshold) {
if(sensorState[s] == false){
Serial.println(s+1);
sensorState[s] = true;
}
}
else {
if(sensorState[s] == true) {
Serial.println(s+7);
sensorState[s] = false;
}
}
delay(10);
}
void base(){
//Serial.println("base: ");
for(int i=0; i<numOfSensor; i++) {
sensorBase[i] = analogRead(sensorPin[i]);
//Serial.println(sensorBase[i]);
}
while(Serial.available() > 0) {
Serial.read();
}
}
VIDEO