Moving and sound emitting pair

The goal of this project is to explore how proximity of two objects can be used to modulate the nature of synthesized sound emitted from two objects. The objects are 3-d printed roly-poly shapes, each equipped with am Arduino Uno, Accelerometer, Speakers, and RFID controller, and two RFID transponder stickers. 

Sketches of shapes

Sketches of shapes

Enclosure

IMG_8587.JPG

I decided to make a 3-D model of an irregular oblong shape, reminiscent of an egg, using Rhino software. In creating this shape, I collaborated with Chester Dols, who is a mentor for this project. He taught me how to use Rhino and I admire his aesthetic, which aligns with mine. 

First, I printed the enclosure at 20% to see if it is structurally sound:

IMG_8593.JPG

I then printed it full size (about 5 inches in diameter) and had one succesful print, fillowrd by 4 failed attempts. The only printer that would print these is the .6 nozzle, which was then never free again. I have yet to schedule it and attempt to print the rest of the enclosures full size. Alternatively, I may try to print smaller enclosures in the .6 nozzle Ultimakers. 

IMG_8606.JPG

The components

Large GIF (416x228).gif

I'm using two accelerometers and RFID controllers to modulate the sound that eminates from the two objects. 

Sound

Option 1

I am using Max/MXP to create synth patches, which will be modulated by the serial input from the two accelerometers (via Arduino 101, which has a wifi shield) in the sculptures. The sculptures are roly-poly toy shapes that wobble when nudged - this is what creates the accelerometer values. Max will send the sound output via blue tooth to a bluetooth speakers that rest inside the sculptures themselves. Concern: I am a little worried there ill be lag when using wifi and bluetooth to send data back and fourth from the computer. 

Option 2

Another option that might produce immediate sound upon touch would be to use micro SD cards in an Arduino Uno. I am not sure if i could use the serial values of an accelerometer to modulate pre-recorded sounds. 

Another concern, is that the bluetooth speakers aren't loud enough. I will test this out. May need to get an amplifier. 

Code for Accelerometer 1: MMA_7455

#include <Wire.h>               //Include the Wire library
#include <MMA_7455.h>           //Include the MMA_7455 library

MMA_7455 accel = MMA_7455();    // Make MMA7455 object
int SpeakerOut = 9;
char xVal, yVal, zVal;          // Return value variables


void setup() {
  Serial.begin(9600);           // Use the Serial Monitor window at 9600 baud
  
  // Set the g force sensitivity: 2=2g, 4=4g, 8-8g
  accel.initSensitivity(2);
  
 // Provide oiffset values so that sensor displays 0, 0, 63
 //  (or close to it) when positioned on a flat surface, all pins
 //  facing down
 
 // Update the numbers with your own values from the MMA7455_CalibrateOffset sketch.
  accel.calibrateOffset(0, 0, 0);

  pinMode(SpeakerOut, OUTPUT);
}

void loop() {
 
  // Get the X, Y, anx Z axis values from the device
  xVal = accel.readAxis('x');   // Read X Axis
  yVal = accel.readAxis('y');   // Read Y Axis
  zVal = accel.readAxis('z');   // Read Z Axis
  
  // Display them in the Serial Monitor window.
  Serial.print("X: = ");
  Serial.print(xVal, DEC);
  Serial.print("   Y: = ");
  Serial.print(yVal, DEC);
  Serial.print("   Z: = ");
  Serial.println(zVal, DEC);
  delay(1000);

int frequency2 = map(yVal, -90, 90, 100, 680);


}
 

Code for Accelerometer 2 - ADXL335 - 5V

const int xInput = A3;
const int yInput = A1;
const int zInput = A2;
const int buttonPin = 2;
int SpeakerOut = 9;

// Raw Ranges:
// initialize to mid-range and allow calibration to
// find the minimum and maximum for each axis
int xRawMin = 0;
int xRawMax = 1024 / 2;

int yRawMin = 0;
int yRawMax = 1024 / 2;

int zRawMin = 0;
int zRawMax = 1024 / 2;

// Take multiple samples to reduce noise
const int sampleSize = 10;

void setup()
{
  //analogReference(EXTERNAL);
  Serial.begin(9600);
  pinMode(SpeakerOut, OUTPUT);
}

void loop()
{
  int xRaw = ReadAxis(xInput);
  int yRaw = ReadAxis(yInput);
  int zRaw = ReadAxis(zInput);

  if (digitalRead(buttonPin) == LOW)
  {
    AutoCalibrate(xRaw, yRaw, zRaw);
  }
  else
  {
    //    Serial.print("Raw Ranges: X: ");
    //    Serial.print(xRawMin);
    //    Serial.print("-");
    //    Serial.print(xRawMax);
    //
    //    Serial.print(", Y: ");
    //    Serial.print(yRawMin);
    //    Serial.print("-");
    //    Serial.print(yRawMax);
    //
    //    Serial.print(", Z: ");
    //    Serial.print(zRawMin);
    //    Serial.print("-");
    //    Serial.print(zRawMax);
    //    Serial.println();
    //    Serial.print(xRaw);
    //    Serial.print(", ");
    //    Serial.print(yRaw);
    //    Serial.print(", ");
    //    Serial.print(zRaw);

    // Convert raw values to 'milli-Gs"
    long xScaled = map(xRaw, xRawMin, xRawMax, -1000, 1000);
    long yScaled = map(yRaw, yRawMin, yRawMax, -1000, 1000);
    long zScaled = map(zRaw, zRawMin, zRawMax, -1000, 1000);

    // re-scale to fractional Gs
    float xAccel = xScaled / 1000.0;
    float yAccel = yScaled / 1000.0;
    float zAccel = zScaled / 1000.0;

    //    Serial.print(" :: ");
    //    Serial.print(xAccel);
    //    Serial.print("G, ");
    //    Serial.print(yAccel);
    //    Serial.print("G, ");
    //    Serial.print(zAccel);
    //    Serial.println("G");


    int frequency = 0;
    int frequency2 = 0;
    int frequency3 = 0;

    float totalAccel = 0;

    totalAccel = abs(xAccel) + abs(yAccel) + abs(zAccel);

    //frequency = map(xAccel, 0, 1, 100, 8700);
    frequency = map(xAccel, 0, 3, 100, 700);

    //Serial.println("xAccel: " + String(xAccel));
    Serial.println("totalAccel: " + String(totalAccel));
    //Serial.println("freq: " + String(frequency));


    //    if (xRaw < 350 || xRaw > 610 || yRaw > 600 || yRaw < -430) {


    //dont make a sound when its not moving
    if (totalAccel < 3.3 || totalAccel > 3.5) {
      tone(SpeakerOut, frequency);
      delay(10);
    }
    else {
      //mute it
      noTone(SpeakerOut);
      delay(10);
    }

  }
}


//end if


// Read "sampleSize" samples and report the average
//
int ReadAxis(int axisPin)
{
  long reading = 0;
  analogRead(axisPin);
  delay(1);
  for (int i = 0; i < sampleSize; i++)
  {
    reading += analogRead(axisPin);
  }
  return reading / sampleSize;
}

//
// Find the extreme raw readings from each axis
//

void AutoCalibrate(int xRaw, int yRaw, int zRaw)
{
  Serial.println("Calibrate");
  if (xRaw < xRawMin)
  {
    xRawMin = xRaw;
  }
  if (xRaw > xRawMax)
  {
    xRawMax = xRaw;
  }

  if (yRaw < yRawMin)
  {
    yRawMin = yRaw;
  }
  if (yRaw > yRawMax)

  {
    yRawMax = yRaw;
  }

  if (zRaw < zRawMin)
  {
    zRawMin = zRaw;
  }
  if (zRaw > zRawMax)
  {
    zRawMax = zRaw;
  }
}

Meta Mounds: p5js and three force sensitive resistor buttons.

In this project I used an clay shape of a wave, serving as a sort of enclosure. On the three "waves" I placed three sensors. The sensors all work, but I am still trying to figure out how to parse the values and assign them to three different functions. So far, the theta of the wave is controlled by the sensors (all of them) and the vertical height is controlled by the mouse y position.

Next steps: I hope to use another sensor for controlling the amplitude of the wave and using the third sensor to change the background color of the canvas.

Link to the working code, which uses x and y mouse values instead of input so that one can play with this without hooking up an Arduino. 

Large GIF (740x444).gif
Large GIF (528x442).gif
Large GIF (816x440).gif

Below is a previous attempt to create this, along with the code I used to make the animation above. 

 

Large GIF (420x468).gif

The goal of this project was to use arrays and a constructor function to generate cleaner, compartmentalized code. I am using a shape I made (a clay model of an abstract shape that has curves, sort of reminiscent of a cartoony mountain range) and recreating it's shape using arcs. The display function uses the position of x and y (which are set to random) to place the "portrait" or linear representations of the clay shape onto the canvas.  Here is the link to the code to the P5JS editor. 

Questions

1. I am not sure how to make a step repeat pattern. It must be easy but so far I have only been able to generate linear repetitions, not evenly spread out wallpaper-like repetitions. I actually prefer the randomization, but was just curious to try a more orderly step-repeat approach. 

2. I would like to superimpose this wave over the patterns so that they block the top if the screen with the sine wave motion but I cannot get the two sets of code to coexist in one file. When i try to merge the code i get the following error: 

Uncaught TypeError: Cannot read property 'length' of undefined (sketch: line 96)

This is the code

 

Next Steps

The next step of this project is to use serial connection the pressure sensors on the clay shape and manipulate the amplitude, width, and speed of the wave. 

Code (with Errors)


var xspacing = 12;    // Distance between each horizontal location
var w;                // Width of entire wave
var theta = 0;      // Start angle at 0
var amplitude = 75.0; // Height of wave
var period = 400.0;   // How many pixels before the wave repeats
var dx;               // Value for incrementing x
var yvalues;  // Using an array to store height values for the wave

var sensor1;
var sensor2;
var inData;


function setup() {
  createCanvas(710, 400);
 
  w = width+12;
  dx = (TWO_PI / period) * xspacing;
  // dx =1;
  yvalues = new Array(floor(w/xspacing)); 
  // print(dx);

}

//end of setup

function draw() {
  //background(344, 54, 23);
   background(22, 22, 243);

 calcWave();
 renderWave();
  sensor1 = map(inData, 0, width, 0, 5);
 // sensor2 = map(mouseY, 0, height, 1, 3);
}


function calcWave() {
  // Increment theta (try different values for
  // 'angular velocity' here)
  
  theta += 0.02;

  // For every x value, calculate a y value with sine function
  var x = theta;
   
  for (var i = 0; i < yvalues.length; i++) {
    yvalues[i] = sensor2*sin(x * sensor1) * amplitude ;
    x+=dx;
  }
}

// for incoming serial data

function setup() {
  createCanvas(500, 300);
  colorMode(HSB,255,255,255);
  serial = new p5.SerialPort();       // make a new instance of the serialport library
  serial.on('list', printList);  // set a callback function for the serialport list event
  serial.on('connected', serverConnected); // callback for connecting to the server
  serial.on('open', portOpen);        // callback for the port opening
  serial.on('data', serialEvent);     // callback for when new data arrives
  serial.on('error', serialError);    // callback for errors
  serial.on('close', portClose);      // callback for the port closing
 
  serial.list();                      // list the serial ports
  serial.open(portName);              // open a serial port
circlecolor = color(inData, 200, 200);
  
  
  w = width+12;
  dx = (TWO_PI / period) * xspacing;
  // dx =1;
  yvalues = new Array(floor(w/xspacing)); 
  // print(dx);

  
}

function renderWave() {
  noStroke();
  fill(255);
  // A simple way to draw the wave with an ellipse at each location
  

  for (var x = 0; x < yvalues.length; x++) {
    ellipse(x*xspacing, height/105+yvalues[x], 10, -390);
  }
}
 

CODE THAT DOES WORK (but only maps to one sensor)


var xspacing = 12;    // Distance between each horizontal location
var w;                // Width of entire wave
var theta = 0;      // Start angle at 0
var amplitude = 75.0; // Height of wave
var period = 400.0;   // How many pixels before the wave repeats
var dx;               // Value for incrementing x
var yvalues;  // Using an array to store height values for the wave

var sensor1;
var sensor2;


function setup() {
  createCanvas(710, 400);
 
  w = width+12;
  dx = (TWO_PI / period) * xspacing;
  // dx =1;
  yvalues = new Array(floor(w/xspacing)); 
  // print(dx);

}

//end of setup

function draw() {
  //background(344, 54, 23);
   background(22, 22, 243);

 calcWave();
 renderWave();
  sensor1 = map(mouseX, 0, width, 0, 5);
  sensor2 = map(mouseY, 0, height, 1, 3);
}


function calcWave() {
  // Increment theta (try different values for
  // 'angular velocity' here)
  
  theta += 0.02;

  // For every x value, calculate a y value with sine function
  var x = theta;
   
  for (var i = 0; i < yvalues.length; i++) {
    yvalues[i] = sensor2*sin(x * sensor1) * amplitude ;
    x+=dx;
  }
}

function renderWave() {
  noStroke();
  fill(255);
  // A simple way to draw the wave with an ellipse at each location
  

  for (var x = 0; x < yvalues.length; x++) {
    ellipse(x*xspacing, height/105+yvalues[x], 10, -390);
  }
}
 

Sound sculpture prototype with Arduino and accelerometer

 

Part 1.  10/2/17.

Using tape and plaster is not ideal. My next steps are: making smooth, sandable sculptures using styrofoam and clay, then casting them in a foam resin that will allow for sound to travel from inside the enclosure. 

 

 

 

Part 2. Update. 10/9/17.

I made a roly-poly enclosure so that it can move and make music on it's own when pushed. I used plaster to create a heavy center of mass on the bottom.

 

I am happy with the fact that the rolly polly effect is working. The rolling could be smoother and the shell more polished. I have yet to try 3d printing and resin casting for these shapes. Questions remain:

1. What's the best way to fasten the Arduno inside the shape? 

2. How do I make it so that the Arduino turns off on it's own when the shape isn't moving - do i have to use a button or can it shut off and on by movement activation? Perhaps a touch sensor can act as a button.

I think the easiest way to make an enclosure that can open and close easily is to download a 3d printable container with a screw lid, then modify the top of the lid and body of the jar using Blender. The result would be a shape that opens and closes without a noticeable, distracting latch. 

 

Sound

For the first pass I'm happy with the synth sound. For the next iteration, I'd like to try to use the Mozzi library to create some more variation of sound and manipulate the relationship between current and sound mapping so that it's not mapped linearly. Perhaps some unexpected inverse relationship can be explored. 

 

Code

I found a library in the documentation that came with my accelerometer and used it in my own code, which used the variables that the accelerometer produced to manipulate the frequency of sound synthesized by the speaker. 

 

#include <Wire.h>               //Include the Wire library
#include <MMA_7455.h>           //Include the MMA_7455 library

MMA_7455 accel = MMA_7455();    // Make MMA7455 object
int SpeakerOut = 9;
char xVal, yVal, zVal;          // Return value variables


void setup() {
  Serial.begin(9600);           // Use the Serial Monitor window at 9600 baud
  
  // Set the g force sensitivity: 2=2g, 4=4g, 8-8g
  accel.initSensitivity(2);
  
 // Provide oiffset values so that sensor displays 0, 0, 63
 //  (or close to it) when positioned on a flat surface, all pins
 //  facing down
 
 // Update the numbers with your own values from the MMA7455_CalibrateOffset sketch.
  accel.calibrateOffset(0, 0, 0);

  pinMode(SpeakerOut, OUTPUT);
}

void loop() {
 
  // Get the X, Y, anx Z axis values from the device
  xVal = accel.readAxis('x');   // Read X Axis
  yVal = accel.readAxis('y');   // Read Y Axis
  zVal = accel.readAxis('z');   // Read Z Axis
  
  // Display them in the Serial Monitor window.
  Serial.print("X: = ");
  Serial.print(xVal, DEC);
  Serial.print("   Y: = ");
  Serial.print(yVal, DEC);
  Serial.print("   Z: = ");
  Serial.println(zVal, DEC);
  delay(1000);

int frequency2 = map(yVal, -90, 90, 100, 680);


}

   
   

Analog Input

Lab Exercise 1

For this Lab exercise, I set up my Arduino to read and print out the voltage readings of a switch, a potentiometer, and a photocell.   

switch_sm.gif
lightsensor_sm.gif

Code:

 

void setup() {
  // ppin mode
  pinMode(8, INPUT); //set switch's pin 8 to be input
  Serial.begin(9600); //initialize serial communications
  
  

}

void loop() {
  int SwitchState = digitalRead(8); //read the switch
  int potState = analogRead(A0); // Read the potentiometer
  // you should pause for a a millisecond b/w two analog reads. 
  //Turns out that arduino has only one to analog converter so can only do 2 at a time
  //so you need to reset it using this bit of time, this helps get a reliable read on the second analog read
 
  delay(1);  
  int photoCellState = analogRead(A1); // read the photocell

  //print them all out
  Serial.print("switch: ");
 
  Serial.print(SwitchState);
      Serial.print("\t"); //print a tab
  
  
  Serial.print("potState: ");
  Serial.print(potState);
      Serial.print("\t"); //print a tab
  
  Serial.print("photoCellState: ");
  Serial.println(photoCellState); //like enter return when typing
    


}

Lab Exercise 2

After completing lab exercise 2 - using digital or analog input and digital output, I came up with an application: The pressure sensor served as a weighing mechanism for objects I had around. The analog input was the weight of the objects and the digital output was the strings of words written by the Serial print monitor that corresponded to the weight range I assigned. I used an "if / else" statement for this.

if (lightness < 3)
{
Serial.println("Try a heavier one");
   Serial.print("\t"); 
 
}
else  {
  Serial.println("YOU DID IT");

REINTERPRETED

How to document, keep records, and give credit

I don't have a formula for this myself yet, but documenting and giving credit is gong to be an important part of making work at ITP and beyond.  After reading ON THE RIGHTS OF MOLOTOV MAN Appropriation and the art of context By Joy Garnett and Susan Meiselas, a painter and a photographer whose work the painter referenced, this practice feels even more important. 

When a collage artist pulls an image out of an old magazine, is the image free to use as a building block of creating new meaning? Was Romare Bearden supposed to keep track of every source he used? Does it depend on how much he distorted the original image? If a photograph is highly abstracted and only parts of it are used, one may think that perhaps giving credit to every photographer of every newspaper clipping is superfluous. In reality, we see that it's better to keep a record just in case. The Romare Bearden of today ought to be more diligent in keeping records and adding disclaimers that the referenced material is taken out of context, severed from it's previous meaning, and should be reinterpreted in the new ecosystem the artist created.

If it becomes important to borrow not just the form (visual element) of the clipping (or bitmap) but also the original meaning it carries, the artist is required to research the subject of the photo in order to explain the context accurately in the artist statement or wall text.

 

170-025.jpg

One foot moving into the future: A MEDITATIVE WALK

 

"One step after another, one foot moving into the future and one in the past. Did you ever think about that? Our bodies are caught in the middle. The hard part is staying in the present. Really being here."

 

While I am a fan of Janet Cardiff's work, I have to admit I was initially a bit underwhelmed with Her Long Black Hair audio tour. Towards the end, I gained an appreciation for what she created.   

 

First off, I found it hard to follow where she walked. I was amused at how casually she took 35 minutes of my time with orders of going this way and that, telling me to wet my finger and put it on my cheek and having me listen to her conversation with her husband when he interrupted the walk. It irked me that I had to follow her commands, though i took it with a sense of humor. 

 

Another issue I came across at the walk was that the reality she saw did not match closely with mine. Maybe sometime needs to pass and it would be interesting to revisit this when we live in a time quite different from 2004 or 2017. That said, I also found it thrilling to hear a noise and wonder if it's happening to me or to her. I often had to take my headphones off to check. That was an interesting way to mix the loud realities of Manhattan in 2004 and Manhattan in 2017. 

 

What made this piece enjoyable, despite the setbacks, was the juxtaposition of her meditative stream of consciousness (some of which I found insightful) and the beautiful musical addictions along with a poignant narration of a slave telling his  "walk" story -  running away from slave-owners and getting caught. What I think she is doing is getting us in a mindful state and introducing bits of what she finds worth listening to or worth thinking about. I did feel that being primed with a meditative exercise helped me pay closer attention to the nuances of those stories and sounds.

 

It is believed that meditation increases empathy and I felt this idea may have been playing a role in this work. When Cardiff says "One step after another, one foot moving into the future and one in the past... Our bodies are caught in the middle. The hard part is staying in the present. Really being here." she's inviting us to be present, to see and hear what's there in front of us, even if we don't see exactly what she is seeing in her moment. 

 

photo_cardiff_04_view1_321x244w.jpg

Sound Walk

This sound walk composition Elevator Chaos is a collaborative audio project that my team and I recorded and edited together at NYU's ITP program. The recording is of a trip we took from the 12th to the 4th floor of the Tisch School of the Arts, the building where ITP classes are situated. This project is inspired by Janet Cardiff's audio walk of Central Park called "Her Long Black Hair."

Image courtesy of Google's reusable image archive

Image courtesy of Google's reusable image archive