THIS OR THAT

 

IMG_0255

Inspired conceptually by websites like Kitten War and classic games like “Would You Rather?” and technically by projects like Post-Circuit Board by the Graffiti Research Lab, This or That is an electronic voting poster that allows passersby to vote on two different options as chosen by other strangers.

IMG_0242

The poster consists of a voting button and seven-segment display on each side, as well as a reset button, all of which are controlled by a single ATTiny84. There are no wires on the poster besides the alligator clips connecting to the power–all the traces were made with copper tape.

While we are becoming more interconnected digital, electronics are becoming more and more personal–our laptops and cellphones are not devices that are meant to be shared physically, and we even get physically anxious when they’re out of our reach for too long. This or That is a “public” electronic, its charm and fun comes from its communal usage.

Screen Shot 2013-11-18 at 9.45.17 PMOlder iteration (I’ve since learned the art of making pretty traces!).

IMG_0254

At one point I traded my coin cell battery in for a sweet LiPo battery that someone had lying around.
chargin’ a poster whaaat

Code & Circuits

DIAGRAM:

I have a .ai file that needs cleaning that has both the poster text + lightly drawn traces that you can use to create a poster for your own, so bear with me! 🙂 Here’s a Fritzing diagram for now:

poster_bb

MATERIALS:

LIBRARIES:

TinyLEDBackpack
TinyWireM

ARDUINO CODE:

MIT Media Lab’s High Low Tech group has a fantastic tutorial on programming ATtinies. For reference, on an ATtiny84:

  • Physical Pin 9 –> SCK
  • Physical Pin 8 –> MISO
  • Physical Pin 7 –> MOSI
  • Physical Pin 5 –> RESET

My code below has a diagram included, and each physical pin number has been labelled:

#include 
#include <tiny_ledbackpack .h>

/*
                           -------
                       +  | 1  14 | -
LEFT VOTE BUTTON [PIN 10] | 2  13 | RESET BUTTON [PIN 0]
                          | 3  12 | RIGHT VOTE BUTTON [PIN 1]
                          | 4  11 | 
                          | 5  10 |
                          | 6   9 | SCLOCK
                    SDATA | 7   8 | 
                           -------
*/

Tiny_7segment lMatrix = Tiny_7segment();
Tiny_7segment rMatrix = Tiny_7segment();

int lCounter = 0;
int rCounter = 0;
const int lButton = 10;
const int rButton = 2  ;
const int rstButton = 0;
boolean rBoo = false;
boolean lBoo = false;

void setup() {  
  lMatrix.begin(0x70);
  rMatrix.begin(0x71);
}

void loop() {
  if (digitalRead(lButton) == LOW) {
    lBoo = true;
  } 
  else if ((digitalRead(lButton) == HIGH) && (lBoo == true)) {
    lCounter += 1;
    lBoo = false;
  }

  if (digitalRead(rButton) == LOW) {
    rBoo = true;
  } 
  else if ((digitalRead(rButton) == HIGH) && (rBoo == true)) {
    rCounter += 1;
    rBoo = false;
  }

  if (digitalRead(rstButton) == LOW) {
    lCounter = 0;
    rCounter = 0;
  }

a    lCounter = 0;
  } else if (rCounter == 9999) {
    rCounter = 0;
  }
  lMatrix.println(lCounter);
  rMatrix.println(rCounter);
  lMatrix.writeDisplay();
  rMatrix.writeDisplay();
  delay(10);
}

If you have any questions regarding construction, feel free to email me at maddyvarner (at) gmail (dot) com (preferably with the subject line “This or That”).

Maddy-Looking Outwards + Sketches

LOOKING OUTWARDS

01. Elektrobiblioteka / Electrolibrary

An electronic book! The video makes the creation process look so INTENSE and DRAMATIC, look at the those arduino code closeups, wow, computers. This was somewhat disappointing in that the book was mainly used as just an HID for the actual program, which was on a computer. I’d love to see a book that is wireless + interactive. (another book spinoff is this circuit sketchbook)

02. Input / Output Paper

More of a tech demonstration than an art piece, input/output paper is a set of two sheets of paper. Fold one and the other mimics its movements. The actuated paper can be made to move, like a tiny paper creature. Adorable! I find memory wire really fascinating and would love to play with that + paper (which is such a flexible medium).

03. Sticker Circuits

This recently launched project on Crowd Supply is a toolkit of stickers that are conductive and can be used as part of electronics projects on non-traditional surfaces like paper, fabric, and even your wall! I know people have been making snap-together electronics kits for a while in a variety of forms, but I think that this more crafts-oriented approach to electronics is more engaging for people who may not be interested in electronics otherwise or find them unapproachable. I like the idea of creating tools with a pedagogical purpose.

IDEAS

01. Origami Robots

112mvarner004

I’d like to use muscle wire and small microcontrollers to create self-sustaining origami robots that wander around. I would connect the wire from the bottom of each leg to a point above on the body/head that would create a right angle so I could have each leg “shuffle” forward based on the shrinking/expansion of the wire. I’d like to add simple sensors like a light sensor to enable line following or some sort of other navigation. For microcontrollers I’d use one of the ATtinys for lightweight control, and for power I’d either use a really light battery (think 3V coin cell) or a larger battery that has longer wires (so the creature is tethered but free to move about).

02. Circuit Graffiti Cookbook

112mvarner003

A short book that details techniques and schematics for sticker circuits. I’d like to embed a battery in the back cover of the book and actually have demonstrations for things within the book. I could have a internet complement to it which could allow me to upload sketches/schematic files so people could then download them and use them to their own advantage.

bonus. SpaceTime Radio

I’ve been to a couple of artist talks on sound art in the recent past and i’m really fascinated by this genre of soundwalks, where you walk around with a device and it plays sounds based on your GPS location. I think it would be interesting to create a radio (I say radio because I’ve been manufacturing various radio design for a concept studio project, my life is currently fake radios and coding) that only plays when it’s placed in a certain location at a certain time. I’m fascinated with the idea of ritual and cargo cult, esp. in a modern era where there’s often very little understanding of objects we depend on every day (e.g. our cellphones!). The radio would be paired with either vague or nonexistent instructions for spacetime placement, forcing the user to wander and rely on the radio itself for knowledge.

THIS OR THAT?

Screen Shot 2013-11-18 at 9.45.17 PM

Recently, Microsoft Research presented their first paper on a project they’ve been working on where they are developing electrical components that are also stickers. The idea of sticky circuits is not new–Graffiti Research Lab was creating circuit boards out of mail postage in 2006, but while wearable computing has become immensely popular over the past few years, paper-based computing has not gained similar traction. Fascinated by this weird cousin of wearables, I tried my hand at a postage circuit board, using an ATtiny45 and some conductive tape:

I stuck it in a random elevator near ArtFab and it lasted a couple of hours.  Then, around Halloween, I actually ended up making a joke “ghost meter” that detected the amount of spirits haunting a person and put it in one of the women’s bathroom stalls.

I really liked the idea of “physical apps”–cheap little programs (with varying degrees of usefulness and playfulness) that someone can stick or hang up on a wall for strangers to engage and play with. “Would You Rather” is a game where someone gives a group two (often terrible/gross) situations and the group is forced to vote for one or the other. This game has been turned into multiple apps and internet sites like Kitten War seem to draw inspiration from it. “This Or That” is an electronic poster constructive out of conductive tape, an ATtiny84, and two seven-segment displays that gives passerby a pseudo-anonymous platform to vote on one of two options (which they can also decide on!). While most people were honest in their votes, some people “stuffed the ballot” so to speak–this is probably not going to replace the ballot boxes during the 2016 presidential election, but it’s a fun diversion.

http://www.youtube.com/watch?v=9q_88BjcTKA

Ultimately, the choice is yours.

Screen Shot 2013-11-18 at 9.44.43 PM

poster_bb

#include 
#include 

Tiny_7segment lMatrix = Tiny_7segment();
Tiny_7segment rMatrix = Tiny_7segment();

int lCounter = 0;
int rCounter = 0;
const int lButton = 2;
const int rButton = 3;
const int rstButton = 5;
boolean rBoo = false;
boolean lBoo = false;

void setup() {  
  lMatrix.begin(0x70);
  rMatrix.begin(0x71);
}

void loop() {
  if (digitalRead(lButton) == LOW) {
    lBoo = true;
  } 
  else if ((digitalRead(lButton) == HIGH) && (lBoo == true)) {
    lCounter += 1;
    lBoo = false;
  }

  if (digitalRead(rButton) == LOW) {
    rBoo = true;
  } 
  else if ((digitalRead(rButton) == HIGH) && (rBoo == true)) {
    rCounter += 1;
    rBoo = false;
  }

  if (digitalRead(rstButton) == LOW) {
    lCounter = 0;
    rCounter = 0;
  }
  
  if (lCounter == 9999) {
    lCounter = 0;
  } else if (rCounter == 9999) {
    rCounter = 0;
  }
  lMatrix.println(lCounter);
  rMatrix.println(rCounter);
  lMatrix.writeDisplay();
  rMatrix.writeDisplay();
  delay(10);
}

Maddy Looking Outwards – Arduino Shields

Wave Shield Kit & Etc.

The Adafruit Wave Shield simplifies the thought process behind hardware projects with audio by give you a nice shield with all the necessary components. Useful for making lots of noise! I don’t know much about sound or music, but I always find myself enjoying sonic art/projects that incorporate sound. I think it adds an extra dimension to any project and I’d love to use this in a piece.

Gameduino Shield

This has plugs for a VGA monitor and stereo speakers, and you can use it for creating “old-school” video games. Using an rPi or an Udoo would probably be easier, but it’s amazing that you can even get interactive graphics using an Arduino.

Touch Shield

It’s a fully assembled touch shield, you can use it to draw LOTS OF THINGS and it even takes pressure! Wow! I’d love to see this used as some sort of interface, like a way to design a robot’s walk path before executing.

Adafruit Window Shopping

RGB Color Sensor with IR Filter

Color sensor! This can actually detect color, what? Becky Stern has a really awesome chameleon scarf tutorial on their tutorial site, this would be great for other computational fashion pieces. This would also be pretty cool for sorting/computer vision type things.

Magstripe Reader

Card readers! These look pretty fantastic, oh wow. I could see myself using these for like, a visualization of $$$ or an installation that requires users to give me money. I’ve never really messed around with card readers before though, and I’m sort of interested in seeing what kind of information is stored in the cards I carry with me daily?

Touch Screen (Nintendo DS)

When I was in middle school/early high school I was fascinated by DIY multitouch tables. I’m really surprised and pleased that Adafruit sells tiny touch screens for only $8! I’d love to make a tiny touch interface with something like this.

Penny Door

There’s a little door in Doherty that can only be opened with the use of a coin. Coins clank off the sides of the door and each other, giving passerbys hints as to how to get in. Originally, I wanted to do a double projection that had glowing particles slipping in and out of the door, but that would’ve required multiple projectors + connecting multiple sketches together via osc, and I didn’t have the time to work it all out. I ended up having projection issues anyways–the projector I was using was too small and too weak to project onto the space!

I’d love to do more projection mapping work, perhaps next time with a little pico projector + RPi combo. I found it’s ridiculously difficult to line up the projectors, even with Keystone–I’d like to try my hand at computer vision next time.

import ddf.minim.spi.*;
import ddf.minim.signals.*;
import ddf.minim.*;
import ddf.minim.analysis.*;
import ddf.minim.ugens.*;
import ddf.minim.effects.*;

import pbox2d.*;
import org.jbox2d.collision.shapes.*;
import org.jbox2d.common.*;
import org.jbox2d.dynamics.*;
import org.jbox2d.dynamics.contacts.*;
import org.jbox2d.dynamics.joints.*;
import org.jbox2d.collision.shapes.Shape;



PImage penny;

Minim minim;
AudioSample clang;
AudioSample bigClang;

//door size
float door = 60.5 * 5 * 1.5;
float lastHit;
boolean caliDoor;

//box2D world
PBox2D box2d;

//stuff
ArrayList movers;
Boundary[] walls = new Boundary[4];

import deadpixel.keystone.*;
Keystone ks;
CornerPinSurface surface;
PGraphics offscreen;

void setup() {
  size(640*2, 360*2, P3D);
  ks = new Keystone(this);
  surface = ks.createCornerPinSurface(int(640*1.5), int(360*1.5), 20);
  offscreen = createGraphics(int(640*1.5), int(360*1.5), P3D);
  smooth();

  // http://en.wikipedia.org/wiki/Penny_(United_States_coin)
  penny = loadImage("2010_cent_obverse.png"); 

  minim = new Minim(this);
  // http://www.freesound.org/people/timgormly/sounds/170958/
  clang = minim.loadSample("clang.wav", 512);
  // http://www.freesound.org/people/DJ%20Chronos/sounds/123587/
  bigClang = minim.loadSample("loud_clang.aiff", 512);


  box2d = new PBox2D(this);
  box2d.createWorld();
  box2d.listenForCollisions();
  // No global gravity force
  box2d.setGravity(0, -2);

  movers = new ArrayList();
  for (int i = 0; i < 8; i++) {
    movers.add(new Mover(random(30, 60), offscreen.width/2, offscreen.height/2));
  }
  float cx = offscreen.width/2;
  float cy = offscreen.height/2;
  walls[0] = new Boundary((cx - door/2), cy, 1, offscreen.height);
  walls[1] = new Boundary(cx + door/2, cy, 1, offscreen.height);
  walls[2] = new Boundary(cx, cy - door/2, offscreen.width, 1);
  walls[3] = new Boundary(cx, cy + door/2, offscreen.width, 1);
}

void draw() {

  PVector surfaceMouse = surface.getTransformedMouse();
  offscreen.beginDraw();
  offscreen.background(0);

  // We must always step through time!
  box2d.step();

  for (Mover m : movers) {
    m.display();
  }
  for (int i = 0; i < 4; i++) {
    walls[i].display();
  }

  if (caliDoor == true) {
    offscreen.noFill();
    offscreen.strokeWeight(3);
    offscreen.stroke(255);
    offscreen.rect(width/2, height/2, door, door);
  } else {offscreen.stroke(0);}
  offscreen.endDraw();
  background(0);
  surface.render(offscreen);
}

// Collision event functions!
void beginContact(Contact cp) {

  clang.trigger();
}
// Objects stop touching each other
void endContact(Contact cp) {
}
void keyPressed() {
  switch(key) {
  case 'c':
    // enter/leave calibration mode, where surfaces can be warped 
    // and moved
    ks.toggleCalibration();
    if (caliDoor == false) {
      caliDoor = true;
    } 
    else {
      caliDoor = false;
    }
    break;

  case 'l':
    // loads the saved layout
    ks.load();
    break;

  case 's':
    // saves the layout
    ks.save();
    break;
  }
}

// The Nature of Code
// 
// Spring 2012
// PBox2D example

// A fixed boundary class

class Boundary {

  // A boundary is a simple rectangle with x,y,width,and height
  float x;
  float y;
  float w;
  float h;
  
  // But we also have to make a body for box2d to know about it
  Body b;

  Boundary(float x_,float y_, float w_, float h_) {
    x = x_;
    y = y_;
    w = w_;
    h = h_;

    // Define the polygon
    PolygonShape sd = new PolygonShape();
    // Figure out the box2d coordinates
    float box2dW = box2d.scalarPixelsToWorld(w/2);
    float box2dH = box2d.scalarPixelsToWorld(h/2);
    // We're just a box
    sd.setAsBox(box2dW, box2dH);


    // Create the body
    BodyDef bd = new BodyDef();
    bd.type = BodyType.STATIC;
    bd.position.set(box2d.coordPixelsToWorld(x,y));
    b = box2d.createBody(bd);
    
    // Attached the shape to the body using a Fixture
    b.createFixture(sd,1);
    
    b.setUserData(this);
  }

  // Draw the boundary, if it were at an angle we'd have to do something fancier
  void display() {
    fill(0);
    stroke(0);
    rectMode(CENTER);
    offscreen.rect(x,y,w,h);
  }

}

// The Nature of Code
// 
// Spring 2011
// PBox2D example

// Showing how to use applyForce() with box2d

class Mover {

  // We need to keep track of a Body and a radius
  Body body;
  float r;

  Mover(float r_, float x, float y) {
    r = r_;
    // Define a body
    BodyDef bd = new BodyDef();
    bd.type = BodyType.DYNAMIC;

    // Set its position
    bd.position = box2d.coordPixelsToWorld(x, y);
    body = box2d.world.createBody(bd);

    // Make the body's shape a circle
    CircleShape cs = new CircleShape();
    cs.m_radius = box2d.scalarPixelsToWorld(r);

    // Define a fixture
    FixtureDef fd = new FixtureDef();
    fd.shape = cs;
    // Parameters that affect physics
    fd.density = 0.8;
    fd.friction = 0.3;
    fd.restitution = 1.1;

    body.createFixture(fd);

    body.setLinearVelocity(new Vec2(random(-5, 5), random(-5, -5)));
    body.setAngularVelocity(random(-1, 1));
  }

  void applyForce(Vec2 v) {
    body.applyForce(v, body.getWorldCenter());
  }


  void display() {
    // We look at each body and get its screen position
    Vec2 pos = box2d.getBodyPixelCoord(body);
    // Get its angle of rotation
    float a = body.getAngle();
    offscreen.pushMatrix();
    offscreen.translate(pos.x, pos.y);
    offscreen.rotate(a);
    offscreen.image(penny,-r,-r,r*2, r*2);
    offscreen.popMatrix();
  }
}

Lil Nippers

Unfortunately, this doesn’t look nearly as good in tiny youtube format, as it’s actually 1000+ pixels wide. The Macs in the clusters are huge and I wanted to make a thing that takes up most, if not all of the space. The nippers are pretty simple in nature: you feed them by typing on your keyboard, and after they eat a certain amount they will explode and become two tiny nippers. If there’s no food left for them to eat, their will to leave dissipates and they slowly move to a stop. Poor little nippers!

Originally, I wanted to assign more significance to the act of typing–there’s a residual element of that left over as the most frequent letters found in the English language (e, t, and a) give the nippers more energy than the least common (z, q, x). This was easily cribbed from Wikipedia, lots of people have done research into this and little kids use it to break each other’s substitution ciphers. As it stands, it’s more fun to smash keys and watch the nippers run around.

Were I to have more time to work on this, I would’ve loved to add a way for the nippers to slowly die. They each have their own different speeds, and when you run the program you’ll sometimes notice one brutally beating the competition, picking up food left and right and leaving slow, hungry nippers in its dust. I’d like to have them slow to a stop and begin to shrink if they haven’t eaten in a certain amount of time, reminding us that the circle of life involves stone-cold competition.


int zoom = 400;
PImage lLeg;
PImage rLeg;
PImage body;

//---GLOBAL COLORS---
color green = color(163, 169, 72);
color yellow = color(237, 185, 46);
color orange = color(248, 89, 49);
color red = color(206, 24, 54);
color blue = color(0, 153, 137);

//---FOOD STUFF---
ArrayList foods;

//---BUG STUFF---
ArrayList bugs;

//for adding bugs
ArrayList bugCoords;
int queue;

//for bugs eating foods
int distDex;

void setup() {
size(1800+zoom, 300);
noStroke();
smooth();

foods = new ArrayList();

bugs = new ArrayList();
bugs.add(new Bug(random(width-400), random(height*.75, height)));

bugCoords = new ArrayList();

rLeg = loadImage("rightleg.png");
lLeg = loadImage("leftleg.png");
body = loadImage("body.png");

}

void draw() {
background(230);
fill(255);
Bug zoomy = bugs.get(0);
pushMatrix();
translate(width-height-50+cos(zoomy.xpos/2), -height/4);
pushMatrix();
translate(height/3+25,height-23);
image(lLeg, -18, 3*sin(zoomy.xpos),height/6,height/6);
image(rLeg, 18, 3*cos(zoomy.xpos), height/6, height/6);
popMatrix();
image(body, 0, 0, height, height);
popMatrix();
rect(0, 0, width-399, height);
fill(230);
rect(0, height*.75, width-400, height);

for (Food f : foods) {
f.display();
}

for (Bug b : bugs) {

//get the closest food
float leastDist = -1;
float tempDist;
if (foods.size() > 0) {
for (int i = 0; i < foods.size(); i++) { Food g = foods.get(i); if (leastDist < 0) { leastDist = dist(b.xpos, b.ypos, g.x, g.y); distDex = i; } tempDist = dist(b.xpos, b.ypos, g.x, g.y); if (tempDist < leastDist) { distDex = i; leastDist = tempDist; } } } if (foods.size() > 0) {
Food goal = foods.get(distDex);
b.id = distDex;
b.seek(goal.x, goal.y);
}

if (foods.size() < 1) { b.vx = lerp(b.vx, 0, .001); b.vy = lerp(b.vy, 0, .001); } if ((dist(b.xpos, b.ypos, b.goalx, b.goaly) < 3) && (foods.size() > 0)) {
Food g = foods.get(b.id);
b.eat(g.priority);
foods.remove(b.id);

b.vx = lerp(b.vx, 0, .001);
b.vy = lerp(b.vy, 0, .001);
}

b.size = lerp(b.size, b.desiredSize, .1);

if (b.isMature() == true) {
b.desiredSize = 0.05;
bugCoords.add(b.xpos);
bugCoords.add(b.ypos);
queue += 1;
}

b.update();
b.display();
}

// safely add bugs
if (queue > 0) {
for (int i = 0; i < queue; i++) { float x = bugCoords.get(i); float y = bugCoords.get(i+1); bugs.add(new Bug(x+5, y)); } queue = 0; bugCoords.clear(); } } //---------------------------------------------------- //-- CHECK THE KEYBOARD FOR DELICIOUS FOOD! -- //---------------------------------------------------- void keyReleased() { //upper case if (int(key) >= 65 && int(key) < = 90) { float xpos = random(10, width-400-50); float ypos = random(height*.75+15, height - 5); int pri = checkUpper(key); if (pri != 0) { foods.add(new Food(xpos, ypos, 8, checkUpper(key))); } } //lower case else if (int(key) >= 97 && int(key) < = 122) { float xpos = random(10, width-400-50); float ypos = random(height*.75+15, height - 5); int pri = checkLower(key); if (pri != 0) { foods.add(new Food(xpos, ypos, 8, checkLower(key))); } } } //---------------------------------------------------- //-- GRAB COLOR/PRIORITY INFO FROM KEYBOARD -- //---------------------------------------------------- int checkLower(char letter) { int pri = 0; if ("eta".indexOf(str(letter)) > -1) {
pri = 5;
}
else if ("oinshr".indexOf(str(letter)) > -1) {
pri = 4;
}
else if ("dlcumwfg".indexOf(str(letter)) > -1) {
pri = 3;
}
else if ("ypbvk".indexOf(str(letter)) > -1) {
pri = 2;
}
else if ("xqz".indexOf(str(letter)) > -1) {
pri = 1;
}
return pri;
}

int checkUpper(char letter) {
int pri = 0;
if ("ETA".indexOf(str(letter)) > -1) {
pri = 5;
}
else if ("OSINSHR".indexOf(str(letter)) > -1) {
pri = 4;
}
else if ("DLCUMWFG".indexOf(str(letter)) > -1) {
pri = 3;
}
else if ("YPBVK".indexOf(str(letter)) > -1) {
pri = 2;
}
else if ("XQZ".indexOf(str(letter)) > -1) {
pri = 1;
}
return pri;
}

class Bug {
float xpos, ypos;
float vx, vy;
float dist;
float size = 0.05;
float desiredSize = size;
float ms = 100;
float goalx, goaly;
int id;
float speed;
float lastAte;

Bug(float xin, float yin) {
xpos = xin;
ypos = yin;
size = 0.05;
vx = 0;
vy = 0;
speed = random(.5,1.2);
}

void display() {
noStroke();
fill(52, 27, 27);
pushMatrix();
float depth = 1-((height-ypos)/height);
translate(xpos, ypos+cos(xpos/2)-depth*size*ms/2);
scale(depth*size, depth*size);
fill(72, 47, 47);
ellipse(-(ms/20), (ms/2)+sin(xpos), ms/10, ms/10);
fill(52, 27, 27);
ellipse(2*cos(millis()/200), 0, ms, ms);
ellipse((ms/20), (ms/2)+cos(xpos), ms/10, ms/10);
popMatrix();
}

void eat(float foodSize) {
desiredSize += foodSize / 100;
lastAte = millis();
}

void seek(float goalxin, float goalyin) {
goalx = goalxin;
goaly = goalyin;
float absx = goalx - xpos;
float absy = goaly - ypos;
float dist = sqrt((absx * absx) + (absy * absy));
vx = absx / dist * speed;
vy = absy / dist * speed;
}

void update() {
xpos += vx;
ypos += vy;

if (xpos + vx > width-400-(ms*size/2)) {
vx *= -1;
xpos = min(xpos, width-400-(ms*size/2));
}
else if (xpos + vx < 0) { vx *= -1; xpos = max(xpos, 0); } if (ypos + vy > height) {
vy *= -1;
ypos = min(ypos, height);
}
else if (ypos + vy < height*.75) { vy *= -1; ypos = max(ypos, height*.75); } } boolean isMature() { if (size > 1) {
return true;
}
return false;
}
}

class Food {
float x, y, dia;
int priority;
color flavor;

Food (float xin, float yin, float din, int pri) {
x = xin;
y = yin;
dia = din;
priority = pri;

//------SET COLOR-------
if (pri == 5) {
flavor = red;
}
else if (pri == 4) {
flavor = orange;
}
else if (pri == 3) {
flavor = yellow;
}
else if (pri == 2) {
flavor = green;
}
else if (pri == 1) {
flavor = blue;
}
}

void display() {
fill(flavor);
pushMatrix();
translate(x,y);
scale(1-((height-y)*2/height),1-((height-y)*2/height));
ellipse(0,0,dia,dia);
popMatrix();
}

boolean isGone() {
if (dia < 1) { return true; } return false; } }

Madeleine-LookingOutwards-03


Sound Machines – 2011. Sound Machines was created by The Product, a Berlin-based design studio for Volkswagen. It’s a faux-record player that uses a (light? color?) sensor to read slowly rotating “records” that have been concentrically patterned. The data is thrown into a music software package that then processes it and makes beautiful beats! Cool! I really like the idea of taking old technology and remixing it into something novel, as this does well. They were *almost* there in terms of interactivity, I really love the ability to play new patterns based on where the sensor is rotated, but I feel like they could’ve gone further. I wish they had allowed visitors to generate their own records and attempt to play them, although I understand the fear of having a less musically inclined person attempt to draw their own record and have it sound like crap.


NOISY JELLY – 2012. Noisy Jelly was created by Raphaël Pluvinage and Marianne Cauvard as part of a class project at L’Ensci Les ateliers. Players mix and set their own jellies and then place them on a board to create their own jelly soundboards. Super clever use of capacitive sensors and conductivity to create audio signals, I liked that each addable color had different salt capacities as opposed to having players add salt on their own, clever way to help players *and* the computer differentiate between different instruments. The sounds they use are kind of annoying, but they totally work for jelly.


DJ JACKET – 2013. Another sound interface project! Created by Atif Ateeq, the DJ Jacket is a wearable electronic device that communicates with MAX MSP & Ableton Live to do various audio transformations such as noise additions (air horns, scratching), looping, and cross fading. I <3 wearable electronics, I think this provided an interesting way to remix music. Clothing and style are often very relevant to musical genres (rappers namedrop clothing brands all the time, country singers often talk about wearing work boots). His jacket had so many zippers though, I wish he had used some of them as sensors!

Trypophobia

trypophobiaI have to walk through the radio station to get to campus every day, and there’s a small wooded area with lots of leaves on the ground (as there tends to be in the fall). I noticed that some of these leaves have weird holes in them–probably from small, hungry, bugs, but unsettling nonetheless. These creepy leaves reminded me of this phenomena coined trypophobia, where people find themselves intensely afraid of small, patterned holes such as those in lotus flowers or honeycomb. Small, patterned holes are also a regular natural occurrence, besides lotus flower and honeycomb they can be found in wood, plants, coral, sponges, and more. Clearly the art of generating small, patterned holes was worth investigation.

http://cmuems.com/2013/a/wp-content/uploads/sites/2/2013/10/screen02.pdf

I ended up with two variants. The first of which has a lot more variation in size and shape, and completely fills the wooded area. I basically shot particles at a board and if they were too close to an edge or another particle they’d fall off. Not very simulation heavy!

import processing.pdf.*;

int inch = 60;
int margin = inch/2;

ArrayList blobs;

void setup() {
  size(inch*12, inch*12, PDF, "screen05.pdf");
  background(255);
  noFill();
  smooth();

  float rad, x, y, maxr, minr;
  float desiredseperation = 0;
  boolean addBlob = true;
  int points, attempts, maxblob;

  blobs = new ArrayList();

  minr = inch/8;
  maxr = 1.5*inch;
  maxblob = 300;
  attempts = 0;

  while ((blobs.size() != maxblob) && (attempts < 6000)) {     rad = random(minr, maxr - map(blobs.size(), 0, maxblob, 0, maxr-minr+1));     points = int(random(5, 25 - map(blobs.size(), 0, maxblob, 0, 20)));     //x = random(margin+rad, width-(margin+rad));     //y = random(margin+rad, height-(margin+rad));    x = (width/2) + random(0,inch*4)*cos(TWO_PI*random(0,2));    y = (height/2) + random(0,inch*4)*sin(TWO_PI*random(0,2));     addBlob = true;     if (blobs.size() > 0) {
      for (Blob other : blobs) {
        desiredseperation = rad + other.r + (inch/8);
        if (dist(x, y, other.cx, other.cy) < desiredseperation) {
          addBlob = false;
          attempts += 1;
        }
      }
      if (addBlob) {
        blobs.add(new Blob(rad, points, x, y));
        attempts = 0;
      }
    }

    if (blobs.size() == 0) {
       blobs.add(new Blob(rad, points, x, y));
    }
  }

  for (Blob b : blobs) {
    b.display();
  }
  println(blobs.size());
}

void draw() {
  // Exit the program 
  println("Finished.");
  exit();
}

class Blob {
  float r;
  float cx, cy;
  int points;
  float px, py, pr, angle, offset;

  Blob (float inr, int inpoints, float inx, float iny) {
    r = inr; // random(inch/8, inch*2)
    points = inpoints; // random(3, 12)
    cx = inx;
    cy = iny;
  }

  void display() {
    beginShape();
    offset = random(0,1);
    for (int i = 0; i < points; i++) {
      angle = TWO_PI*(i+offset)/points;
      pr = random(.6, 1) * r;
      px = cx + pr*cos(angle);
      py = cy + pr*sin(angle);
      curveVertex(px, py);
      if ((i == 0) || (i == points-1)) {
        curveVertex(px, py);
      }
    }
    endShape(CLOSE);
  }
}

http://cmuems.com/2013/a/wp-content/uploads/sites/2/2013/10/frame-0214.pdf

The second one used Golan’s particle class to create a fleet of small holes that then drifted away from each other within a larger circle.

import processing.pdf.*;
boolean record;

int inch = 60;

ArrayList particles;

void setup() {
  size(inch*12, inch*12);
  background(255);
  noFill();
  smooth();

  particles = new ArrayList();

  for (int i = 0; i < 150; i++) {     float rad = random(inch/8, inch/4);     particles.add(new Particle(width/2 + random(-inch, inch), height/2 + random(-inch, inch), rad));   } } void draw() {   if (record) {     // Note that #### will be replaced with the frame number. Fancy!     beginRecord(PDF, "frame-####.pdf");    }      background(255);   float gravityForceX = 0;   float gravityForceY = 0.0;   float mutualRepulsionAmount = inch/16;     for (Particle p : particles) {      for (Particle other : particles) {       float desiredseperation = p.r + other.r + (inch/8);              float dx = p.px - other.px;       float dy = p.py - other.py;       float dh = sqrt(dx*dx + dy*dy);       if (dh > 1.0) {

        float componentInX = dx/dh;
        float componentInY = dy/dh;
        float proportionToDistanceSquared = 1.0/(dh*dh);

        float repulsionForcex = mutualRepulsionAmount * componentInX * proportionToDistanceSquared;
        float repulsionForcey = mutualRepulsionAmount * componentInY * proportionToDistanceSquared;

        p.addForce( repulsionForcex,  repulsionForcey); // add in forces
        other.addForce(-repulsionForcex, -repulsionForcey); // add in forces
      }

      /*if (dist(p.px, p.py, other.px, other.py) < desiredseperation) {

      }*/
    }
  }

  // update the particles
  for (int i=0; i<particles.size(); i++) {
    particles.get(i).bPeriodicBoundaries = false;
    particles.get(i).update(); // update all locations
  }

  for (int i=0; i<particles.size(); i++) {     particles.get(i).addForce(gravityForceX, gravityForceY);   }   for (Particle p : particles) {     p.render();   }      if (record) {     endRecord(); 	record = false;   } } // Use a keypress so thousands of files aren't created void mousePressed() {   record = true; } class Particle {   float r;   float px;   float py;   float vx;   float vy;   float damping;   float mass;   boolean bLimitVelocities = true;   boolean bPeriodicBoundaries = false;   float margin = 2;      float offset, qx, qy, qr, angle;   // stuff   float cx = width / 2;   float cy = height / 2;   float boundr = 300;   // Constructor for the Particle   Particle (float x, float y, float inr) {     r = inr;     px = x;     py = y;     vx = vy = 0;     damping = 0.95;     mass = 1.0;   }   // Add a force in. One step of Euler integration.   void addForce (float fx, float fy) {     float ax = fx / mass;     float ay = fy / mass;     vx += ax;     vy += ay;   }   // Update the position. Another step of Euler integration.   void update() {     vx *= damping;     vy *= damping;     limitVelocities();     handleBoundaries();     px += vx;     py += vy;   }   void limitVelocities() {     if (bLimitVelocities) {       float speed = sqrt(vx*vx + vy*vy);       float maxSpeed = 6.0;       if (speed > maxSpeed) {
        vx *= maxSpeed/speed;
        vy *= maxSpeed/speed;
      }
    }
  }

  void handleBoundaries() {
    if (bPeriodicBoundaries) {
      if (px > width ) px -= width;
      if (px < 0     ) px += width;       if (py > height) py -= height;
      if (py < 0     ) py += height;     }     else {       //super tenuous circular boundaries       if (dist(cx, cy, px+vx, py+vy) > boundr - r) {
        vx *= -1;
        vy *= -1;
      }
    }
  }

  void render() {

    float noiseVal = noise((mouseX)*80, 
                            mouseY*80);

    stroke(0);
    beginShape();
    offset = random(0,1);
    for (int i = 0; i < 10; i++) {
      angle = TWO_PI*(i+offset)/10;
      qr = random(0.75, 1) * r;
      qx = px + qr*cos(angle);
      qy = py + qr*sin(angle);
      curveVertex(qx, qy);
      if ((i == 0) || (i == 10-1)) {
        curveVertex(qx, qy);
      }
    }
    endShape(CLOSE);
  }
}