[62-362] Activating the Body | Project 2: Flow | Fall 2019 | Alex Lin

Long Exposure Shot of User Movements

Overall Project Technology Arrangement

Overall Technology Set-Up

Project Calibration Set-Up

Overall Calibration Set-Up with Garment Display

Project Installation

Installing the Project onto a User | Photo Credit: Scarlet Tong

Project Wiring Overview (HUB)

Project Main Wiring Hub Close-Up

Project Wiring Overview (EMBEDDED)

Project User Embedded Wiring Close-Up

Project Suit-Up Process

Process of Installing the Project On Site | Photo Credit: Dave Choi

Process of Installing Project Collage

Project Demonstration

Project Detail Highlights

Adjustability Highlight

Stack of Embedded Accelerometer, Speaker, and Neopixel LED Circle

Description
Abstract Description
Two people stand on each side of a curtain and move. Their movements cause lights on them to shine. The movements also cause music on the other person to play louder or softer and cause vibration motors to vibrate based on which way they lean.
Narrative Description

Blind Understanding is a performance piece where two people stand on opposite sides of a curtain and are equipped with accelerometers which monitor and capture their movement. This information is then sent through digital signals to create a combination of vibration and music for the opposing person to experience, who can then process that information which can impact their movement. Sited in the Media Lab to provide an intimate space for the dancers to perform and through movement communicate, the project aims to allow for the users to speak through a different medium and feel the presence of the other individual. The dancers will be blocked from each other’s view due to the position of the curtain, but will be free to move as they please (within the confines of the reach of wires). The goal of the exhibit is to convey and to exercise the reading of movement through technology that may reveal information and emotion that otherwise may not be within our frame of perception.

This concept was derived from John Berger’s Ways of Seeing in which he describes how photographs are inherently subjective to the control of the photographer. This was applied to an idea about how people see past one another and attempting to create an experience that brings people together in an experience driven by a focus on the senses rather than language to communicate. This concept is related to my interest in the ways that people explore and interact with space as well as other people. Introducing a visual limitation, changes the ways in which people move and act within a space. In addition, communicating in an intimate environment where one is separated from the other begins to tie into ideas of technology and the distortion of distance that it allows. The concept tries to propose an alternate future where one can sense through a call the physical movements of the person they are communicating with. The project also is a projection of my perception of how I interact with others as someone who is more introverted and reserved, and  has become constructive criticism, as well as encouragement, for myself to express and to confide in others more frequently.

Process Images

Initial Concept Sketches:

Elevation Concept Diagram

Data Flow Diagram

The initial idea was, as explained above, to have two lines of communication between two users that abstracted information about the other persons movements that would influence the users movement without being able to see one another. In developing the concept, most of the concept remained the same, except for the lights which became feedback for the dancers themselves to know that their movements were causing a fluctuation in the data being sent across to the other person. The main question that was vague was the form that the project would take in latching on to each user and how it would fulfill all of its necessary functions.

Wiring Regrets Timelapse:

This timelapse is a snippet of the effort applied to securing all of the wires necessary to make this project possible. Because the system I proposed is not wireless, and I wanted the dancers to have a reasonable level of freedom in movement, this meant that I wanted the wires to hang above them so that they wouldn’t trip and that I would need to overestimate the amount of wire to provide as slack so that they would be able to move around more.

Wiring Regrets:

Workspace Update and Wiring Regrets

At each stage of the wiring process, from soldering, to wiring to the Arduino board, to mounting the accelerometers, speakers, LEDs, and vibration motors to the garment, I needed to ensure that all of the connections were still working, so that required me to troubleshoot multiple times (ex. when a wire pops out of an Arduino pin).

Garment Design & Sewing:

It’s been a while since I have sewed anything, but getting back wasn’t as terrible as I had originally thought. I used canvas as the more flexible fabric, and a plastic material as the more rigid which worked out fine, but sewing the two together took a while, especially when making two of them. In addition, a key factor in the design of the garment was ensuring that it would be able to fit anyone that wanted to try it, and so I took extra care to implement strategies as to allow for that adaptability (which also took more time than I had originally intended).

Garment Folding:

My apologies for the beginning of the timelapse being out of focus. In any case, folding the tessellations that I had decided on took a while to get the initial grid pattern set, but the tessellating wasn’t terribly difficult. I had originally planned on using CNC-ed wood for this project, but due to various issues with photogrammetry and CNC-ing, I had to scale down and redesign an origami piece that would be feasible within the time constraints. I chose the tessellation I did to match the scale of the project’s LEDs, but the patterning was intended to symbolize the scales/armor that we put up to protect ourselves which represent the hesitation to fully communicate with others.

Project Layout:

Deconstructed Layout View of the Project

Laying out the project after all of the initial fabrication was complete was interesting to see the bundles of wire and the layers of material and information that were embedded in the project. It was also a representation of organizing the system and visualizing it before the absolute chaos of wiring, undoing the wire bundles, etc.

Wire Securing:

Wire Securing Process

To ensure that the wiring directly connected to the Arduinos would not get pulled out through the movements of the dancers, I used a piece of wood to secure the breadboards and Arduinos and used zip-ties to secure the wires, protecting the wiring as best as I could. The zip-ties were threaded through holes in the wood and tightened until the wires weren’t budging.

Process Reflection

The process of this project was a bit bumpy to be honest. I was fairly confident throughout the process that I would be able to get the electronics working, but I took too much time to assess fabrication processes. I ran into issues with the photogrammetry program I was using with the images I was inputting and the modeling for the CNC-ing was heavily reliant on the 3D model that the photogrammetry software would output. I burned a lot of time trying to get the initial idea to work, and took too long to bail. In addition, the garment design was a huge undertaking given my ambitions. As I didn’t have two specific designated people to perform, I had to make sure that the final design would be able to fit anyone (although that would have been my intent either way, I suppose). Many of the solutions to allow for more flexibility can only be described as “jank”, but they did function as intended and the piece seems to perform well in that context. Although it worked out in the end, the final project wasn’t as integrated between the technology band and the origami sculptural piece as I would have hoped. In some of the imagery, you can clearly see issues with dancers having wires lifting the origami piece or dealing with wires threaded under their arms.

In regards to technology, the DFRobot Mini MP3 Player was a massive asset to allow for the Exploded Ensemble’s music to play, but was also very finicky at times, with some functions not working and general troubleshooting occurred very often. In regards to the LED feedback, I managed to get it to the point where different movements clearly made different light patterns and colors, but I would have liked to further develop that so that people can better understand what data was being collected from their movements. I think the vibration was also a point that could have been composed better. The vibration motors were definitely felt, but because the two motors on each garment were attached to the same piece of plastic, the sensation of the motors was more easily confused or lost than I would prefer. Lastly, the general use of wires felt really wasteful. The concept would have been weaker and more fragile if the lengths had been shortened, but in the future it might be better to consider ways to reduce that sort of excessive expenditure of materials.

Conceptually, the review and feedback was very helpful to give insight on how others saw the project in how it was presented and in how it functioned. The project would have been more compelling if I had taken more strides to introduce the rules of the project beforehand or if I had choreographed a dance that would provide an intriguing performance for the audience. In addition, the idea of a goal or of stakes was frustrating because one of the original ideas that I had was to give dancers a prompt (through a piece of music or through text) that they would be trying to convey to the other dancer. I think if more planning had gone into this part of the project, it would have had much more depth and would have incentivized the dancers to reach for a specific goal. Looking forward, I want to consider perhaps implementing myself into the final project and becoming a performer. The goal of designing a performance sat in the backseat for this project mostly because I was overly concerned about the fabrication, functionality, and aesthetics of the project. Moving forward, I want to expedite the fabrication portion to allow more time to consider the other intriguing performance aspects of the work, or to stay diligent on implementing these ideas earlier on in the process.

Arduino Code
//Blind Understanding by Alex Lin 
//This code uses the input of an accelerometer to control several outputs, including a Neopixel LED circle, two vibration motors, and a speaker based on various data (ex. pitch and roll) processed by the accelerometer. 
//Code requires two Arduinos for the two users, but should be able to be condensed into one file of code and run through one Arduino. 

//Accelerometer Code From: https://www.electronicwings.com/arduino/adxl335-accelerometer-interfacing-with-arduino-uno
#include <math.h>
#define x_out A1 /* connect x_out of module to A1 of UNO board */
#define y_out A2 /* connect y_out of module to A2 of UNO board */
#define z_out A3 /* connect z_out of module to A3 of UNO board */

#include <Adafruit_NeoPixel.h>
#define LED_PIN 6
#define LED_COUNT 16

#define vibrationLeft A4
#define vibrationRight A5

int red = 0;
int green = 0;
int blue = 0;

int together;

int ledLoop = 0;

Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_KHZ800);

//DFPlayer Mini Code From: https://wiki.dfrobot.com/DFPlayer_Mini_SKU_DFR0299
#include "Arduino.h"
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"

SoftwareSerial mySoftwareSerial(10, 11); // RX, TX
DFRobotDFPlayerMini myDFPlayer;
void printDetail(uint8_t type, int value);

int volume = 10;
int max_vol = 30;
int min_vol = 5;

void setup()
{
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'

  mySoftwareSerial.begin(9600);
  Serial.begin(115200);

  pinMode(vibrationLeft, OUTPUT);
  pinMode(vibrationRight, OUTPUT);

  Serial.println();
  Serial.println(F("DFRobot DFPlayer Mini Demo"));
  Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));

  if (!myDFPlayer.begin(mySoftwareSerial)) {  //Use softwareSerial to communicate with mp3.
    Serial.println(F("Unable to begin:"));
    Serial.println(F("1.Please recheck the connection!"));
    Serial.println(F("2.Please insert the SD card!"));
    while(true);
  }
  Serial.println(F("DFPlayer Mini online."));

  myDFPlayer.volume(volume);  //Set volume value. From 0 to 30
//  myDFPlayer.loopFolder(15); //loop all mp3 files in folder SD:/05.
  myDFPlayer.play(1);  //Play the first mp3
}

void loop(){
  static unsigned long timer = millis();

  if (myDFPlayer.available()) {
    printDetail(myDFPlayer.readType(), myDFPlayer.read()); //Print the detail message from DFPlayer to handle different errors and states.
  }
  
  int x_adc_value, y_adc_value, z_adc_value; 
  double x_g_value, y_g_value, z_g_value;
  double roll, pitch;
  x_adc_value = analogRead(x_out); /* Digital value of voltage on x_out pin */ 
  y_adc_value = analogRead(y_out); /* Digital value of voltage on y_out pin */ 
  z_adc_value = analogRead(z_out); /* Digital value of voltage on z_out pin */ 
//  Serial.print("x = ");
//  Serial.print(x_adc_value);
//  Serial.print("\t\t");
//  Serial.print("y = ");
//  Serial.print(y_adc_value);
//  Serial.print("\t\t");
//  Serial.print("z = ");
//  Serial.print(z_adc_value);
//  Serial.print("\t\t");

  x_g_value = ( ( ( (double)(x_adc_value * 5)/1024) - 1.65 ) / 0.330 ); /* Acceleration in x-direction in g units */ 
  y_g_value = ( ( ( (double)(y_adc_value * 5)/1024) - 1.65 ) / 0.330 ); /* Acceleration in y-direction in g units */ 
  z_g_value = ( ( ( (double)(z_adc_value * 5)/1024) - 1.80 ) / 0.330 ); /* Acceleration in z-direction in g units */ 

  roll = ( ( (atan2(y_g_value,z_g_value) * 180) / 3.14 ) + 180 ); /* Formula for roll */
  pitch = ( ( (atan2(z_g_value,x_g_value) * 180) / 3.14 ) + 180 ); /* Formula for pitch */
  //yaw = ( ( (atan2(x_g_value,y_g_value) * 180) / 3.14 ) + 180 ); /* Formula for yaw */
  /* Not possible to measure yaw using accelerometer. Gyroscope must be used if yaw is also required */

  Serial.print("Roll = ");
  Serial.print(roll);
  Serial.print("\t");

  Serial.print("Pitch = ");
  Serial.print(pitch);
  Serial.print("\t");

  if(roll < 30 && volume > min_vol) {
      volume--;
      myDFPlayer.volumeDown(); //Volume Down
  }

  if(roll > 90 && volume < max_vol) {
    volume++;
    myDFPlayer.volumeUp(); //Volume Up
  }

  if(roll < 60 && red < 255) {
    red++;
  }

  if(roll > 60 && red > 0) {
    red--;
  }

  if(pitch < 150 && green < 255) {
    green++;
  }

  if(pitch > 150 && green > 0) {
    green--;
  }

  together = pitch + roll;
 
  if(together < 200 && blue < 255) {
    blue++;
  }

  if(together > 200 && blue > 0) {
    blue--;
  }

  if(pitch > 120) {
    analogWrite(vibrationLeft, 255);
    analogWrite(vibrationRight, 0);
  }

  if(pitch < 120) { 
    analogWrite(vibrationLeft, 0);
    analogWrite(vibrationRight, 255);
  }
  
  Serial.print("red = ");
  Serial.print(red);
  Serial.print("\t\t");
  Serial.print("green = ");
  Serial.print(green);
  Serial.print("\t\t");
  Serial.print("blue = ");
  Serial.print(blue);
  Serial.println("\t\t");
    
  strip.setPixelColor(ledLoop, red, green, blue);
  ledLoop++;
  if(ledLoop == 16) {
    ledLoop = 0;
  }
  strip.show();
}


void printDetail(uint8_t type, int value){
  switch (type) {
    case TimeOut:
      Serial.println(F("Time Out!"));
      break;
    case WrongStack:
      Serial.println(F("Stack Wrong!"));
      break;
    case DFPlayerCardInserted:
      Serial.println(F("Card Inserted!"));
      break;
    case DFPlayerCardRemoved:
      Serial.println(F("Card Removed!"));
      break;
    case DFPlayerCardOnline:
      Serial.println(F("Card Online!"));
      break;
    case DFPlayerPlayFinished:
      Serial.print(F("Number:"));
      Serial.print(value);
      Serial.println(F(" Play Finished!"));
      break;
    case DFPlayerError:
      Serial.print(F("DFPlayerError:"));
      switch (value) {
        case Busy:
          Serial.println(F("Card not found"));
          break;
        case Sleeping:
          Serial.println(F("Sleeping"));
          break;
        case SerialWrongStack:
          Serial.println(F("Get Wrong Stack"));
          break;
        case CheckSumNotMatch:
          Serial.println(F("Check Sum Not Match"));
          break;
        case FileIndexOut:
          Serial.println(F("File Index Out of Bound"));
          break;
        case FileMismatch:
          Serial.println(F("Cannot Find File"));
          break;
        case Advertise:
          Serial.println(F("In Advertise"));
          break;
        default:
          break;
      }
      break;
    default:
      break;
  }
}