EDPX 3310 (Tangible Interactivity) BLOG

 

 

 

Week 1

Inspiration

Muriel Cooper

Muriel Cooper is one of the first few designer that use digital electronic communication. She was a "Bauhausian" who incorporated a lot of modernist Bauhaus style into book and publication design at MIT Press. She helped find the MIT Visible Language Workshop (VLW), a program that pioneer a lot of experimental computing in design using electronic technologies. The program explored many 3D graphic computing and manipulation that we use today. Eventually, the VLW became a part of MIT Media Lab with two other programs (MIT Architectural Machine Group, and the Center for Advanced Visual Studies). This brought more physical computing, robotics and other experimental digital form into the program. In addition, she worked with ACM SIGCHI. The MIT Media Lab now consist of 27 different research focus from Biomechatronics to Tangible Media. Her interest in computer graphics and typography created a new field of user interface and GUI even before the computer graphical user interface exist.

Progress and Process (LED Processing)

float bright = 0;
float bright2 = 0;
float bright3 = 0;
int change = 10; 
float angle;
long myTime = 0;

void setup() {
 size(800, 800);
 
}

void draw() {
 myTime = millis();

 fill(bright2, bright, bright3);
 ellipse(width/2-150, height/2, 100, 100);
 fill(bright, bright2, bright3);
 ellipse(width/2+150, height/2, 100, 100);
 bright2 = (sin(myTime/200.0)+cos(myTime/200.0)+1)*128.0;
 bright = (cos(myTime/200.0)+1)*128.0;
 bright3 = (sin(myTime/200.0)+1.0)*128.0;
println(bright + "," + bright2 + "," + bright3);
}

Reflection

I explored the blinking through the use of 3 different combination of trigonometry functions (sin + cos, sin, and cos). I believe these will create unique pattern that could be apply to RGB both circle. I switched the bright with bright2 on Red and Green of the ellipses so they have a different color pattern. Overall, I believe it created a movement that is more natural to the human eyes and the color flow well as it switches from Red to Green and the opposite on the another circle. 

 

Progress and Process (4 LEDs Arduino)
int red = 5;
int yellow = 9;
int green = 10;
int blue = 11;

float brightness = 0; 
float brightness1 = 0;
float brightness2 = 0;
float brightness3 = 0;

void setup() {

pinMode(red, OUTPUT);
pinMode(yellow, OUTPUT);
pinMode(green, OUTPUT);
pinMode(blue, OUTPUT);
pinMode(6, OUTPUT);
digitalWrite(6, LOW);
}
void loop() {
long currentTime = millis();

analogWrite(red, brightness);
analogWrite(yellow, brightness1);
analogWrite(green, brightness2);
analogWrite(blue, brightness3);

brightness = (cos(currentTime / 200.0) + 1.0) * 128;
brightness1 = (sin((currentTime / 200.0) + (1.5 * PI)) + 1.0) * 128;
brightness2 = (cos(currentTime / 200.0) + 1.0) * 128;
brightness3 = (sin((currentTime / 200.0) + (1.5 * PI)) + 1.0) * 128;
}

Reflection

For this project, I wanted the LEDs to fade in and out one by one. I experimented with trigonometry function (Sin and Cos) to create a smooth transition from one LED to another. This work with 2 LEDs really well however I could not get it to work with 4 LEDs. I use cos for the first LED as it will glow initially while sin for another. In other to make sin function to start at the lowest point, I needed to shift the function left so I added 1.5 Pi to do this. With 4 LEDs, I tried to use timer to stop 1 and 2 LEDs from glowing while 3 and 4 LEDs glow, and Vice Versa. However, when I did this, the analogWrite function reset and make both of the LEDs glow. Below is the modification that I made to create my fading algorithm.

long currentTime = millis();
if (currentTime - lastTime >= 250*PI) {
if (state < 3) {
state++;
}
if (state > 2) {
state = 0;
}
lastTime = currentTime;
}

if (state == 1) {
analogWrite(green, 0);
analogWrite(blue, 0);
analogWrite(red, brightness);
analogWrite(yellow, brightness1);
}
if (state == 2) {
analogWrite(red, 0);
analogWrite(yellow, 0);
analogWrite(green, brightness2);
analogWrite(blue, brightness3);
}

Back to the Top

 

 

 

Week 2

Inspiration

Doris Sung's Living Architecture

The concept of architecture being static is an old narrative that have been there for thousands of years. Sung's living architecture uses heat reactive metal to create movement in the form. As Sung mentioned in this video, the contemporary view of architecture is shifting towards more sustainable approach. This material could help create sustainable heat control for a building by letting hot air through when it is too cold or vice versa. Furthermore, they could react to how much sunlight should be in the building. I also share this dream of architecture that have movement through natural reaction to rain, snow, wind, heat, sunlights, and other nature processes. This will help create movements that conform with natural processes and movements which are more natural to human. For example, the movement of branches and leaves on the tree is natural response to the wind. This video further fuel my passion of mimicking natural processes through mathematical formula (sin, cos, tan, golden ratio).

Progress and Process (Arduino 6 LEDs)

const int numLEDs = 6;

int brightness[numLEDs] = {0};

int fadeIn[numLEDs] = {10, 10, 10, 10, 10, 10};

int fadeOut[numLEDs] = { -10, -10, -10, -10, -10, -10};

bool fadeUp [numLEDs] = {1, 1, 1, 1, 1, 1};

unsigned long lastTime[numLEDs] = {0, 0, 0, 0, 0, 0};

unsigned long lastTime2[numLEDs] = {0, 0, 0, 0, 0, 0};

unsigned int pin[numLEDs] = {5, 6, 9, 10, 11, 13};

int timer[numLEDs] = {15, 15, 15, 15, 15, 15};

unsigned long currentTime = 0;

int state = 0;

long counter = 0;

void setup() {
Serial.begin(9600);
randomSeed(analogRead(0));
for (int i = 0; i < numLEDs; i++) {
pinMode(pin[i], OUTPUT);
}
}


void loop() {
currentTime = millis();
if (currentTime - counter >= 3000) {
state = random(2);
counter = currentTime;
}

if (state == 1) {
for (int i = 0; i < numLEDs; i++) {
fader(i);
}
}
if (state == 0) {
for (int i = 0; i < numLEDs; i++) {
randomness(i);
}
}

}

void fader(int led) {

if (currentTime - lastTime[led] > timer[led]) {

analogWrite(pin[led], brightness[led]);
if (fadeUp[led]) {
brightness[led] = brightness[led] + fadeIn[led];
}
else {
brightness[led] = brightness[led] + fadeOut[led];
}

if (brightness[led] <= 0) {
fadeUp[led] = true;
} else if (brightness[led] >= 255) {
fadeUp[led] = false;
}
lastTime[led] = currentTime;
}
}
void randomness(int led) {
int state2 = random(7);

if (currentTime - lastTime2[led] > timer[led]) {
analogWrite(pin[led], brightness[led]);
if (state2 == 0) {
brightness[led] = (cos(currentTime / 200.0) + 1.0) * 128;
}
if (state2 == 1) {
brightness[led] = (sin((currentTime / 200.0) + (1.5 * PI)) + 1.0) * 128;
}
if (state2 == 2) {
brightness[led] = (tan(currentTime / 200.0) + 1.0) * 128;
}
if (state2 == 3) {
brightness[led] = (atan((currentTime / 200.0) + (1.5 * PI)) + 1.0) * 128;
}
if (state2 == 4) {
brightness[led] = (atan((currentTime / 200.0)) + 1.0) * 128;
}
if (state2 == 5) {
brightness[led] = (sin((currentTime / 200.0)) + 1.0) * 128;
}
if (state2 == 6) {
brightness[led] = (cos(currentTime / 200.0) + (1.5 * PI) + 1.0) * 128;
}

lastTime2[led] = currentTime;
}
}

Reflection

The code did not appear to do the intended effect that I want the LEDs to do. I use the state change and different functions to create different scenes. I believe the code could be more elegant and the narrative could be develop more. These exercise helped me understand timer better and could help me create different LEDs effect without using delays.

Back to the Top

 

 

 

Week 3

Inspiration

Toshiyuki Inoko

Toshiyuki Inoko is the founder of teamLab, that produces many techno art experiences. They uses a lot of projection mapping technology and tracking technology create immersive experience. teamLab combine the tangible elements of spaces and materials with virtual projection mapping to create immersive spaces. A lot of the pieces follows the natural processes such as water movement, glass reflection, and flower blooming. One of the most impressive work under the teamLab is the use of water as the interactive surface to create a new form of interface for holistic experience. The movement of the water are used to create an input response to the computer program that render the images. This intersection of light and tangible water surface create a more immersive experience for "users" as it draw the two interface with the most sensitive senses. I also have similar interest in creating responsive fluid dynamic works which is further inspired by this work. 

Progress and Process (Neo Pixel)

#include <Adafruit_NeoPixel.h>

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(1, 6, NEO_GRB + NEO_KHZ800);

int R = 0;
int G = 0;
int B = 0;

unsigned long lastLoop = 0;
unsigned long lastTime = 0;
unsigned long lastTime2 = 0;
unsigned long lastTime3 = 0;
unsigned long lastTime4 = 0;
unsigned long lastTime5 = 0;
unsigned long waitTime = 0;

int state = 0;

int light = 0;

int velocity = 250;

const int times = 7;

boolean lightning = 1;

void setup() {
Serial.begin(9600);
pixels.begin();
randomSeed(analogRead(0));
}

void loop() {

unsigned long currentTime = millis();

if (currentTime - lastLoop <= 2000) {
state = 0;
} else if (currentTime - lastLoop > 2000 && currentTime - lastLoop <= 7000) {
state = 1;
R = 0;
B = 0;
G = 0;
}
else if (currentTime - lastLoop > 7000 && currentTime - lastLoop <= 17000) {
state = 2;
R = 0;
G = 0;
B = 0;
}
else if (currentTime - lastLoop > 17000 && currentTime - lastLoop <= 19000) {
state = 3;
}
else if (currentTime - lastLoop > 19000 && currentTime - lastLoop <= 28000) {
state = 4;
}
else if (currentTime - lastLoop > 28000 && currentTime - lastLoop <= 33000) {
state = 5;
}
else {
lastLoop = currentTime;
}

if (state == 0) { // Reaching Dew Point
pixels.setPixelColor(0, pixels.Color(R, G, B));
pixels.show();
if (currentTime - lastTime > 30) {
B++;
lastTime = currentTime;
}
}
else if (state == 1) { // Starting to Rain
if (velocity > 75) {
velocity--;
}
B = (cos(currentTime / velocity) + 1.0) * 128;
pixels.setPixelColor(0, pixels.Color(R, G, B));
pixels.show();
}

else if (state == 2) { // Lightning

lightning = random(2);
if (currentTime - lastTime2 > 100) {
if (lightning) {
light = (cos(currentTime / 50.0) + 1.0) * 128;
pixels.setPixelColor(0, pixels.Color(light, light, light));
pixels.show();
} else {
pixels.setPixelColor(0, pixels.Color(0, 0, 0));
pixels.show();
}
lastTime2 = currentTime;
}

}

if (state == 3) { // Pause
pixels.setPixelColor(0, pixels.Color(0, 0, 0));
pixels.show();
}

if (state == 4) { // Storm Done (Sunrise)
pixels.setPixelColor(0, pixels.Color(R, G, B));
pixels.show();
if (currentTime - lastTime4 > 15) {
if (G < 128) {
G++;
}
if (R < 255) {
R++;
}
lastTime4 = currentTime;
}

}

if (state == 5) { // Sunset()
pixels.setPixelColor(0, pixels.Color(R, G, B));
pixels.show();
if (currentTime - lastTime5 > 15) {
if (R > 0) {
R--;
}
if (G > 0) {
G--;
}
if (B > 0) {
B--;
}
lastTime5 = currentTime;
}
}
}

Reflection

I believe I learned a lot of through using timer instead of delay from the pass 3 weeks. I still think there are limitation to timer that are hard to resolve that delay can perform really well. For example, the lightning (state2) is better with using small random time delay because lightning flashes are inconsistent. Millis() could not handle 2 digits delay because it is going too fast. Otherwise, a lot timer are extremely useful. I believe I could have make lightning more realistic. I found a couple of online examples that are extremely complex in calculating probability of creating the lightning flashes but I could not understand it so I couldn't applied into my code. At the end of the day, I use random to change between on and off stage and cos to create constant flashing along with timer to limit the amount of time that flashes happen (small number (2 digits) in millis() are missed sometime).

Back to the Top

 

 

 

Week 4

Inspiration

Refik Anadol

Progress and Process

const byte dim_curve[] = {
0, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6,
6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8,
8, 8, 9, 9, 9, 9, 9, 9, 10,10,10,10,10,11,11,11,
11,11,12,12,12,12,12,13,13,13,13,14,14,14,14,15,
15,15,16,16,16,16,17,17,17,18,18,18,19,19,19,20,
20,20,21,21,22,22,22,23,23,24,24,25,25,25,26,26,
27,27,28,28,29,29,30,30,31,32,32,33,33,34,35,35,
36,36,37,38,38,39,40,40,41,42,43,43,44,45,46,47,
48,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,
63,64,65,66,68,69,70,71,73,74,75,76,78,79,81,82,
83,85,86,88,90,91,93,94,96,98,99,101, 103, 105, 107, 109,
110, 112, 114, 116, 118, 121, 123, 125, 127, 129, 132, 134, 136, 139, 141, 144,
146, 149, 151, 154, 157, 159, 162, 165, 168, 171, 174, 177, 180, 183, 186, 190,
193, 196, 200, 203, 207, 211, 214, 218, 222, 226, 230, 234, 238, 242, 248, 255,
};

#include <Adafruit_NeoPixel.h>

int NUM_LEDS = 32;
int LED_PIN = 6;

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800);

int rgb_colors[3]; // recieves the results from hsb conversion

int H;
int S;
int B;

unsigned long lastTime = 0;
unsigned long lastLoop = 0;

int state = 0;

void setup() {
pixels.begin();
Serial.begin(9600);
S = 255;
B = 100;
}

void loop(){
unsigned long currentTime = millis();
if (currentTime - lastLoop <= 5000) {
pixels.clear();
state = 0;
}
else if (currentTime - lastLoop > 5000 && currentTime - lastLoop <= 10000) {
state = 1;
}
else {
lastLoop = currentTime;
}

if (state == 0) {

H = 90;
B = 100;
getRGB(H, S, B, rgb_colors); // converts HSB to RGB

for (int i = 5; i < 8; i++) {
pixels.setPixelColor(i, pixels.Color(rgb_colors[0], rgb_colors[1], rgb_colors[2]));
}
for (int i = 15; i < 16; i++) {
pixels.setPixelColor(i, pixels.Color(rgb_colors[0], rgb_colors[1], rgb_colors[2]));
}
for (int i = 21; i < 24; i++) {
pixels.setPixelColor(i, pixels.Color(rgb_colors[0], rgb_colors[1], rgb_colors[2]));
}
pixels.show();

}

else if (state == 1) {
for (int i = 0; i < pixels.numPixels(); i++) {
H = ((sin(((currentTime + i * 300.0) / 50.0) + (1.5 * PI)) + 1.0) * 180.0) + (0); // base and range
if (H > 75 && H < 175) {
B = 100;
} else {
B = 0;
}
getRGB(H, S, B, rgb_colors); // converts HSB to RGB
pixels.setPixelColor(i, pixels.Color(rgb_colors[0], rgb_colors[1], rgb_colors[2]));
pixels.show();
}

}

}

void getRGB(int hue, int sat, int val, int colors[3]) {
val = dim_curve[val];
sat = 255 - dim_curve[255 - sat];

int r;
int g;
int b;
int base;

hue = hue % 360;

if (sat == 0) { // Acromatic color (gray). Hue doesn't mind.
colors[0] = val;
colors[1] = val;
colors[2] = val;
} else{

base = ((255 - sat) * val) >> 8;

switch (hue / 60) {
case 0:
r = val;
g = (((val - base) * hue) / 60) + base;
b = base;
break;

case 1:
r = (((val - base) * (60 - (hue % 60))) / 60) + base;
g = val;
b = base;
break;

case 2:
r = base;
g = val;
b = (((val - base) * (hue % 60)) / 60) + base;
break;

case 3:
r = base;
g = (((val - base) * (60 - (hue % 60))) / 60) + base;
b = val;
break;

case 4:
r = (((val - base) * (hue % 60)) / 60) + base;
g = base;
b = val;
break;

case 5:
r = val;
g = base;
b = (((val - base) * (60 - (hue % 60))) / 60) + base;
break;
}

colors[0] = r;
colors[1] = g;
colors[2] = b;
}
}

Reflection

I had a hard time trying to figure out how to animate the spaceship and the laser blast in an efficient way. I could have done line by line code but I rather have a for loops or if then state to create the animation. Aside from that figure out the LEDs was not too hard. Clearing the LEDs was initially a problem because I didn't know there was a function for clearing the LEDs board. The inspiration of this project is from space invader. The spaceship will stop and shoot then it will warp through space.

Back to the Top

 

 

 

Week 5

Project Essence is an interface that explore the sense of smell. In many interfaces that are available today, smell and taste tend to be left behind as they are harder to replicate. The millions type of taste and smell make this effort hard. Project Essence is a project that track biometric and contextual data to create smell that help you relax or energize. Project Essence is part of MIT Media Lab Fluid Interface Research Group. It was awarded the Golden Mouse award at ACM CHI 2017. I uses Muse EEG monitors and E4 wristband monitors to track brain activity, heart rate variability, and electrodermal activity.

 

 

Progress and Process

Link: https://github.com/weiweikee/Snake-LEDs-

const byte dim_curve[] = {
  0,   1,   1,   2,   2,   2,   2,   2,   2,   3,   3,   3,   3,   3,   3,   3,
  3,   3,   3,   3,   3,   3,   3,   4,   4,   4,   4,   4,   4,   4,   4,   4,
  4,   4,   4,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   6,   6,   6,
  6,   6,   6,   6,   6,   7,   7,   7,   7,   7,   7,   7,   8,   8,   8,   8,
  8,   8,   9,   9,   9,   9,   9,   9,   10,  10,  10,  10,  10,  11,  11,  11,
  11,  11,  12,  12,  12,  12,  12,  13,  13,  13,  13,  14,  14,  14,  14,  15,
  15,  15,  16,  16,  16,  16,  17,  17,  17,  18,  18,  18,  19,  19,  19,  20,
  20,  20,  21,  21,  22,  22,  22,  23,  23,  24,  24,  25,  25,  25,  26,  26,
  27,  27,  28,  28,  29,  29,  30,  30,  31,  32,  32,  33,  33,  34,  35,  35,
  36,  36,  37,  38,  38,  39,  40,  40,  41,  42,  43,  43,  44,  45,  46,  47,
  48,  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,
  63,  64,  65,  66,  68,  69,  70,  71,  73,  74,  75,  76,  78,  79,  81,  82,
  83,  85,  86,  88,  90,  91,  93,  94,  96,  98,  99,  101, 103, 105, 107, 109,
  110, 112, 114, 116, 118, 121, 123, 125, 127, 129, 132, 134, 136, 139, 141, 144,
  146, 149, 151, 154, 157, 159, 162, 165, 168, 171, 174, 177, 180, 183, 186, 190,
  193, 196, 200, 203, 207, 211, 214, 218, 222, 226, 230, 234, 238, 242, 248, 255,
};


#include <Adafruit_NeoPixel.h>
#include "Keyboard.h"

int NUM_LEDS = 32; // Height = 4, Width = 8
int LED_PIN = 6;

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800);

int rgb_colors[3]; // recieves the results from hsb conversion


unsigned long lastTime = 0;
unsigned long moveTime = 0;
unsigned long nameTime = 0;

int a = 1;
int b = 7;

int offset = 0;

int state = 0;

char serialStuff = 's';

int eat = 0;

int numSnake = 31;

unsigned long currentTime = 0;

int s;

byte matrix[4][8] =
{
  { 0,  1,  2,  3,  4,  5,  6,  7},
  { 8,  9, 10, 11, 12, 13, 14, 15},
  {16, 17, 18, 19, 20, 21, 22, 23},
  {24, 25, 26, 27, 28, 29, 30, 31}
};



unsigned int SnakeGrid1[3][10] = {
  // Y (Rows) // 0-3
  {1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  // X (Cols) // 0-7
  {3, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  // Boolean (on or off)
  {1, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};


bool W[4][35] = {
  { 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0},
  { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0},
  { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0},
  { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0}
};

bool L[4][51] = {
  { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0},
  { 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0},
  { 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0},
  { 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0}
};


void setup() {
  pixels.begin();
  Serial.begin(9600);
  Keyboard.begin();

}

void loop()  {
  currentTime = millis();
  pixels.clear();
  switch (state) {
    case 0:
      snake();
      food();
      break;
    case 1:
      gameOver();
      break;
    case 2:
      youWin();
      break;
    default:
      break;
  }

  if (Serial.available() > 0) {
    serialStuff = char(Serial.read());
    Serial.println(serialStuff);
  }


  if (currentTime - lastTime >= 10000) {
    if (state == 1 || state == 2) {
      state = 0;
      eat = 0;
      SnakeGrid1[0][0] = 1;
      SnakeGrid1[1][0] = 3;
      for (int n = 1; n < 32; n++) {
        SnakeGrid1[0][n] = 0;
        SnakeGrid1[1][n] = 0;
      }
    }
  }



  if (eat == 6 && state == 0) {
    s = int(random(1, 3));
    lastTime = currentTime;
    if (s = 1) {
      state = s;
    }
    else if (s = 2) {
      state = s;
    }
  }
  pixels.show();
}

void snake() {

  for (int j = 0; j < 9; j++) {

    int x = SnakeGrid1[0][j];
    int y = SnakeGrid1[1][j];


    if (SnakeGrid1[2][j] == 1) {
      pixels.setPixelColor(matrix[x][y], pixels.Color(255, 0, 0));
    }

    // food random
    if (a == x && b == y) {
      a = int(random(0, 4));
      b = int(random(0, 8));
      eat++;
    }
  }

  if (currentTime - moveTime > 500) {
    for (int n = 9; n >= 1; n--) {
      SnakeGrid1[0][n] = SnakeGrid1[0][n - 1];
      SnakeGrid1[1][n] = SnakeGrid1[1][n - 1];
    }
  }

  SnakeGrid1[2][eat] = 1;


  // move
  if (serialStuff == 's') { // down
    if (currentTime - moveTime > 500) {
      SnakeGrid1[0][0] = SnakeGrid1[0][0] + 1;
      SnakeGrid1[0][0] = SnakeGrid1[0][0] % 4;
      moveTime = currentTime;
    }
  }

  if (serialStuff == 'w') { // up
    if (currentTime - moveTime > 500) {
      SnakeGrid1[0][0] = SnakeGrid1[0][0] - 1;
      SnakeGrid1[0][0] = abs(SnakeGrid1[0][0] % 4);
      moveTime = currentTime;
    }
  }

  if (serialStuff == 'a') { // left
    if (currentTime - moveTime > 500) {
      SnakeGrid1[1][0] = SnakeGrid1[1][0] - 1;
      SnakeGrid1[1][0] = abs(SnakeGrid1[1][0] % 8);
      moveTime = currentTime;
    }
  }

  if (serialStuff == 'd') { // right
    if (currentTime - moveTime > 500) {
      SnakeGrid1[1][0] = SnakeGrid1[1][0] + 1;
      SnakeGrid1[1][0] = SnakeGrid1[1][0] % 8;
      moveTime = currentTime;
    }
  }
}
void gameOver() {
  for (int i = 0; i < 8; i++) {
    for (int j = 0; j < 4; j++) {
      if (L[j][(i + offset) % 51]) { // modulo to not get out of bound in array. // check boolean too.
        pixels.setPixelColor(matrix[j][i], pixels.Color(255, 0, 0));
      }
    }
    if (currentTime - nameTime > 200) {
      offset++;
      if (offset > 51) offset = 0;
      nameTime = currentTime;
    }
  }
}

void youWin() {
  for (int i = 0; i < 8; i++) {
    for (int j = 0; j < 4; j++) {
      if (W[j][(i + offset) % 35]) { // modulo to not get out of bound in array. // check boolean too.
        pixels.setPixelColor(matrix[j][i], pixels.Color(0, 255, 0));
      }
    }
    if (currentTime - nameTime > 200) {
      offset++;
      if (offset > 35) offset = 0;
      nameTime = currentTime;
    }
  }
}

void food() {
  pixels.setPixelColor(matrix[a][b], pixels.Color(0, 255, 0));
} 

Reflection

I choose to create a playable Snake game as a way to appreciate the complication that many game developers go through. I was not successful in creating a fully playable snake game on the LEDs. There were many complications with massive array lists and timer so there delays in creating snake tails. As a result, I embrace this inefficiency in my code and create a Snake Game that you win or lose in random after certain amount of food eaten. I believe there is a lot of other ways to approach this project and I should have plan the overall base of the game better. I used red as the snake and green as food which represent apple. 

Back to the Top

 

 

 

Week 6

Inspiration

I was inspired by the art of creating sound effects for film. The video "The Foley Artist" shows us how sound effects are made and how unusual items are used to create different sounds. I love the creativity behind the unrelated aspect between the visual and audio. Therefore, I tried to create the gear changing, and racing sound of a car with my fan.  

Progress and Process

unsigned long currentTime;
unsigned long lastTime = 0;
int delay1 = 100;
int delay2 = 1000;
bool next = 0;

void setup() {
// put your setup code here, to run once:
pinMode(5, OUTPUT); //Unset //NC //Red light
pinMode(6, OUTPUT); //Set //NO //Green light
}

void loop() {
currentTime = millis();
if (next) {
delay1 = delay1 + 10;
delay2 = delay1 + 100;
next = 0;
}
if (delay1 == 200 && delay2 == 10000) {
delay1 = 100;
delay2 = 1000;
}

if (currentTime - lastTime < delay1) {
digitalWrite(5, LOW);
digitalWrite(6, HIGH);
}
else if (currentTime - lastTime > delay1 && currentTime - lastTime < delay2) {
digitalWrite(6, LOW);
digitalWrite(5, HIGH);
}
else {
lastTime = currentTime;
next = 1;
}

}

Reflection

I believe the relay ability to flip on and off create this nice effect of changing gear so I went to create the changing gear sound that mimicked the car. I used linear increase in both on and off time. For the on time the range is from 100 to 200 and it increases at an increment of 10. For the off time the range is from 1000 to 10000 and it increases at an increment of 100. This is more realistic to car as if you go to higher gear, you tend to stay longer in that gear. The visual effect of the fan might not replicate the car motor but i do believe the switch flipping and fan turning make it sound like you are switching through gear. In order to make this better, I could find the exponential equation that might fit in better with the gear change instead of the linear approach. 

Back to the Top

 

 

 

Week 7

Inspiration

Link: http://pandalabccc.blogspot.com/2010/07/spiralwall-final-arduino-processing.html

Initially, I wanted to create a heart beating device that mimicked human heart. I had a hard time trying to achieve that using plastic and string so I tried to look at other approach to this. I found this video of Spiral Wall which is an exploration of form by compressing and retracting the small threads in circle formation. This Spiral Wall is developed by the P&A LAB (Programming and Architecture LAB). It looks like the compression and retraction looks like breathing. It might be more natural if they applied some form of nonlinear functions. As I explore

 

Progress and Process

#include <Adafruit_NeoPixel.h>
#include <Servo.h>

int NUM_LEDS = 1;
int LED_PIN = 6;

Servo myservo;

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800);

int pos = 0;
int R = 0;

unsigned long currentTime;
unsigned long lastTime = 0;
float freq;
float alt;

int sinePos;

void setup() {
myservo.attach(9, 500, 2400);

pixels.begin();
}

void loop() {
currentTime = millis();
freq = (cos(currentTime / 2500.0) + 2.0) * 50.0;
alt = (cos(currentTime / 2500.0)+ 1.0) * 90.0;
sinePos = (cos((currentTime - lastTime) / freq) + 1.0) * alt;

R = (cos((currentTime - lastTime) / freq) + 1.0) * 128;
pixels.setPixelColor(0, pixels.Color(R, 0, 0));
pixels.show();

}

Reflection

I wanted to explore the combination of sound, form, and light for this project. The mechanical sound of the Servo created this eerie industrial sound so I used the red color of Neopixel to match the sinister vibe of the sound. For the form, I wanted to explore the twisting and turning of threads. A cardboard platform was used as a base for the thread. I used conductive thread as I thought it would provide more reflection for the red LED. However, it was not the case and the thread was completely dark when the light was off. I used cosine to create an increasing and decreasing frequency and alt for the angle position (sinePOS). As the freq and alt increased, the servo turned at a wider angle with a slower pace. As the angle decreased, it became extremely fast and this caused vibrations at the origin (0 degree) point. I also used the same function for the LED so it matched that value of the servo turns. As the servo turned left, the LED lighted up and when it turned right, it turned off. I could improve the turning of the servo overtime as it jittered as over a long period of time.

Back to the Top

 

 

 

Week 8

Inspiration

Link: https://www.thingiverse.com/thing:1069256

I was inspired by this self-balancing two wheel robot that uses servo motor and algorithm to move and balance itself. The robot was more complex as it have robotics circuit board and Accelerometers & Gyro board to measure and balance the robot so it will not topple. The robot also have wifi module which allow it to be wireless and can be easily control by a controller. I am impressed by how easy it is to make robots now compare to a decade ago.

Progress and Process

Github Link: https://github.com/weiweikee/StepperMotor_DanceBot

This is the Dancing Robot that I shown in last which uses two stepper motor to move. I created the wheel by 3D Printing the same wheel from a project that I was inspired from (above). I took design inspiration from the bottom part of the robot because I did not want to make my robot heavy as I would not have a balancing algorithm. The Dance moves were timed to 50 first seconds of the Evolution Dance.

Github Link: https://github.com/weiweikee/StepperMotor_ControlBot

I also make another version of the code that allow me to control the Robot by the serial port. 

Reflection

I believe I put the 2 servo motor to a great use and incorporate element of physical computing and robotic to create this project. I wish I could have make a balancing algorithm to create more stable form for the robot because the weight of the cable make it lean backward. The exploration of different speed and steps help me explores different spins and movements. I can improved this project by making it wireless and putting a gyro and accelerometer to limit the speed and movement so it could balance better. Furthermore, I could mimicked the dance more if it was able to move 360 degree or more. 

Back to the Top

 

 

 

Week 9

Inspiration

Nintendo Power Gloves was flex sensor to create interactive video game console controller. Nintendo experiment with Power Gloves and Virtualy Boy were few of the company way to create new form of interaction through tangible and immersive media. Both of these were developed in the late 80s and early 90s. However, both were not really successful in creating the immersive experience they were meant to. This tangible interface shows a failure of application because the technology was not ready and the computer graphics were not fluid and fast enough. With limited data transfer speed in the consumer setting, it was hard to create a more responsive flex sensor at a cheap price. Now in the age, where the DIY components have more data transfer speed and are cheaper, we are able to create more fluid interfaces with microcontroller and computers. Furthermore, the computing power allows us to smooth the data as soon as it is received so it is easier for cheaper microcontroller to create these new interfaces. For my project, I was inspired the failure and the early attempts at VR gloves that did make it in consumer gaming community.

Progress and Process

Github Link: https://github.com/weiweikee/Flex_Sensor_NeoPixel_Test

Reflection

The flex sensor data was filtered and normalized through the moving average formula that averages 10 data points. This allows the curve to be have little outliers so the NeoPixel would not have sudden flashes. I believe this test was a success as the movement of the color through the color wheel were smooth. For the NeoPixel, I used HSB to create the smooth transition from on color to another.  Initially, I didn't bend the flex sensor to its maximum range so the transition between color were too fast. I changed that since then to find the full range of the flex sensor. 

Back to the Top

 

 

 

Week 10

Inspiration

For the bluetooth control project, I was using HC05 bluetooth module that can act as both the transmitter and the receiver. I used this because I want the bluetooth to connect from one Arduino to another Arduino. It was also a cheaper option. Many bluetooth module connect only to phone or computer because they are preset with an established platform. For the two bluetooth module to connect to each other, I needed to program the bluetooth module to automatically connect to each other when it is on. 

Progress and Process

Github Link: https://github.com/weiweikee/Bluetooth-HC-05-Test

This link include the code from the video example that I used to create the bluetooth connection and test its connection.

Reflection

It was interesting to learn that there was a two to three seconds delay when using ASCII numbers because of it have to send more information than just a byte number. The encoding and decoding process of ASCII numbers could also slow down the transmission of these data. Learning to program with a HC-05 was also a great learning experience. The amount of control we can have over protocols allow the project to module have have flexibility for many different projects.

Back to the Top

 

 

 

Final

DanceBot HC-05 have two parts: Accelerometer Control Gloves and 2 Wheel Dancing Bot. I used Arduino Nano for both of these as the HC05 bluetooth module requires 3.6V - 6V. Arduino Nano small size with it inclusion of 5V regulator make a great candidate for this project. Both of these Arduino are powered by a 9V battery.

2 Wheel Dancing Bot

The dancing bot was the same dancing bot from Week 8 with a improvement in the wheel base. The wheel base is now two 3D printed base which is stronger it can hold 3 boards and 2 battery. The dancing bot initially used Feather to operate the motor so the Feather wing was easy to connect. In order to connect to the Arduino Nano, it uses 3.3V, Ground, and I2C (SDA, SCL). The HC-05 was connected to the TX, RX, 5V, Ground of the Arduino nano. The serial port 38400 was used for both of the Arduino because it is the default port on the HC-05. 

Accelerometer Control Gloves

The accelerometer control gloves is also made with a Arduino Nano and LIS3DH 3 axis accelerometer. LIS3DH was connected through the I2C ports. I used the acceleration data for X, Y, Z to calculate the pitch and roll of the glove. First, I did a 50-50 low pass filter to even out the data. Then I used the calculation: 

roll = (atan2(fXg, fZg) * 180.0) / M_PI;

pitch = (atan2(-fYg, sqrt(fXg * fXg + fZg * fZg)) * 180.0) / M_PI;

The formula were derived from these post: 

https://theccontinuum.com/2012/09/24/arduino-imu-pitch-roll-from-accelerometer/

http://www.nxp.com/assets/documents/data/en/application-notes/AN3461.pdf

https://stackoverflow.com/questions/3755059/3d-accelerometer-calculate-the-orientation

 

These formula I believe estimate quite accurately for what I needed the gloves to do. I just needed the gloves to pass a threshold of certain angle to activate the control. I use the glove similar to a directional pad. Then the glove will send which state should the robot be in through the bluetooth. Hence there are only 4 states that will occur with this controller. 

Reflection

I believe the responsiveness of sending the different state was better than sending over the roll and pitch data which will create enormous delay with the bluetooth module. The 4 states react instantly with almost no delays. However, I believe I can make the project better if I have a 9-DOF Accel/Mag/Gyro+Temp sensors (https://www.adafruit.com/product/3387) which can be put on the Dancebot to create a self balancing algorithm. The Dancebot was heavier than the week 8 version because of the battery and a new base. In order to create a more stable movement, I must use the 9-DOF Accel/Mag/Gyro+Temp sensors to calculate the tilt to adjust speed when it is falling over. Furthermore, the constant speed sketch was not working so I could not make a purely directional Movebot. The constant speed sketch run the stepper motors one by one and not simultaneously so it would not move directionally. Furthermore, the Accel ConstantSpeed Sketch example does not work properly as the wheel spin at an extremely slow speed and it was stuttering. Even when the set speed was increased, it still run weird. 

Resources for Balancing Bot:

https://github.com/spin7ion/Wheelee

http://digituma.uma.pt/bitstream/10400.13/59/1/MestradoVictorAbreu.pdf

https://www.intorobotics.com/5-best-examples-build-diy-self-balancing-robot/

 

 

 

Cultural Event 1

mi tierra

IMG_3270.JPG
IMG_3279.JPG

Mi Tierra is a site specific art installation that explore spaces from the perspective of the 13 Latinx artist. The installations were in multimedia formats, which includes textiles, videos, animations, sculpture and other form of tangible site installation. A lot of the artworks talk about the experience of place, identity, and culture behind the place that were experienced by the 13 Latinx artist. The topic ranged from colonization to gender rights that were experienced by both the Latinx and the native community. John Jota Leaños's Destinies Manifest (Video Above) was an animated installation that explore the idea of colonization in the lens of the native community. The animation show how the development of America was not all good as we imagined as we were forced out the native community.

Destinies Manifest was one of my favorite installation as it shows the alternative view of the development in the United State. The atrocities of forced development through the displacement of native communities is one of the few stories that is usually overshadowed by the accomplishment of the development. I believe this piece told the alternative story really well through animation and referencing the American Progress by John Gast. The name also came from the manifest destiny belief that believe that settlers were destined to expand to the west. This story not being told in the mainstream culture is one of the things that make this animation piece great. It conflict with our mainstream knowledge and culture that people know throughout the years. It gives another perspective of progress and development that we usually do not think through. Similar to the many current technological advancement without considering the holistic impact of these technology. For example, tracking and recommendation algorithm are few of technology we never stop to reconsider it long term holistic effect. 

Back to the Top

 

 

 

Cultural Event 2

Jeff Chang Talk

Harper Distinguished Speaker Series

18261063_3247837237273_786987693_o.jpg

Jeff Chang is an Executive Director of the Institute for Diversity in the Arts at Stanford University.  He was here at University of Denver for the 2017 Harper Distinguished Speaker. His journalist works revolves around culture, art, race, and civil rights. He talks about the history of segregation and its effect on the culture of minority groups such as African Americans. The context of the rap culture and the lyrics of the rap music came from the long history of segregation, inequality, and prejudices towards African Americans. He explain these in the context of both historical events (Martin Luther King Jr) and contemporary cultural icon (Kendrick Lamar). His Crisis Cycle process shows that these segregation and mistreatment are nothing new as we are stuck in this cycle. The Crisis Cycle goes from Crisis to Reaction to Backlash to Exhaustion and then back to Crisis. In order to fix this issue, we must break the cycle with equity not just superficial diversity. His process to do this includes Desegregate, Imagine, Organize, and Create.

I agree with a lot of his theory and process that explain the inequality and inequity of minority in the modern age. The Crisis Cycle is one the thing I definitely agree with as I see a lot of human process are cyclical. Everything from politics to technology moved in progressively cyclical fashion as things are rarely revolution or new. The currently backlash in the politics towards nationalism and racism seems like history repeating itself. The danger of nationalism is that it will create segregated homogenous communities in a connected globalized world. His talks about how rap culture relate back to all these historical events amazes me. In addition, his drive to create diversity in the field of art show that the field is still facing challenges in representation of minority groups. With the current political situation, I believe American's culture is at risk. In order to minimize these negative impacts, we must follow his process for achieving equity in this modern age. 

Back to the Top

 

 

 

Cultural Event 3

Crafting Computers, Crafting Cultures by Irene Posch

Irene Posch is a researcher and artist based in Vienna, Austria. Irene Posch's researches and arts are based on computational textile which is one of the emerging field in both sciences and arts. Her works combine the art of textile with the science of computational methods. He explores the computational bit and data in the form of textile. As computer switches and transistors start to become at the nano scale, the tangible aspect of these computer start to fade. Irene Posch is trying to question this tangible aspect of computational methods by considering manual textile crafts as method for electronic and computational artifacts. Her current work consist of creating tools for physical computing and also textile computer. The picture shows the construction of computer bit in term of textile form. The video show the switching of bit from 1 to 0 and vice versa.

I believe her work create a new form of interdisciplinary field that intersect textile craft and computational methods. This emerging field along with the raise of wearables computing make these artifacts and research important. Her work on a bigger scale textile computing shows an alternative view on electronic and computational artifacts. Though it is not current practical to have function computing system with this new media, it still make us question the traditional form of computing that uses silicon chips and metal to create computer. Her work and research also make us think about other form of media that could mimicked the computational method of traditional computer. These emerging form of media will help create alternative form of computational media while question the traditional form of media. However, textile computing overarching concept is still limited by law of physics and traditional computing method that turn the switch on and off. 

Back to the Top