Showing posts with label arduino. Show all posts
Showing posts with label arduino. Show all posts

Monday, October 12, 2009

Foot Sensors for Longboarding Data

This week the goal was to make our data logging devises mobile if not wearable. I was unable to become fully detached from my computer for the data logging. However, I was able to make it mobile by using a small netbook to log the data, and keep it stored in my backpack while I went for a nice ride around Washington Square Park. The values were sent from the Arduino via serial communication, and Processing listened for the values and wrote them to a CSV(comma separated values) file. Next, I stuck the file into a program written by Dan O'Sullivan that graphs that data and allows the viewer to scroll through the data. If you look closely, you will see that my right foot makes more jumps than my left foot. This is because I push my longboard with my right foot :) Moving forward, I would like to find a better sensor for a more stable and wider range values. I found that the FSRs that I used were almost maxed out even when standing.

Friday, October 9, 2009

Depth Time: adventures in finger painting

Sue Syn and I collaborated on a project for Dan O'Sullivan's "The Rest of You" class, in which we wore ultra sonic range finders on our wrists while we painted with our hands. The values that were recorded from the sensors were then used to render information that was captured from a camera that was recording our movements. Both the actual footage and the data augmented video were displayed together. The result is a time lapse record of our movements and color choices, allowing the user to watch the painting develop and time pass. The idea was to make the artist and viewer aware of spatial relationships that are not considered important or taken for granted. The hope being that a greater understanding of one's subconscious might come to light. While I was pleased with the result, I have been making strides toward a better mapping of the depth data than just value. The next iteration of this idea will have the painting pushed and pulled in 3D space based on the values from the range finder.

Depth Time from Matt Richard on Vimeo.

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);
}
}

Saturday, December 6, 2008

Sensor Dome comes alive!!!!

I am proud to say that the Sensor Dome is up and running. Eyal Ohana and I were able to get both parts(audio and visual) to work seperately. Tomorrow we will get them to work together and build the structure that will house the light tile and the Sensor Dome. I uploaded two videos showing it working. I will add some pictures of the guts tomorrow.

Oh yeah, I almost forgot! We are using a multiplexer to allow for 16 photocells in analog input.


Sensor Dome - Light Tile Test from Matt Richard on Vimeo.


Sensor Dome - Sound Test from Matt Richard on Vimeo.

Saturday, November 22, 2008

Robotic arm drawing machine

For our mid-term project in Physical Computing, Jim Lamiell, Kristen Loeb and I created a drawing machine using two servo motors and a little bit of inverse kinematics. We set out to draw a straight line using with a contraption in mind that would mimic a simplified human arm.

The first servo acts like the shoulder and is connected to an arm with another servo at the end that acts like an elbow. The second servo has is connected to another arm with a marker on the end that acts like the hand.

The trick is to tell the servos what angle to go to based on the position of the marker(mouse). This can be done using the law of cosines and inverse kinematics.

We were able to make it draw, but not a straight line. I remade the arms using a CAD program to make it much more precise. I will post another video when it is finished.


PComp Midterm: Drawing Machine from James Lamiell on Vimeo.

Tuesday, October 21, 2008

Inverse Kinematics and Processing



Basic inverse kinematics code rewritten for processing from Keith Peters of bit-101. The idea is to replicate the motion of your shoulder, upper arm, elbow, lower arm, and hand in two dimensions. The angular value of the "shoulder" and "elbow" will be written to corresponding servo motors that are being controlled by Arduino.

Here is the code:

int sx,sy,ex,ey,hx,hy;
int armLength,ua,la;
float uad, lad;
void setup(){
size(500,500);
background(255, 224, 150);
sx = width/2;
sy = height/2;
armLength = int(width/5);
}

void draw(){
fill(255);
rect(0,0,width,height);
upperArm();
}

void upperArm(){
int dx = mouseX - sx;
int dy = mouseY - sy;
float distance = sqrt(dx*dx+dy*dy);

int a = armLength;
int b = armLength;
float c = min(distance, a + b);

float B = acos((b*b-a*a-c*c)/(-2*a*c));
float C = acos((c*c-a*a-b*b)/(-2*a*b));

float D = atan2(dy,dx);
float E = D + B + PI + C;

ex = int((cos(E) * a)) + sx;
ey = int((sin(E) * a)) + sy;
print("UpperArm Angle= "+degrees(E)+" ");

hx = int((cos(D+B) * b)) + ex;
hy = int((sin(D+B) * b)) + ey;
println("LowerArm Angle= "+degrees((D+B)));

stroke(255,0,0,100);
fill(240,0,0,200);
ellipse(sx,sy,10,10);
ellipse(ex,ey,8,8);
ellipse(hx,hy,6,6);
stroke(0);
line(sx,sy,ex,ey);
line(ex,ey,hx,hy);
}

Multi-Value Serial Communication

I want to thank Meredith for writing this post. I merely changed my name to her's.

I worked with Meredith Hasson on the serial communication lab for this week. We followed the lab instructions and did the first basic serial circuit using a flex sensor, a photo cell and a switch. We were able to get it working and thus, began to play with moving the ball around the screen.



We then changed both the Arduino and Processing code up a bit and went for snow. We made the background color change based on how much light the photocell was receiving. When it was getting lots of light, it would be a light background and when it was not receiving any light, it was a black background. The white balls were moving around based off of random numbers, but we utilized the flex sensor to decide how many balls would be present. When bent one way there were lots of balls and when bent the other there were fewer balls.



Here is our code:

Arduino:

int analogOne = 0; // analog input
int analogTwo = 1; // analog input
int digitalOne = 2; // digital input

int sensorValue = 0; // reading from the sensor

void setup() {
// configure the serial connection:
Serial.begin(9600);
// configure the digital input:
pinMode(digitalOne, INPUT);
}

void loop() {
// read the sensor:
sensorValue = analogRead(analogOne);
// print the results:
Serial.print(sensorValue, DEC);
Serial.print(”,”);

// read the sensor:
sensorValue = analogRead(analogTwo);
// print the results:
Serial.print(sensorValue, DEC);
Serial.print(”,”);

// read the sensor:
sensorValue = digitalRead(digitalOne);
// print the last sensor value with a println() so that
// each set of four readings prints on a line by itself:
Serial.println(sensorValue, DEC);
}

Processing:

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

float bgcolor; // Background color
float fgcolor; // Fill color
float xpos, ypos; // Starting position of the ball

void setup() {
size(640,480);
myPort = new Serial(this, Serial.list()[2], 9600);

// read bytes into a buffer until you get a linefeed (ASCII 10):
myPort.bufferUntil(’\n’);
}

void draw() {
//background(xpos);
fill(xpos, 50);
rect(0, 0, width, height);
fill(fgcolor);
// Draw the shape
for(int i = 0; i <= ypos; i++){
// ellipse(i*10, height/2, 10, 10);
ellipse(random(width), random(height), 10, 10);
}
}

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

void serialEvent(Serial myPort) {
// 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("Sensor " + sensorNum + ": " + sensors[sensorNum] + "\t");
}
// add a linefeed after all the sensor values are printed:
println();
if (sensors.length > 1) {
xpos = map(sensors[0], 190,900,1,255);
ypos = map(sensors[1], 220,540,1,200);
fgcolor = sensors[2] * 255;
}
}
}

Tuesday, September 30, 2008

Jealous Boyfriend with servo technology

Meredith and I worked together on our Physical Computing homework and created a gem. Our task was create something using a servo motor. I knew that I wanted to attach a rigid arm to the motor. After playing with the setup we stumbled upon a funny little thing.

Enjoy :)


The Jealous Boyfriend with servo technology from Matt Richard on Vimeo.

Tuesday, September 16, 2008

Physical Computing Week 2 Homework

For week two I had to use a sensor(analog in) to send information to the Arduino that then used the data to regulate something else. In my case I used 3 potentiometers that controlled blue, green and red LEDs.

I wanted to create a way to make many different colors. I put the LEDs inside of a cube of foamcore with a paper window. Watch the videos to see how it went.


With the lights on so you can see the components.


Color Maker in the light from Matt Richard on Vimeo.


With the lights off so you can see it work.


Color Maker in the dark from Matt Richard on Vimeo.

Thursday, September 11, 2008

Fixing Physical Computing Homework

Thanks Kevin it seems to work :)

My brother Kevin, who lives in Florida and works as a Flash developer, had an idea about how to fix my code. He sent me a snippet of the void loop() section and I swapped it in and then rearranged the variables.

His idea was to check the switchState on every iteration of the for loop. Since switchState would only return 0 or 1(no or yes), he added the value of switchState to the lower of the two LED pins(pin 3) which were in pins 3 and 4.

Code snippet:
void loop() {
for (int i=10; i >= 1; i--){
// read the switch input at the beginning of
// each loop iteration
switchState = digitalRead(switchPin);
digitalWrite((ledPin + switchState), HIGH);
delay(i*(i*10));
digitalWrite((ledPin + switchState), LOW);
delay(i*(i*10));
}

Here is a video:


Physical Computing Week 1 Homework FIXED from Matt Richard on Vimeo.

Tuesday, September 9, 2008

Physical Computing Week 1 Homework

I finally got my Arduino Diecimila to work on my computer. I was really excited about programming in Arduino. It seemed like such a simple language that I just wanted to dive in and play around a bit.

I played with for loops allowing the LEDs to blink at either an exponentially increasing or decreasing amount. The LED that turns on depends on the position of a switch, whether it is open or closed. Here is my code:

// declare variables:
int switchPin = 2; // digital input pin for a switch
int yellowLedPin = 3; // digital output pin for an LED
int redLedPin = 4; // digital output pin for an LED
int switchState = 0; // the state of the switch

void setup() {
pinMode(switchPin, INPUT); // set the switch pin to be an input
pinMode(yellowLedPin, OUTPUT); // set the yellow LED pin to be an output
pinMode(redLedPin, OUTPUT); // set the red LED pin to be an output
}

void loop() {
switchState = digitalRead(switchPin); // read the switch input:

if (switchState == 1) // if the switch is closed:
for (int i=10; i >= 1; i--){
digitalWrite(yellowLedPin, HIGH); // turn on the yellow LED
delay(i*(i*10));
digitalWrite(yellowLedPin, LOW); // turn off the yellow LED
delay(i*(i*10));
}
digitalWrite(redLedPin, LOW); // turn off the red LED
}
else if (switchState == 0){ // if the switch is open:
for (int i=1; i <= 10; i++){
digitalWrite(redLedPin, HIGH); // turn on the red LED
delay(i*(i*10));
digitalWrite(redLedPin, LOW); // turn off the red LED
delay(i*(i*10));
}
digitalWrite(yellowLedPin, LOW); // turn off the yellow LED
}
}
Here is a video:


The LEDs blinked the way I wanted them to, but the switch wouldn't change the lit LED until after the currently lit one was finished its for loop. I tried adding an if statement with a break to get the for loop to stop, but it didn't work.