Tuesday, December 16, 2008

Physical Computing Final: Sensor Dome

The Sensor Dome is an interface for controlling light and sound using photocells. Each of the 16 photocells sends a value based on how much it is covered by shade. These values are used to control both the volume of music tracks and the lights above the sensors. The dimming and animation of the lights above the sensors alter the values of the sensors.


Sensor Dome performs for YOU! from Matt Richard on Vimeo.


Sensor Dome comes together... almost from Matt Richard on Vimeo.


Building the Light Dome for the Sensor Dome! from Matt Richard on Vimeo.

Processing Code:
//Matt Richard(visual) and Eyal Ohana(audio)

import UDP.*; // import Light Tile library
UDPSend udp;

import processing.serial.*; // import the Processing serial library
Serial myPort;

import ddf.minim.signals.*; // import the Minim sound library
import ddf.minim.*;
Minim minim;
AudioOutput out;


//declare variables
int totalSquares = 16; // var for how many squares you want on the screen, !! must be a square itself
int colorMax = 255;
int tracks = 16;
float rectColorArray[][][][]; // create nested array that holds the rects alpha value
float sensorValue[] = new float[tracks]; // array to hold sensor values
AudioPlayer players[] = new AudioPlayer[tracks];
float gain[] = new float[tracks];
float val[] = new float[tracks];


void setup() {
//colorMax = totalSquares;
size(240, 240);
background(0);
colorMode(HSB, 255);
noStroke();
smooth();

udp = new UDPSend(this,"10.031.066.202",6038,"/Users/matt/Documents/Processing/libraries/UDP/colorkinetics_lib/header","/Users/matt/Documents/Processing/libraries/UDP/colorkinetics_lib/lookup",200,0);
myPort = new Serial(this, Serial.list()[0], 9600);
// read bytes into a buffer until you get a linefeed (ASCII 10):
myPort.bufferUntil('\n');

setup_audio(); // contains all of the setup code for audio(located below)
setup_visual(); // contains all of the setup code for visual(located below)
}

void draw() {
draw_audio();
draw_visual();
udp.send();
}


void serialEvent(Serial myPort) {
// serialEvent method is run automatically by the Processing applet
// whenever the buffer reaches the byte value set in the bufferUntil()
// method in the setup():


// read the serial buffer:
String myString = myPort.readStringUntil('\n');
// if you got any bytes other than the linefeed:
if (myString != null) {
myString = trim(myString);

// split the string at the commas
// and convert the sections into integers:
int sensors[] = int(split(myString, ","));

// print out the values you got:
for (int sensorNum = 0; sensorNum < sensors.length; sensorNum++) {
print(sensorNum + ": " + sensors[sensorNum] + " ");
}
// add a linefeed after all the sensor values are printed:
println();
if (sensors.length > 1) {
for(int i=0;i < tracks;i++){
val[i] = map(sensors[i], 100, 300, 7, -30); // map the sensor read to the audible range of the gain for the audio
sensorValue[i] = map(sensors[i], 20,200,0,colorMax); // map the sensor value for visual
}
}
}
}


/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//////// AUDIO FUNCTIONS ////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
void setup_audio(){
minim = new Minim(this);
out = minim.getLineOut();

players[0] = minim.loadFile("01_drums.aif");
players[1] = minim.loadFile("02_filter.aif");
players[2] = minim.loadFile("03_flute.aif");
players[3] = minim.loadFile("04_hard.aif");
players[4] = minim.loadFile("05_horns.aif");
players[5] = minim.loadFile("06_pad.aif");
players[6] = minim.loadFile("07_pad_b.aif");
players[7] = minim.loadFile("08_bass.aif");
players[8] = minim.loadFile("09_didge.aif");
players[9] = minim.loadFile("10_beat_hi.aif");
players[10] = minim.loadFile("11_beat_low.aif");
players[11] = minim.loadFile("12_machine.aif");
players[12] = minim.loadFile("13_click.aif");
players[13] = minim.loadFile("14_scape.aif");
players[14] = minim.loadFile("15_strings.aif");
players[15] = minim.loadFile("16_bells.aif");
//players[.play();
for (int i=0; i< players.length; i++) {
players[i].loop();
}
}
void draw_audio() {

if ( out.hasControl(Controller.GAIN) )
{
for (int i = 0; i < players.length; i++) {
players[i].setGain(val[i]);
}
}
}
void stop() {

// the Audioplayers[ you got from Minim.loadFile()
for (int i=0; i< players.length; i++) {
players[i].close();
}
out.close();
// the AudioInput you got from Minim.getLineIn()
//input.close();
minim.stop();

// this calls the stop method that
// you are overriding by defining your own
// it must be called so that your application
// can do all the cleanup it would normally do
super.stop();
}



/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//////// VISUAL FUNCTIONS ////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
void setup_visual(){
rectColorArray = new float[floor(sqrt(totalSquares))][floor(sqrt(totalSquares))][3][2];
for(int x=0; x < sqrt(totalSquares); x++){
for(int y=0; y < sqrt(totalSquares); y++){
rectColorArray[x][y][0][0] = x;
rectColorArray[x][y][1][0] = 1;
rectColorArray[x][y][2][0] = 1;

rectColorArray[x][y][0][1] = 10;
rectColorArray[x][y][1][1] = 10;
rectColorArray[x][y][2][1] = 10;
}
}
}

void draw_visual(){
for(int x = 0; x < sqrt(totalSquares); x++){
for(int y = 0; y < sqrt(totalSquares); y++){

fill(sensorValue[(x*4)+y]);
rect(floor((x * (width/(sqrt(totalSquares))))), floor((y * (height/(sqrt(totalSquares))))), floor((width/(sqrt(totalSquares)))), floor((height/(sqrt(totalSquares)))));
}
}
}

Arduino Code:
int sensorValue[16]; // an array to store the sensor values

// the address pins will go in order from the first one:
#define firstAddressPin 8

int analogInput = 0;

void setup() {
Serial.begin(9600);
// set the output pins:
for (int pinNumber = firstAddressPin; pinNumber < firstAddressPin + 4; pinNumber++) {
pinMode(pinNumber, OUTPUT);
}
}

void loop() {
for (int channelNum = 0; channelNum < 16; channelNum ++) {
// determine the four address pin values from the channelNum:
setChannel(channelNum);

// read the analog input and store it in the value array:
sensorValue[channelNum] = analogRead(analogInput);
//delay(10);
// print the values as a single tab-separated line:
Serial.print(sensorValue[channelNum], DEC);
if(channelNum < 15){
Serial.print(",");
}
}

// print a carriage return at the end of each read of the mux:
Serial.println();
}

void setChannel(int whichChannel) {
for (int bitPosition = 0; bitPosition < 4; bitPosition++) {
// shift value x bits to the right, and mask all but bit 0:
int bitValue = (whichChannel >> bitPosition) & 1;
// set the address pins:
int pinNumber = firstAddressPin + bitPosition;
digitalWrite(pinNumber, bitValue);
}
}

2 comments:

  1. Great post, Matt :)

    I would love to play with something like this.

    ReplyDelete
  2. I have been a herpes carrier for 2 years and I tried every possible means of curing but all of no useful until I saw a health promotion on a herbalist from West Africa who prepares herbal medicines to cure all sorts of diseases including #HSV and many others sickness but look at me today am very much happy and healthy, I'm telling you today don't lose hope keep trying God is with you, If you needs Dr.Chala help contact him on his email dr.chalaherbalhome@gmail.com or you can visit his website on http://drchalaherbalhome.godaddysites.com or https://mywa.link/dr.chalaherbalhome

    ReplyDelete