Revolving Games

RGPressPhotoResize

This crafty measuring device is meant to draw attention to the daily usage of revolving doors at Carnegie Mellon’s University Center building. It logs the time, proximity, and rpm data, but also incites a little competitive spirit on its free voltage.

This project revisited our previous class assignment that utilized seven segment displays to capture an interesting measurement. In my original idea, I wanted to choose a unique and fun way to portray numbers, and what better way to do that than with rankings? The reason I chose revolving doors as my subject matter was more or less because I was interested in the calculations involved with an accelerometer.

But as I developed my idea in this assignment, I wanted to convey more useful information about my subjects, the revolving doors. The research changed its direction from “interesting calculations” to bringing attention to those mundane doors that we pass through without a second thought. And I have to thank Maddy Varner and Golan Levin for reminding me that an extra seven segment display and data logging shield were just the things I needed to accomplish this.

That said, the actual wiring of all these new devices, as well as figuring out their libraries were the most technical aspect of the project. Through this process, I came to understand JUST HOW INVALUABLE neat soldering can be. But in the end, the effort was definitely worth it. (See below for fritzing and code). I had some technical difficulties along the way (I seem to have jynxed technology a lot this semester), but I find the data that came from my 7 hours of installation really valuable. The animated GIF below shows the plotted data from the data logging shield, and there are clear patterns of usage for these doors. (Click the image.)

SMALLGIF

Facts and Figures:
124 people used the door in those 7 hours
The highest score was 40 rpm
There were 4 notable mishaps

Of course, I won’t forget to address the most exciting–and hazardous–part of this project: the participants. I may have underestimated the competitive spirit of college students, because I felt fear watching some of them. My project installation time was cut short because the UC staff asked me not to display the high score portion, and I personally thought the goings could get worse since it is finals week. On a side note, I was extremely happy with how the magic arm stabilized the box. The whole contraption was incredibly sturdy.

In conclusion, I am very satisfied with this project. Although video editing is not my strong point, I did enjoy watching over my project and seeing people have fun and expressing a genuine interest.

Supported in part by a microgrant from the Frank-Ratchye Fund For Art at the Frontier
URL: bit.ly/revolving-games

Parts:

Sparkfun Arduino Uno
Adafruit ADXL345 Triple Axis Accelerometer
Adafruit Assembled Data Logging Shield
Adafruit IR Distance Sensor (10-80 cm)
Adafruit 4 Digit 7 Segment Displays (0.56″)
9V Batteries

Fritzing Diagram:

Revolving Games_bb

//Revolving Games by Michelle Ma
//note the code may have been altered due to
//the WordPress syntax

#include 
#include 
#include "RTClib.h"
#include "Adafruit_LEDBackpack.h"
#include "Adafruit_GFX.h"
#include 
#include 

Adafruit_7segment matrix1 = Adafruit_7segment();
Adafruit_7segment matrix2 = Adafruit_7segment();
Adafruit_ADXL345 accel = Adafruit_ADXL345(12345);

RTC_DS1307 RTC; // Real Time Clock

const int chipSelect = 10; //for data logging
const int distancePin = 0; //A0 for IR sensor

const int threshold = 100; //collect data when someone near
const float radius = 0.65; //radius of door in meters
const float pi = 3.1415926;

File logfile;

int highScore;

void setup() {
  Serial.begin(9600);
  SD.begin(chipSelect);
  createFile();
  accel.begin();
  matrix1.begin(0x70);
  matrix2.begin(0x71);
  
  if (!RTC.isrunning()) {
    RTC.adjust(DateTime(__DATE__, __TIME__));
  }
  
  accel.setRange(ADXL345_RANGE_16_G);
  
  highScore = 0;
}

void createFile() {
  char filename[] = "LOGGER00.CSV";
  for (uint8_t i=0; i<100; i++) {
    filename[6] = i/10 + '0';
    filename[7] = i%10 + '0';
    if (!SD.exists(filename)) {
      logfile = SD.open(filename, FILE_WRITE);
      break;
    }
  }
  
  if (!logfile) {
    Serial.print("Couldn't create file");
    Serial.println();
    while(true);
  }
  Serial.print("Logging to: ");
  Serial.println(filename);
  
  Wire.begin();
  
  if (!RTC.begin()) {
    Serial.println("RTC error");
  }
  logfile.println("TimeStamp,IR Distance,Accel (m/s^2),RPM");
}

void loop() {
  
  DateTime now = RTC.now();
  sensors_event_t event; 
  accel.getEvent(&event);
  
  float distance = analogRead(distancePin);
  float acceleration = event.acceleration.z;
  float rpm;
  
  if (distance > threshold) {
    rpm = computeRpm();
  } else {
    rpm = 0; //I chose not to display the scores
  }          //of people in other booths
  
  if (rpm > highScore) {
    highScore = rpm;
  }
  
  logData(now, distance, acceleration, rpm);
  serialData(now, distance, acceleration, rpm);
  writeMatrices(int(rpm), int(highScore));
  
  Serial.println("Saved...");
  logfile.flush(); // Write data to SD
}

float computeRpm() {
  float velocity = computeVelocity();
  float result = abs(60.0*velocity)/(2.0*pi*radius);
  return result;
}

float computeVelocity() {
  float acceleration;
  float sum = 0;
  int samples = 100;
  int dt = 10; //millis
  for (int i=0; i

Prezi-tation

Some images from the presentation:

Revolving Games_bb

door

//Revolving Games by Michelle Ma
//Revolving Games by Michelle Ma

#include 
#include 
#include "RTClib.h"
#include "Adafruit_LEDBackpack.h"
#include "Adafruit_GFX.h"
#include 
#include 

Adafruit_7segment matrix1 = Adafruit_7segment();
Adafruit_7segment matrix2 = Adafruit_7segment();
Adafruit_ADXL345 accel = Adafruit_ADXL345(12345);

RTC_DS1307 RTC; // Real Time Clock

const int chipSelect = 10; //for data logging
const int distancePin = 0; //A0 for IR sensor

const int threshold = 100; //collect data when someone near
const float radius = 0.65; //radius of door in meters
const float pi = 3.1415926;

File logfile;

int highScore;

void setup() {
  Serial.begin(9600);
  SD.begin(chipSelect);
  createFile();
  accel.begin();
  matrix1.begin(0x70);
  matrix2.begin(0x71);
  
  if (!RTC.isrunning()) {
    RTC.adjust(DateTime(__DATE__, __TIME__));
  }
  
  accel.setRange(ADXL345_RANGE_16_G);
  
  highScore = 0;
}

void createFile() {
  char filename[] = "LOGGER00.CSV";
  for (uint8_t i=0; i<100; i++) {
    filename[6] = i/10 + '0';
    filename[7] = i%10 + '0';
    if (!SD.exists(filename)) {
      logfile = SD.open(filename, FILE_WRITE);
      break;
    }
  }
  
  if (!logfile) {
    Serial.print("Couldn't create file");
    Serial.println();
    while(true);
  }
  Serial.print("Logging to: ");
  Serial.println(filename);
  
  Wire.begin();
  
  if (!RTC.begin()) {
    Serial.println("RTC error");
  }
  logfile.println("TimeStamp,IR Distance,Accel (m/s^2),RPM");
}

void loop() {
  
  DateTime now = RTC.now();
  sensors_event_t event; 
  accel.getEvent(&event);
  
  float distance = analogRead(distancePin);
  float acceleration = event.acceleration.z;
  float rpm;
  
  if (distance > threshold) {
    rpm = computeRpm();
  } else {
    rpm = 0;
  }
  
  if (rpm > highScore) {
    highScore = rpm;
  }
  
  logData(now, distance, acceleration, rpm);
  serialData(now, distance, acceleration, rpm);
  writeMatrices(int(rpm), int(highScore));
  
  Serial.println("Saved...");
  logfile.flush();
}

float computeRpm() {
  float velocity = computeVelocity();
  float result = abs(60.0*velocity)/(2.0*pi*radius);
  return result;
}

float computeVelocity() {
  float acceleration;
  float sum = 0;
  int samples = 100;
  int dt = 10; //millis
  for (int i=0; i

Flying Carpets and Related Ideas


http://www.artcom.de/en/projects/project/detail/symphonie-cinetique-the-poetry-of-motion/

I have seen the work of these artists around vimeo before, and their sculptures are always seamless and breathtaking. There is a mystical harmony between the reflective light, music, and wavelike motions. This documentary describes the artsts’ inspirations and process pretty well, and shows their different variations in the sculpture. Their blog and videos didn’t say much about how their sculptures were implemented, but there was one comment that said each string-bound obeject was controlled by a stepper motor, and that the movements were coded in hardware (I’m not too sure what that means).

I’ve wanted to do a ceiling-type installation for a while, and I am extremely intrigued by the idea of making a sculpture that looks like it is floating. I imagine the challenge would be to get all the stepper motors to work at the same time and coordinate a sinusoidal motion. Even better, it would be cool if they were arranged in an array to look like a levitating mesh (flying carpet). But I realize this project needs to be scaled down, so I will just think about how to get all those stepper motors working. I would need a bigger power source for sure, as well as a shift register or something to get them to be programmed in the same way. I also am not that great at synchronizing the visual with music, so I think it would be cool for the movement to correspond to a sensor measurement.

I’ve seen a lot of drawing bots during my research, and I think this is a pretty interesting one because it is not a bot, really. It is controlled by motors reeling the string. This would be an interesting way of transforming a sensor measurement into a visual. Again, this would involve a lot of calculations between stepper motors, which would prove an interesting challenge.

This piece is really charming because it gives life to these typically inanimate objects and hides the mechanism behind its operation, which makes it quite mysterious. The artist uses a Lilypad and a servo for each book. It would be very interesting to take at least two inanimate objects and have them be able to communicate in a cute and humorous way. There method of communication would be through motors and maybe sound or light, and they would either have a sensor to interact, or maybe they could be connected through the internet. The idea would be that they have a story to tell together, and the viewers can watch or participate to figure it out. As for the actual objects, they could be salt and pepper shakers (Blue’s Clues anyone?), newspapers, rocks, water bottles, or generally anything that can conceal an arduino.

Sketches:
2013-11-18T21-55-41_4

How Fast Can You Spin?

Spin

My arduino project was installed on the revolving doors of the University Center. Basically, it uses an accelerometer to compute the speed of the doors as someone pushes it. The LED display then reports back the rank of the person out of the total number of people who passed through when the box was installed.

When I heard of the measuring device assignment, I wanted the numbers to be something easy to understand. For some reason, rankings were the first thing that came to mind, since first place is first place no matter what game you play. So I decided to go with a competitive event, and when I learned about the gyroscope, I knew I wanted to do something with rotations. As it turned out though, the revolving doors only needed an accelerometer to measure a force in one direction.

Some problems I ran into, as you will see in the video, is that some people didn’t really understand the colon separating the rank and the total number of participants. Maybe I should have just displayed one number… Another strange issue is that photographs and videos of the LED display could not capture a whole number unless I took a picture really close to the display. I’m not sure if this means the camera goes out of focus, or if the LED display has a slow enough frame rate that the camera picks up each frame. Another issue was that it was a little too bright out for the LED to be put in certain locations. My last problem was that many people ignored the box…

Overall, I had a great amount of fun with this project. I only wish I could leave the project there as a permanent installation to see the rankings accumulate over time.

EDIT:
I tried to get a video of the actual numbers changing, but at night the numbers were too bright. Plus people kept walking through when I tried to get a video. So here is a VERY brief shot of the numbers, if you can see them.

IMG_2940

IMG_2942

All the supplies I used were a FedEx box, masking tape, scissors, and Sugru to attach the thing to glass doors.

Revololving Games_bb

Parts used:
Adafruit ADXL345 – Triple-Axis Accelerometer
Adafruit 0.56″ 4-Digit 7-Segment Display w/I2C Backpack – Red

//Revolving Games
//Michelle Ma
//Adapted from Adafruit's 7 segment matrix and ADXL345 accelerometer example
//Using a 7 segment matrix and a 3-axis accelerometer, displays the ranking 
//out of a total number of rankings of the velocity of a person using a 
//revolving door.

#include 
#include "Adafruit_LEDBackpack.h"
#include "Adafruit_GFX.h"
#include 
#include 

Adafruit_7segment matrix = Adafruit_7segment();
Adafruit_ADXL345 accel = Adafruit_ADXL345(12345);

//If acceleration is greater than this value, start computing ranking!
const int accelThreshold = 2.00;
//There are only two available digits to display total rankings
const int numScores = 99;

//array of the speeds (scores)
float velocities[numScores];
int numRankings = 0;

void setup() {
  Serial.begin(9600);
  if(!accel.begin())
  {
    /* There was a problem detecting the ADXL345 ... check your connections */
    Serial.println("Ooops, no ADXL345 detected ... Check your wiring!");
    while(1);
  }
  matrix.begin(0x70);
  matrix.setBrightness(5);
  accel.setRange(ADXL345_RANGE_16_G);
  //velocities array initialized with impossible speeds
  for (int i=0; i accelThreshold) {
    float velocity = computeVel(event.acceleration.y);
    velToArray(velocity);
    //Give time for door to stop rotating
    delay(5000);
  }
}

float computeVel(float accel) {
  // Will collect over 250 ms
  // Using trapezoid rule to compute estimated velocity
  float sum = 0;
  int samples = 25;
  int dt = 10;
  for (int i=0; i < samples; i++) {
    if ((i==0)||(i==(samples-1))) {
      sum += abs(accel);
    } else {
      sum += 2*abs(accel);
    }
    delay(dt);
  }
  //dt is in milliseconds
  float result = ((dt/1000.0)/2.0)*(sum);
  Serial.print("  Velocity: "); Serial.print(result);
  return result;
}

void velToArray(float velocity) {
  int rank;
  //If rankings reach the cap of the matrix, take off the 
  //slowest velocity
  if (numRankings==numScores) {
    velocities[numScores-1] = 100.0;
    numRankings--;
  }
  //first velocity entered
  if (numRankings==0) {
    velocities[0] = velocity;
    rank = 1;
    numRankings++;
  } else {
    //Go through the list from the right
    for (int i=numScores-1; i>0; i--) {
      //place velocity after a faster velocity
      if ((velocity > velocities[i-1])){
        velocities[i] = velocity;
        rank = i+1;
        numRankings++;
        break;
      } else {
        //move velocities down an index
        velocities[i] = velocities[i-1];
        if (i==1) {
          //fastest velocity placed at beginning
          velocities[0] = velocity;
          rank = 1;
          numRankings++;
        }
      }
    }
  }
  Serial.print("  Rank: "); Serial.print(rank);
  Serial.print("  Fastest: "); Serial.print(velocities[0]);
  Serial.print("  NumRankings: "); Serial.print(numRankings);
  displayRank(rank);
}

void displayRank(int rank) {
  //Display rank in matrix0 and matrix1
  //Display total rankings in matrix3 and matrix 4
  matrix.writeDigitNum(0, int(rank/10));
  matrix.writeDigitNum(1, rank%10);
  matrix.drawColon(true);
  matrix.writeDigitNum(3, int(numRankings/10));
  matrix.writeDigitNum(4, numRankings%10);
  matrix.writeDisplay();
}

Arduino Circuit Exercises

Yay! Arduinos!

Circuit 1
IMG_2909

Circuit 2
IMG_2910

Circuit 3 – Combined the RGB thing with the Potentiometer thing and practiced making Fritzing diagrams
circuit rainbow_bb

Circuit 4
IMG_2912

Circuit 5
IMG_2913

Circuit 6
IMG_2915

Circuit 7 – Learned not to confuse the transistor with the temperature sensor
IMG_2916

Circuit 8
IMG_2917

Circuit 9
IMG_2918

Circuit 10
IMG_2920

Circuit 11
IMG_2921

Circuit 12
IMG_2922

*Forgot to document 13 and 14

First Soldering attempt… Collaborated with Rachel!
IMG_2926

Shields!

Arduino Wi-Fi Shield
https://www.sparkfun.com/products/11287

This would definitely be an incredibly convenient addition to an arduino project just because wireless internet means less hassle over ethernet. Then again, I haven’t had much luck with CMU’s wireless… Anywho, this would be really useful for projects involving transmitting/receiving data from RSS Feeds or other sites on the web. Especially if the projects are meant to be portable!
(Too bad it’s a whopping $85…)

TFT Touch Screen for Arduino
http://www.adafruit.com/products/376

I’m impressed by the fact that this shield has a pretty high resolution and is also a touch screen. It’s a really useful interactive display and vastly expands what kind of data can be retrieved from the user’s interactions with the arduino. For example, it can measure the speed of tapping, or the position the finger slides to on the screen. Or it can just display some pretty flashy stuff.
(And again, a whopping $59…)

Data Logging Shield for Arduino
http://www.adafruit.com/products/1141

After seeing the cap on how large of a program you can put into an Arduino Uno, I’m thinking this shield would be the most reasonable choice for storing large amounts of data for projects that involve plotting or collecting data from a GPS shield or some other database. For example, if I did a project based on surveys from CMU students, I could use the data logging shield and then program the arduino to have some fancy visual output that lets the students see the results of the surveys.
(Less than $20!)

Sensors!

Color Light Sensor – Sparkfun
https://www.sparkfun.com/products/10656

I had a strong bias to the cheaper sensors on each site, and this is one of my favorites. I can imagine this being used as the “eyes” of a robot to identify certain objects by color. I think it would be cool to make a robot that can analyze the colors of a simple painting, drawing, or graphic and try to duplicate that coloring by having several arms that reach into pigments, mix its own shades and then draw the shapes. I also think this project could be used in a cool way to identify the color schemes of a room, someone’s outfit, or etcetera because sometimes I walk into a room that has some awesome interior decorations and I want to know the exact colors they combined so well.

Piezo Vibration Sensor – Large with Mass – Sparkfun
https://www.sparkfun.com/products/9197

The most obvious application I can think of for this would be attaching it to musical instruments to sense sound vibrations. The vibration data can then be converted into some other sensory output. Depending on how sensitive this device is, it can also be used to detect a presence through footsteps or knocking on a door. I imagine it can be applied to anything with sound, actually.

Tilt Sensor – Sparkfun
https://www.sparkfun.com/products/10313

A tilt sensor is screaming for use in an interactive piece. It could be used with a controller, lever, or a ship wheel… Anywho, the tilt sensor kind of reminds me of a project like Dave’s bubble creature. It could measure the amount of someone’s OCD in a room of tilted objects…

Clotheshanger

For this project I went through Daniel Schiffman’s tutorial and found the section on toxiclibs really interesting. I stuck to the springs and soft body square section and decided to do a clotheshanger. The toxiclibs springs have a very interesting texture to them compared to the meshes in processing or PBox2D, and fiddling around with constants in meshes are very fun.

Anywho, the point of my projection was to have the arrow keys control the wind direction so, as people walk by, they can experience the illusion of blowing cloth. I wanted to make clothes-shaped meshes, but I had enough trouble with the soft body squares, so that didn’t happen… I also found a beautiful example of coloring meshes by shading places darker according to distance between springs, but I didn’t know how to fill in the spaces between springs individually, so that didn’t happen either… Also, this projection was on a smaller scale, so Rachel and I just pretended to blow puffs of wind or blow a hairdryer at the cloth. I did struggle with the physics quite a bit, and there are still glitches within my toxiclibs code, but overall this assignment was much more fun. This might be because of the hands-on aspect of the project or because I had fun partnering up with Rachel. I also really like working with the pico projector and arm. I want them so badly now.

Here are some extremely rough sketches:

photo (4)

photo (6)

Froggies!

For my ecosystem, I started out with a fish pond because I remember a while back google had a random koi fish app somewhere on the internet. I tried searching it up again but I only see different android apps. I tried modelling the tail movements of the fish, but those ended up looking like tapeworms… So, I reused the curveVertex design that I featured in my first lasercut and added eyeballs. The lillypads have a gravitational force, so it looks like they try to hide from you. I applied Daniel Schiffman’s flocking examples to separate the fishes so they all wouldn’t go into the same spot due to the averaging of gravitational pulls. When you click the lillypads to make them disappear, the gravitational force gets added to the other lillypads so the fish don’t slow down. Pressing the space bar adds more lillypads. The lillypads, by the way, are cardioids, and they oscillate up and down and cause ripples. That was the funnest part of this project.

Then I decided to add frogs. I wanted them to leap onto a different lillypad when you clicked on one so that you would be “scaring them away”, but I had enough problems just getting them to jump on different lillypads. Giving them velocities ended up in hours of project failures, so this became my end product. Anywho, the best part about them is that they blink.

Here is my openprocessing upload, but the Javascript version of the code is far glitchier than the regular version run on processing:

Here are my sketches (notice I started out with the idea of Puffles hiding under rocks instead of a fish pond):

photo (5)
frog

photo 1

Lasercut 2.0 – Cracks

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

The results:

img001

img002

I changed my idea for the lasercut after the lecture today. Because of the limitations on shapes you can make with the lasercut, I decided to go back to using simple lines. I remembered back to the Recursive Trees code in the book Form + Code by Casey Reas and decided to search around the internet for similar code. Most trees had the problem of intersecting lines that would be impractical to lasercut. I was also thinking about the instructional art we had to engineer in an earlier assignment, because it was able to stop drawing lines once it detected another line.

Then I was looking at particle systems on OpenProcessing and found this one code called “Roots” that uses nodes like particles, and creates new nodes based on their distance from other nodes. His inspiration was Rapidly-exploring Random Trees (RRT). The link to that person’s code is here: http://www.openprocessing.org/sketch/38518

So I thought that would be very applicable to a lasercut, where everything has to be intact. I studied and grossly simplified the code to the point where I could understand it and modeled the growth of the nodes to match the Lissajous curves we learned in class. (Although, the circle still looked the best out of the various PDFs I saved…)

Here are my sketches:

photo (2)

photo (3)

Unfortunately, my code doesn’t work in Javascript so I can’t show it on OpenProcessing, but it is below:

// Credit goes to Alexander Mordvintsev for his code "Roots"
// which was inspired by RRT (Rapidly-exploring Random Trees)
// See here: http://www.openprocessing.org/sketch/38518

import processing.pdf.*;

ArrayList nodes;
int     branching    = 100;
float   branchLength = 5.0;
 
void setup()
{
  size(500,500);
  background(255);
  strokeWeight(1);
  smooth();
  nodes = new ArrayList();
  beginRecord(PDF, "cracks1.pdf");
}

void draw() {
  // Adds the parent node
  if (nodes.size() == 0)
    nodes.add(new Node(width-20,height/2));
  // Accelerates the amount of growth per frame
  for (int i=0; i<10; i++)
    grow();
}

void keyPressed() {
  endRecord();
  exit();
}

Node findNearest(Node p) {
  float minDist = 1e10;
  int minIndex  = -1;
  for (int i=0; i sq(branching));
  x += px;
  y += py;
  
  // Boundaries for the frame of the lasercut
  if(x>20 && x20 && y= branchLength) {
      Node newNode = new Node(base, sample);
      nodes.add(newNode);
      newNode.display();
    }
  }
}

class Node
{
  PVector pos;
  Node parent;
 
  Node(float x, float y) {
    pos = new PVector(x,y);
  }
  
  Node(Node base, Node sample) {
    PVector step = PVector.sub(sample.pos,base.pos);
    step.limit(5.0);
    pos = PVector.add(base.pos,step);
    parent = base;
  }
 
  float dist(Node other) {
    return PVector.dist(pos,other.pos);
  }
  
  // Draws a line between nearest node and new node
  void display() {
    if (parent!=null) {
      line(parent.pos.x, parent.pos.y, pos.x, pos.y);
    }
  }
}