Programming Final – Strang

Our Research:

So we wanted to work on something like a clock. After Yue Ling and I looking at some online examples and ideas, we decided to settle on an infinity mirror with LED lights that changes as the user interacts with the clock.

As clock measures time, we wanted to play with the idea of a clock not measuring what it’s supposed to measure. So by changing the speed and colour of the clock through interaction, it will create an inaccurate idea of time, and as such, becomes an interesting observation of our relationship with interaction and time.

Our Proposal:

Our Project

Yue Ling and I went to Sim Lim and Art Friend to purchase the items, and after getting some help from Charissa, Jia Yi, Nok Wan, Mark, and Vienna, we managed to get the items we need!

Assembly

Fixing up the main structure of the clock

Applying of black one-way mirror film

After assembly, we put in the LED

The Prototype Code:

Yue Ling found an example online:

Guide for WS2812B Addressable RGB LED Strip with Arduino

With this example, we were able to use a timer to change the LED states, and as we are unable to find an elegant way of coding the colours to change smoothly, we have to create different set of colours and code different timings to different set of colours:

#include <FastLED.h>

#define LED_PIN 13
#define NUM_LEDS 51
#define BRIGHTNESS 200
#define LED_TYPE WS2811
#define COLOR_ORDER GRB
CRGB leds[NUM_LEDS];

#define UPDATES_PER_SECOND 100

CRGBPalette16 currentPalette;
TBlendType currentBlending;

extern CRGBPalette16 myRedWhiteBluePalette;
extern const TProgmemPalette16 myRedW4hiteBluePalette_p PROGMEM;

int x = 1000;
int xspeed = 100;
int p1, p2, p3;
int o1, o2, o3;

void setup() {
delay( 3000 ); // power-up safety delay
FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
FastLED.setBrightness( BRIGHTNESS );

// currentPalette = RainbowColors_p;
currentBlending = LINEARBLEND;
}

void loop()
{

ChangePalettePeriodically();

static uint8_t startIndex = 0;
startIndex = startIndex + 1;

FillLEDsFromPaletteColors( startIndex);

FastLED.show();
FastLED.delay(x / UPDATES_PER_SECOND);
}

void FillLEDsFromPaletteColors( uint8_t colorIndex)
{
uint8_t brightness = 255;

for ( int i = 0; i < NUM_LEDS; i++) {
leds[i] = ColorFromPalette( currentPalette, colorIndex, brightness, currentBlending);
colorIndex += 3;
}
}

void ChangePalettePeriodically()
{
uint8_t secondHand = (millis() / 1000) % 21;
static uint8_t lastSecond = 99;

if ( lastSecond != secondHand) {
lastSecond = secondHand;
if ( secondHand == 0) {
SetupPurpleAndGreenPalette();
currentBlending = LINEARBLEND;
}
if ( secondHand == 1) {
SetupPurpleAndGreenPalette();
currentBlending = LINEARBLEND;
}
if ( secondHand == 2) {
SetupPurpleAndGreenPalette2();
currentBlending = LINEARBLEND;
}
if ( secondHand == 3) {
SetupPurpleAndGreenPalette3();
currentBlending = LINEARBLEND;
}
if ( secondHand == 4) {
SetupPurpleAndGreenPalette4();
currentBlending = LINEARBLEND;
}
if ( secondHand == 5) {
SetupPurpleAndGreenPalette5();
currentBlending = LINEARBLEND;
}
if ( secondHand == 6) {
SetupPurpleAndGreenPalette6();
currentBlending = LINEARBLEND;
}
if ( secondHand == 7) {
SetupPurpleAndGreenPalette7();
currentBlending = LINEARBLEND;
}
if ( secondHand == 8) {
SetupPurpleAndGreenPalette8();
currentBlending = LINEARBLEND;
}
if ( secondHand == 9) {
SetupPurpleAndGreenPalette9();
currentBlending = LINEARBLEND;
}
if ( secondHand == 10) {
SetupPurpleAndGreenPalette10();
currentBlending = LINEARBLEND;
}
if ( secondHand == 11) {
SetupPurpleAndGreenPalette11();
currentBlending = LINEARBLEND;
}
if ( secondHand == 12) {
SetupPurpleAndGreenPalette10();
currentBlending = LINEARBLEND;
}
if ( secondHand == 13) {
SetupPurpleAndGreenPalette9();
currentBlending = LINEARBLEND;
}
if ( secondHand == 14) {
SetupPurpleAndGreenPalette8();
currentBlending = LINEARBLEND;
}
if ( secondHand == 15) {
SetupPurpleAndGreenPalette7();
currentBlending = LINEARBLEND;
}
if ( secondHand == 16) {
SetupPurpleAndGreenPalette6();
currentBlending = LINEARBLEND;
}
if ( secondHand == 17) {
SetupPurpleAndGreenPalette5();
currentBlending = LINEARBLEND;
}
if ( secondHand == 18) {
SetupPurpleAndGreenPalette4();
currentBlending = LINEARBLEND;
}
if ( secondHand == 19) {
SetupPurpleAndGreenPalette3();
currentBlending = LINEARBLEND;
}
if ( secondHand == 20) {
SetupPurpleAndGreenPalette2();
currentBlending = LINEARBLEND;
}
if ( secondHand == 21) {
SetupPurpleAndGreenPalette();
currentBlending = LINEARBLEND;
}
}
}

void SetupPurpleAndGreenPalette()
{
CRGB pink = CRGB( 250, 0, 100);
CRGB pink2 = CRGB( 225, 0, 100);
CRGB pink3 = CRGB( 200, 0, 100);
CRGB pink4 = CRGB( 175, 0, 100);
CRGB purple1 = CRGB( 150, 0, 100);
CRGB purple2 = CRGB( 125, 0, 100);
CRGB purple3 = CRGB( 75, 0, 100);
CRGB purple4 = CRGB( 75, 0, 125);
CRGB purple5 = CRGB( 75, 0, 150);
CRGB purple6 = CRGB( 75, 25, 150);
CRGB purple7 = CRGB( 75, 50, 150);
CRGB orange = CRGB( 250, 100, 50);
CRGB orange2 = CRGB(200, 100, 50);
CRGB orange3 = CRGB(150, 100, 50);
CRGB orange4 = CRGB(100, 100, 50);
CRGB orange5 = CRGB(50, 100, 50);
CRGB orange6 = CRGB(0, 100, 50);
CRGB orange7 = CRGB(0, 100, 100);
CRGB orange8 = CRGB(0, 100, 150);
CRGB orange9 = CRGB(0, 100, 175);
CRGB orange10 = CRGB(0, 100, 200);
CRGB orange11 = CRGB(0, 100, 250);
CRGB yellow = CRGB(255, 255, 0);
CRGB green = CRGB(100, 255, 0);
CRGB turquoise = CRGB(0, 255, 100);
CRGB grue = CRGB( 0, 100, 255);
CRGB purple = CRGB( 255, 100, 255);
CRGB black = CRGB::Black;
currentPalette = CRGBPalette16(
pink, pink, orange, orange,
orange, orange, pink, pink,
pink, pink, orange, orange,
orange, orange, pink, pink );
}

void SetupPurpleAndGreenPalette2()
{

CRGB pink = CRGB( 250, 0, 100);
CRGB pink2 = CRGB( 225, 0, 100);
CRGB pink3 = CRGB( 200, 0, 100);
CRGB pink4 = CRGB( 175, 0, 100);
CRGB purple1 = CRGB( 150, 0, 100);
CRGB purple2 = CRGB( 125, 0, 100);
CRGB purple3 = CRGB( 75, 0, 100);
CRGB purple4 = CRGB( 75, 0, 125);
CRGB purple5 = CRGB( 75, 0, 150);
CRGB purple6 = CRGB( 75, 25, 150);
CRGB purple7 = CRGB( 75, 50, 150);
CRGB orange = CRGB( 250, 100, 50);
CRGB orange2 = CRGB(200, 100, 50);
CRGB orange3 = CRGB(150, 100, 50);
CRGB orange4 = CRGB(100, 100, 50);
CRGB orange5 = CRGB(50, 100, 50);
CRGB orange6 = CRGB(0, 100, 50);
CRGB orange7 = CRGB(0, 100, 100);
CRGB orange8 = CRGB(0, 100, 150);
CRGB orange9 = CRGB(0, 100, 175);
CRGB orange10 = CRGB(0, 100, 200);
CRGB orange11 = CRGB(0, 100, 250);
CRGB yellow = CRGB(255, 255, 0);
CRGB green = CRGB(100, 255, 0);
CRGB turquoise = CRGB(0, 255, 100);
CRGB grue = CRGB( 0, 100, 255);
CRGB purple = CRGB( 255, 100, 255);
CRGB black = CRGB::Black;
currentPalette = CRGBPalette16(
pink2, pink2, orange2, orange2,
orange2, orange2, pink2, pink2,
pink2, pink2, orange2, orange2,
orange2, orange2, pink2, pink2 );
}

void SetupPurpleAndGreenPalette3()
{
CRGB pink = CRGB( 250, 0, 100);
CRGB pink2 = CRGB( 225, 0, 100);
CRGB pink3 = CRGB( 200, 0, 100);
CRGB pink4 = CRGB( 175, 0, 100);
CRGB purple1 = CRGB( 150, 0, 100);
CRGB purple2 = CRGB( 125, 0, 100);
CRGB purple3 = CRGB( 75, 0, 100);
CRGB purple4 = CRGB( 75, 0, 125);
CRGB purple5 = CRGB( 75, 0, 150);
CRGB purple6 = CRGB( 75, 25, 150);
CRGB purple7 = CRGB( 75, 50, 150);
CRGB orange = CRGB( 250, 100, 50);
CRGB orange2 = CRGB(200, 100, 50);
CRGB orange3 = CRGB(150, 100, 50);
CRGB orange4 = CRGB(100, 100, 50);
CRGB orange5 = CRGB(50, 100, 50);
CRGB orange6 = CRGB(0, 100, 50);
CRGB orange7 = CRGB(0, 100, 100);
CRGB orange8 = CRGB(0, 100, 150);
CRGB orange9 = CRGB(0, 100, 175);
CRGB orange10 = CRGB(0, 100, 200);
CRGB orange11 = CRGB(0, 100, 250);
CRGB yellow = CRGB(255, 255, 0);
CRGB green = CRGB(100, 255, 0);
CRGB turquoise = CRGB(0, 255, 100);
CRGB grue = CRGB( 0, 100, 255);
CRGB purple = CRGB( 255, 100, 255);
CRGB black = CRGB::Black;
currentPalette = CRGBPalette16(
pink3, pink3, orange3, orange3,
orange3, orange3, pink3, pink3,
pink3, pink3, orange3, orange3,
orange3, orange3, pink3, pink3 );
}
void SetupPurpleAndGreenPalette4()
{
CRGB pink = CRGB( 250, 0, 100);
CRGB pink2 = CRGB( 225, 0, 100);
CRGB pink3 = CRGB( 200, 0, 100);
CRGB pink4 = CRGB( 175, 0, 100);
CRGB purple1 = CRGB( 150, 0, 100);
CRGB purple2 = CRGB( 125, 0, 100);
CRGB purple3 = CRGB( 75, 0, 100);
CRGB purple4 = CRGB( 75, 0, 125);
CRGB purple5 = CRGB( 75, 0, 150);
CRGB purple6 = CRGB( 75, 25, 150);
CRGB purple7 = CRGB( 75, 50, 150);
CRGB orange = CRGB( 250, 100, 50);
CRGB orange2 = CRGB(200, 100, 50);
CRGB orange3 = CRGB(150, 100, 50);
CRGB orange4 = CRGB(100, 100, 50);
CRGB orange5 = CRGB(50, 100, 50);
CRGB orange6 = CRGB(0, 100, 50);
CRGB orange7 = CRGB(0, 100, 100);
CRGB orange8 = CRGB(0, 100, 150);
CRGB orange9 = CRGB(0, 100, 175);
CRGB orange10 = CRGB(0, 100, 200);
CRGB orange11 = CRGB(0, 100, 250);
CRGB yellow = CRGB(255, 255, 0);
CRGB green = CRGB(100, 255, 0);
CRGB turquoise = CRGB(0, 255, 100);
CRGB grue = CRGB( 0, 100, 255);
CRGB purple = CRGB( 255, 100, 255);
CRGB black = CRGB::Black;
currentPalette = CRGBPalette16(
pink4, pink4, orange4, orange4,
orange4, orange4, pink4, pink4,
pink4, pink4, orange4, orange4,
orange4, orange4, pink4, pink4 );
}

void SetupPurpleAndGreenPalette5()
{
CRGB pink = CRGB( 250, 0, 100);
CRGB pink2 = CRGB( 225, 0, 100);
CRGB pink3 = CRGB( 200, 0, 100);
CRGB pink4 = CRGB( 175, 0, 100);
CRGB purple1 = CRGB( 150, 0, 100);
CRGB purple2 = CRGB( 125, 0, 100);
CRGB purple3 = CRGB( 75, 0, 100);
CRGB purple4 = CRGB( 75, 0, 125);
CRGB purple5 = CRGB( 75, 0, 150);
CRGB purple6 = CRGB( 75, 25, 150);
CRGB purple7 = CRGB( 75, 50, 150);
CRGB orange = CRGB( 250, 100, 50);
CRGB orange2 = CRGB(200, 100, 50);
CRGB orange3 = CRGB(150, 100, 50);
CRGB orange4 = CRGB(100, 100, 50);
CRGB orange5 = CRGB(50, 100, 50);
CRGB orange6 = CRGB(0, 100, 50);
CRGB orange7 = CRGB(0, 100, 100);
CRGB orange8 = CRGB(0, 100, 150);
CRGB orange9 = CRGB(0, 100, 175);
CRGB orange10 = CRGB(0, 100, 200);
CRGB orange11 = CRGB(0, 100, 250);
CRGB yellow = CRGB(255, 255, 0);
CRGB green = CRGB(100, 255, 0);
CRGB turquoise = CRGB(0, 255, 100);
CRGB grue = CRGB( 0, 100, 255);
CRGB purple = CRGB( 255, 100, 255);
CRGB black = CRGB::Black;
currentPalette = CRGBPalette16(
purple1, purple1, orange5, orange5,
orange5, orange5, purple1, purple1,
purple1, purple1, orange5, orange5,
orange5, orange5, purple1, purple1 );

}

void SetupPurpleAndGreenPalette6()
{
CRGB pink = CRGB( 250, 0, 100);
CRGB pink2 = CRGB( 225, 0, 100);
CRGB pink3 = CRGB( 200, 0, 100);
CRGB pink4 = CRGB( 175, 0, 100);
CRGB purple1 = CRGB( 150, 0, 100);
CRGB purple2 = CRGB( 125, 0, 100);
CRGB purple3 = CRGB( 75, 0, 100);
CRGB purple4 = CRGB( 75, 0, 125);
CRGB purple5 = CRGB( 75, 0, 150);
CRGB purple6 = CRGB( 75, 25, 150);
CRGB purple7 = CRGB( 75, 50, 150);
CRGB orange = CRGB( 250, 100, 50);
CRGB orange2 = CRGB(200, 100, 50);
CRGB orange3 = CRGB(150, 100, 50);
CRGB orange4 = CRGB(100, 100, 50);
CRGB orange5 = CRGB(50, 100, 50);
CRGB orange6 = CRGB(0, 100, 50);
CRGB orange7 = CRGB(0, 100, 100);
CRGB orange8 = CRGB(0, 100, 150);
CRGB orange9 = CRGB(0, 100, 175);
CRGB orange10 = CRGB(0, 100, 200);
CRGB orange11 = CRGB(0, 100, 250);
CRGB yellow = CRGB(255, 255, 0);
CRGB green = CRGB(100, 255, 0);
CRGB turquoise = CRGB(0, 255, 100);
CRGB grue = CRGB( 0, 100, 255);
CRGB purple = CRGB( 255, 100, 255);
CRGB black = CRGB::Black;
currentPalette = CRGBPalette16(
purple2, purple2, orange6, orange6,
orange6, orange6, purple2, purple2,
purple2, purple2, orange6, orange6,
orange6, orange6, purple2, purple2 );

}

void SetupPurpleAndGreenPalette7()
{
CRGB pink = CRGB( 250, 0, 100);
CRGB pink2 = CRGB( 225, 0, 100);
CRGB pink3 = CRGB( 200, 0, 100);
CRGB pink4 = CRGB( 175, 0, 100);
CRGB purple1 = CRGB( 150, 0, 100);
CRGB purple2 = CRGB( 125, 0, 100);
CRGB purple3 = CRGB( 75, 0, 100);
CRGB purple4 = CRGB( 75, 0, 125);
CRGB purple5 = CRGB( 75, 0, 150);
CRGB purple6 = CRGB( 75, 25, 150);
CRGB purple7 = CRGB( 75, 50, 150);
CRGB orange = CRGB( 250, 100, 50);
CRGB orange2 = CRGB(200, 100, 50);
CRGB orange3 = CRGB(150, 100, 50);
CRGB orange4 = CRGB(100, 100, 50);
CRGB orange5 = CRGB(50, 100, 50);
CRGB orange6 = CRGB(0, 100, 50);
CRGB orange7 = CRGB(0, 100, 100);
CRGB orange8 = CRGB(0, 100, 150);
CRGB orange9 = CRGB(0, 100, 175);
CRGB orange10 = CRGB(0, 100, 200);
CRGB orange11 = CRGB(0, 100, 250);
CRGB yellow = CRGB(255, 255, 0);
CRGB green = CRGB(100, 255, 0);
CRGB turquoise = CRGB(0, 255, 100);
CRGB grue = CRGB( 0, 100, 255);
CRGB purple = CRGB( 255, 100, 255);
CRGB black = CRGB::Black;
currentPalette = CRGBPalette16(
purple3, purple3, orange7, orange7,
orange7, orange7, purple3, purple3,
purple3, purple3, orange7, orange7,
orange7, orange7, purple3, purple3 );

}

void SetupPurpleAndGreenPalette8()
{
CRGB pink = CRGB( 250, 0, 100);
CRGB pink2 = CRGB( 225, 0, 100);
CRGB pink3 = CRGB( 200, 0, 100);
CRGB pink4 = CRGB( 175, 0, 100);
CRGB purple1 = CRGB( 150, 0, 100);
CRGB purple2 = CRGB( 125, 0, 100);
CRGB purple3 = CRGB( 75, 0, 100);
CRGB purple4 = CRGB( 75, 0, 125);
CRGB purple5 = CRGB( 75, 0, 150);
CRGB purple6 = CRGB( 75, 25, 150);
CRGB purple7 = CRGB( 75, 50, 150);
CRGB orange = CRGB( 250, 100, 50);
CRGB orange2 = CRGB(200, 100, 50);
CRGB orange3 = CRGB(150, 100, 50);
CRGB orange4 = CRGB(100, 100, 50);
CRGB orange5 = CRGB(50, 100, 50);
CRGB orange6 = CRGB(0, 100, 50);
CRGB orange7 = CRGB(0, 100, 100);
CRGB orange8 = CRGB(0, 100, 150);
CRGB orange9 = CRGB(0, 100, 175);
CRGB orange10 = CRGB(0, 100, 200);
CRGB orange11 = CRGB(0, 100, 250);
CRGB yellow = CRGB(255, 255, 0);
CRGB green = CRGB(100, 255, 0);
CRGB turquoise = CRGB(0, 255, 100);
CRGB grue = CRGB( 0, 100, 255);
CRGB purple = CRGB( 255, 100, 255);
CRGB black = CRGB::Black;
currentPalette = CRGBPalette16(
purple4, purple4, orange8, orange8,
orange8, orange8, purple4, purple4,
purple4, purple4, orange8, orange8,
orange8, orange8, purple4, purple4 );

}

void SetupPurpleAndGreenPalette9()
{
CRGB pink = CRGB( 250, 0, 100);
CRGB pink2 = CRGB( 225, 0, 100);
CRGB pink3 = CRGB( 200, 0, 100);
CRGB pink4 = CRGB( 175, 0, 100);
CRGB purple1 = CRGB( 150, 0, 100);
CRGB purple2 = CRGB( 125, 0, 100);
CRGB purple3 = CRGB( 75, 0, 100);
CRGB purple4 = CRGB( 75, 0, 125);
CRGB purple5 = CRGB( 75, 0, 150);
CRGB purple6 = CRGB( 75, 25, 150);
CRGB purple7 = CRGB( 75, 50, 150);
CRGB orange = CRGB( 250, 100, 50);
CRGB orange2 = CRGB(200, 100, 50);
CRGB orange3 = CRGB(150, 100, 50);
CRGB orange4 = CRGB(100, 100, 50);
CRGB orange5 = CRGB(50, 100, 50);
CRGB orange6 = CRGB(0, 100, 50);
CRGB orange7 = CRGB(0, 100, 100);
CRGB orange8 = CRGB(0, 100, 150);
CRGB orange9 = CRGB(0, 100, 175);
CRGB orange10 = CRGB(0, 100, 200);
CRGB orange11 = CRGB(0, 100, 250);
CRGB yellow = CRGB(255, 255, 0);
CRGB green = CRGB(100, 255, 0);
CRGB turquoise = CRGB(0, 255, 100);
CRGB grue = CRGB( 0, 100, 255);
CRGB purple = CRGB( 255, 100, 255);
CRGB black = CRGB::Black;
currentPalette = CRGBPalette16(
purple5, purple5, orange9, orange9,
orange9, orange9, purple5, purple5,
purple5, purple5, orange9, orange9,
orange9, orange9, purple5, purple5);
}

void SetupPurpleAndGreenPalette10()
{
CRGB pink = CRGB( 250, 0, 100);
CRGB pink2 = CRGB( 225, 0, 100);
CRGB pink3 = CRGB( 200, 0, 100);
CRGB pink4 = CRGB( 175, 0, 100);
CRGB purple1 = CRGB( 150, 0, 100);
CRGB purple2 = CRGB( 125, 0, 100);
CRGB purple3 = CRGB( 75, 0, 100);
CRGB purple4 = CRGB( 75, 0, 125);
CRGB purple5 = CRGB( 75, 0, 150);
CRGB purple6 = CRGB( 75, 25, 150);
CRGB purple7 = CRGB( 75, 50, 150);
CRGB orange = CRGB( 250, 100, 50);
CRGB orange2 = CRGB(200, 100, 50);
CRGB orange3 = CRGB(150, 100, 50);
CRGB orange4 = CRGB(100, 100, 50);
CRGB orange5 = CRGB(50, 100, 50);
CRGB orange6 = CRGB(0, 100, 50);
CRGB orange7 = CRGB(0, 100, 100);
CRGB orange8 = CRGB(0, 100, 150);
CRGB orange9 = CRGB(0, 100, 175);
CRGB orange10 = CRGB(0, 100, 200);
CRGB orange11 = CRGB(0, 100, 250);
CRGB yellow = CRGB(255, 255, 0);
CRGB green = CRGB(100, 255, 0);
CRGB turquoise = CRGB(0, 255, 100);
CRGB grue = CRGB( 0, 100, 255);
CRGB purple = CRGB( 255, 100, 255);
CRGB black = CRGB::Black;
currentPalette = CRGBPalette16(
purple6, purple6, orange10, orange10,
orange10, orange10, purple6, purple6,
purple6, purple6, orange10, orange10,
orange10, orange10, purple6, purple6);
}

void SetupPurpleAndGreenPalette11()
{
CRGB pink = CRGB( 250, 0, 100);
CRGB pink2 = CRGB( 225, 0, 100);
CRGB pink3 = CRGB( 200, 0, 100);
CRGB pink4 = CRGB( 175, 0, 100);
CRGB purple1 = CRGB( 150, 0, 100);
CRGB purple2 = CRGB( 125, 0, 100);
CRGB purple3 = CRGB( 75, 0, 100);
CRGB purple4 = CRGB( 75, 0, 125);
CRGB purple5 = CRGB( 75, 0, 150);
CRGB purple6 = CRGB( 75, 25, 150);
CRGB purple7 = CRGB( 75, 50, 150);
CRGB orange = CRGB( 250, 100, 50);
CRGB orange2 = CRGB(200, 100, 50);
CRGB orange3 = CRGB(150, 100, 50);
CRGB orange4 = CRGB(100, 100, 50);
CRGB orange5 = CRGB(50, 100, 50);
CRGB orange6 = CRGB(0, 100, 50);
CRGB orange7 = CRGB(0, 100, 100);
CRGB orange8 = CRGB(0, 100, 150);
CRGB orange9 = CRGB(0, 100, 175);
CRGB orange10 = CRGB(0, 100, 200);
CRGB orange11 = CRGB(0, 100, 250);
CRGB yellow = CRGB(255, 255, 0);
CRGB green = CRGB(100, 255, 0);
CRGB turquoise = CRGB(0, 255, 100);
CRGB grue = CRGB( 0, 100, 255);
CRGB purple = CRGB( 255, 100, 255);
CRGB black = CRGB::Black;
currentPalette = CRGBPalette16(
purple7, purple7, orange11, orange11,
orange11, orange11, purple7, purple7,
purple7, purple7, orange11, orange11,
orange11, orange11, purple7, purple7);
}

As you can see, we created combinations of different colours manually, which is not practical. We hope to improve on this.

Prototype outcome:

So I tried to fix everything up and here is the result:

Ultrasound

So Brendan worked on the ultrasonic sensors after looking through some codes online:

https://create.arduino.cc/projecthub/unexpectedmaker/ultrasoniceyes-b9fd38?ref=tag&ref_id=ultrasonic&offset=2

https://www.hackster.io/gowrisomanath/the-positronic-brain-my-techno-heart-9084be

He made a code that detects distance based on how far an object is in CM

const int trigPin = 9;
const int echoPin = 10;
const int ledPin = 13;

// defines variables
long duration;//travel time
int distance;//travel distance
int safetyDistance;

void setup() {
pinMode(trigPin, OUTPUT); // sets the trigPin as an Output
pinMode(echoPin, INPUT); // sets the echoPin as an Input
pinMode(ledPin, OUTPUT);
Serial.begin(9600); // Starts the serial communication for serial monitor
}
void loop() {
// Check trigPin
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
//generate ltrasound wave at high state
// Sets the trigPin on HIGH state for 10 micro seconds
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);

// reads the echoPin, read the sound wave travel time
duration = pulseIn(echoPin, HIGH);
// Calculating the distance
distance= duration*0.034/2;
//blinker
safetyDistance = distance;
if (safetyDistance <= 20) {
digitalWrite(ledPin, HIGH);
}
else{
digitalWrite(ledPin, LOW);
}
Serial.print("Distance: ");
Serial.println(distance);

}

With this code, we merged the lights code with the ultrasonic sensor code and simplified it to be slightly more elegant:

const int trigPin = 9;
const int echoPin = 10;
const int ledPin = 13;
const int flexPin = A0; //pin A0 to read analog input

// defines variables
long duration;//travel time
int distance;//travel distance
int safetyDistance;
int value; //save analog value

#include <FastLED.h>

#define LED_PIN 13
#define NUM_LEDS 51
#define BRIGHTNESS 200
#define LED_TYPE WS2811
#define COLOR_ORDER GRB
CRGB leds[NUM_LEDS];

#define UPDATES_PER_SECOND 100

CRGBPalette16 currentPalette;
TBlendType currentBlending;

extern CRGBPalette16 myRedWhiteBluePalette;
extern const TProgmemPalette16 myRedWhiteBluePalette_p PROGMEM;

int x;
int a, b, c;
int d, e, f;
int col1, col2;

void setup() {
pinMode(trigPin, OUTPUT); // sets the trigPin as an Output
pinMode(echoPin, INPUT); // sets the echoPin as an Input
pinMode(ledPin, OUTPUT);
Serial.begin(9600); // Starts the serial communication for serial monitor

FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
FastLED.setBrightness( BRIGHTNESS );

// currentPalette = RainbowColors_p;
currentBlending = LINEARBLEND;

}

void loop() {

value = analogRead(flexPin); //Read and save analog value from potentiometer
Serial.println(value); //Print value
value = map(value, 700, 900, 0, 255);//Map value 0-1023 to 0-255 (PWM)

// Check trigPin
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
//generate ltrasound wave at high state
// Sets the trigPin on HIGH state for 10 micro seconds
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);

// reads the echoPin, read the sound wave travel time
duration = pulseIn(echoPin, HIGH);
// Calculating the distance
distance= duration*0.034/2;
//blinker
safetyDistance = distance;

Serial.print("Distance: ");
Serial.println(distance);

ChangePalettePeriodically();
static uint8_t startIndex = 0;
startIndex = startIndex + 1;

FillLEDsFromPaletteColors( startIndex);

FastLED.show();
FastLED.delay(x / UPDATES_PER_SECOND);
}

void FillLEDsFromPaletteColors( uint8_t colorIndex)
{
uint8_t brightness = 255;

for ( int i = 0; i < NUM_LEDS; i++) {
leds[i] = ColorFromPalette( currentPalette, colorIndex, brightness, currentBlending);
colorIndex += 3;
}
}

void ChangePalettePeriodically()
{
// uint8_t secondHand = (millis() / 1000) % 21;
// static uint8_t lastSecond = 99;

// if ( lastSecond != secondHand) {
// lastSecond = secondHand;
SetupPurpleAndGreenPalette();
currentBlending = LINEARBLEND;
if (safetyDistance >= 30) {
x=500;
a = 250;
b = 0;
c = 100;
d = 250;
e = 100;
f = 50;
}
if (safetyDistance <=29) {
x=800;
a = 225;
b = 0;
c = 100;
d = 200;
e = 100;
f = 50;
}
if (safetyDistance <=26) {
x=1200;
a = 200;
b = 0;
c = 100;
d = 150;
e = 100;
f = 50;
}
if (safetyDistance <=23) {
x=1500;
a = 175;
b = 0;
c = 100;
d = 100;
e = 100;
f = 50;
}
if (safetyDistance <=20) {
x=1800;
a = 150;
b = 0;
c = 100;
d = 50;
e = 100;
f = 50;
}
if (safetyDistance <=17) {
x=2200;
a = 125;
b = 0;
c = 100;
d = 0;
e = 100;
f = 50;
}
if (safetyDistance <=14) {
x=2500;
a = 75;
b = 0;
c = 100;
d = 0;
e = 100;
f = 50;
}
if (safetyDistance <=11) {
x=2800;
a = 75;
b = 0;
c = 125;
d = 0;
e = 100;
f = 100;
}
if (safetyDistance <=8) {
x=3200;
a = 75;
b = 0;
c = 150;
d = 0;
e = 100;
f = 150;
}
if (safetyDistance <=5) {
x=3500;
a = 75;
b = 25;
c = 150;
d = 0;
e = 100;
f = 200;
}
if (safetyDistance <=2) {
x=3800;
a = 75;
b = 50;
c = 150;
d = 0;
e = 100;
f = 250;
}
}

void SetupPurpleAndGreenPalette()
{
CRGB col1 = CRGB( a, b, c);
CRGB col2 = CRGB( d, e, f);

CRGB pink3 = CRGB( 200, 0, 100);
CRGB pink4 = CRGB( 175, 0, 100);
CRGB purple1 = CRGB( 150, 0, 100);
CRGB purple2 = CRGB( 125, 0, 100);
CRGB purple3 = CRGB( 75, 0, 100);
CRGB purple4 = CRGB( 75, 0, 125);
CRGB purple5 = CRGB( 75, 0, 150);
CRGB purple6 = CRGB( 75, 25, 150);
CRGB purple7 = CRGB( 75, 50, 150);
CRGB orange = CRGB( 250, 100, 50);
CRGB orange2 = CRGB(200, 100, 50);
CRGB orange3 = CRGB(150, 100, 50);
CRGB orange4 = CRGB(100, 100, 50);
CRGB orange5 = CRGB(50, 100, 50);
CRGB orange6 = CRGB(0, 100, 50);
CRGB orange7 = CRGB(0, 100, 100);
CRGB orange8 = CRGB(0, 100, 150);
CRGB orange9 = CRGB(0, 100, 175);
CRGB orange10 = CRGB(0, 100, 200);
CRGB orange11 = CRGB(0, 100, 250);
CRGB yellow = CRGB(255, 255, 0);
CRGB green = CRGB(100, 255, 0);
CRGB turquoise = CRGB(0, 255, 100);
CRGB grue = CRGB( 0, 100, 255);
CRGB purple = CRGB( 255, 100, 255);
CRGB black = CRGB::Black;
currentPalette = CRGBPalette16(
col1, col1, col2, col2,
col2, col2, col1, col1,
col1, col1, col2, col2,
col1, col1, col2, col2);
}

Motors + Flex

Brendan went back to fix the motors up with the second part of our project which is to make the screen move. We also went to the film store to borrow some flex sensors.

It was really difficult to connect everything as we have so many wires that are too loose. Eventually, we managed to put everything up and taped the wires down.

Yue Ling found a code for the motors and we merged it with a flex sensor code such that the motor will move directly proportionate to the flex’s bend.

/* Sweep
by BARRAGAN <http://barraganstudio.com>
This example code is in the public domain.

modified 8 Nov 2013
by Scott Fitzgerald
http://www.arduino.cc/en/Tutorial/Sweep
*/

#include <Servo.h>

const int flexPin = A0; //pin A0 to read analog input
int value; //save analog value

Servo myservo; // create servo object to control a servo
// twelve servo objects can be created on most boards

int pos = 0; // variable to store the servo position

void setup() {
Serial.begin(9600); //Begin serial communication
myservo.attach(9); // attaches the servo on pin 9 to the servo object
}

void loop() {

value = analogRead(flexPin); //Read and save analog value from potentiometer
Serial.println(value); //Print value
value = map(value, 400, 500, 0, 180);//Map value 0-1023 to 0-255 (PWM)

//if(value < 399){

myservo.write(value);
// pos = 0;
// pos--;
// delay(1);
}

//if(value> 400){bb
// value = map(value, 700, 900, 0, 255);//Map value 0-1023 to 0-255 (PWM)

//pos+=3;
// myservo.write(pos); // tell servo to go to position in variable 'pos'
// delay(1); // waits 15ms for the servo to reach the position
// }
//}

So with both parts complete, we fixed up the box. The wiring was a major headache for us as we do not have the correct kit and enough wires. We managed to fix everything after much troubles. Yue Ling also borrowed female-to-male wires from Vienna which is a great help! Without that, we would not be able to connect our flex sensors and our ultrasonic sensors.

Unfortunately we don’t have an image of our final wirings.

Final Model

Before placing hand inside (lights)
Before placing hand inside (motor)
After placing hand inside (lights)
After placing hand inside (motor)

Video demonstration:

 

Concept is that by putting your hand through the hole, we bend space and time. Bending time is through slowing down of the rotation of the ‘clock’ as well as turning the colours from pink/orange to purple/blue, which began from the idea of ‘blue shifting’ like how light will look like if time slows down.

By pushing the fabric at the end of the installation, the motors move, emulating fingers that seems like as if the user’s hands have traversed through a wormhole into another location.

The overall feeling we aimed to get is the sense of amazement from the shifting in colours and also being able to teleport their hands through space.

Presentation Slides:

https://docs.google.com/presentation/d/1QqwL3OJHkvuKO2NJf1szHjSbgNvObOalTWKNzutuSV4/edit?usp=sharing


Problems Encountered

  1. LED lights code settings could be better, as we don’t know how to make it smoothly transit between colours. We could possibly make the value from the distance detected by the ultrasonic sensors directly control the colour range, but we don’t know how to do that so that can be an area of improvement.
  2. Circuit is a very big mess for us and we don’t have the right kits provided so we have to keep sourcing from our friends. We could have bought a long roll of wire so we can have all the wire we need and not use tiny short wires which breaks the circuit easily.
  3. We bought some wrong items along the way too, like the acrylic piece that is in front of the clock, we accidentally bought a matt acrylic. We had some difficulty finding the correct LED too and it was thanks to Vienna who helped us with where we can get it.
  4. Ultrasonic Sensor is buggy and there is no solution to fixing it. We speculate that it was because of bad wiring that it kept reading weird readings once in a while.
  5. The ‘fingers’ stuck on the motor wasn’t really sticking well and if we had more time, we would have improved it by securing it better.

What I learnt:

I learnt to control the motor using the flex sensor values, as well as how to work around a problem (the LED one) by manually writing individual code for individual colours. I’ve also learnt to use 4 different components and making them work together.

Tasks Deligation

Brendan:

  • Ultrasonic Sensors code + circuit
  • Motors setup
  • Fabric board assembly

Bryan:

  • LED code + circuit
  • motor circuit
  • general assembly and troubleshooting

Yue Ling:

  • Item sourcing
  • LED code + testing
  • Motors code + circuit

Hyperessay – teamLab, The Ultra-Technologists

teamLab founders Toshiyuki Inoko (left) and Takashi Kudo (right). Image taken from https://www.indesignlive.sg/people/5-minutes-with-teamlab-singapore

The Japanese collective and interdisciplinary company, teamLab, calls themselves ‘ultra-technologists,’ a statement that suggests their rejection of labels to their roles in the company, but instead an integrated community of creatives working together with a common goal. Started out as a small company in 2001 doing programming for clients, teamLab made it to the international scene after Singapore Biennale 2013 where they were given a special showcase in Singapore Art Museum with their project ‘If the World Changed‘.

Artwork showcased in the Singapore Biennale 2013

teamLab aims to achieve a balance between art, science, technology and creativity by creating interactive artwork using mostly spaces, digital media, and technology like augmented reality to engage their audiences. The idea is to allow for audience participation so as to remove the notion of artworks being static. teamLab strongly believes that an artwork should be interactive, as they believe that the experience of the artwork becomes much richer when there is participation, and that creates a collective experience that is much better than the singular experience static artworks can provide for viewers. By simply creating interaction, teamLab allows their participants to be connected to the artwork.

The teamLab work that I would be studying more in depth would be ‘The Infinite Crystal Universe‘, which is a large-spaced installation filled with rows of digitally controlled LED lights that streams down from the ceiling, essentially using pointillism to create a 3D space filled with ‘stars’ in a universe. The LED shimmers and reacts to audiences by proximity and by the interaction with the app that controls the installation. Ambient music also plays to add to the atmosphere. Within the artwork, one may feel like an adventurer stumbling upon a mysterious yet beautiful space.

The Infinite Crystal Universe, teamLab, 2015-2018, Interactive Installation of Light Sculpture, LED.
Image taken from https://www.teamlab.art/ew/infinite_crystaluniverse/

At first glance, one can tell how visually stunning the artwork is, perfect for audiences interacting with it through social media posting. The highlight comes when an audience uses a smartphone to control the artwork using an app.

Image taken from http://www.jetset-away.com/right-here-right-now/crystaluniverse

Through this action, the audience can choose an object to be sent out, which changes the music and allow the object to explode within the artwork into a spectacular LED light show that mimics galactic activities like supernovas. Within this interaction itself, the sender and the other audiences witnesses the spectacle made by the small action of a swipe. As the other audiences realise what they can do, they can start making their own objects and watching their creation blast into the universe and explode beautifully.

At its essence, the artwork encourages interaction through an awesome experience that connects everyone together in the same space, watching the same thing, feeling the same emotions. The artwork evoke a sense of how small we humans are in terms of the scale of the universe, yet one action made by us can impact everyone’s life so greatly. Without audiences, this artwork would not achieve the effect that it was made to express. As such, the artwork is very much in line with teamLab’s ideas of an interactive installation.

Image taken from https://mymodernmet.com/teamlab-crystal-universe/
Image taken from https://mymodernmet.com/teamlab-crystal-universe/
Image taken from https://mymodernmet.com/teamlab-crystal-universe/

In reference to Roy Ascott’s reading ‘Behavioural Art and the Cybernetic Vision’, ‘The Infinite Crystal Universe‘ exhibits some behavioural art characteristics. Firstly, the artwork allows for control and communication between the digital LEDs and the audience, and amongst audiences. The shift in the states of the LED cues the audiences to contemplate on the meaning behind the art, while also allows the audience to imagine the things they can do, while audiences can signal amongst themselves to teach each other on the artwork’s interactions. This feedback loop within said interactions and relationships, allows for the artwork to be in a constant state of change, keeping the artwork alive. Without the audience participation, the feedback loop would break, and the artwork would not function the way it should be. The artwork is also ambiguous, unstable, uncertain, and open-ended, which allows for a flexible interpretation as well as a flexible interaction. In this sense, the lines between art, artefact, and experience is blurred where audience and their experiences becomes part of the artwork.

John Cage’s ‘Variations V’. Image taken from http://www.medienkunstnetz.de/works/variations-v/

We can also see that teamLab also have very close visions with John Cage, which can be seen in his works ‘Variations V‘ where he made use of indeterminacy, chance, and unpredictability in his works to reimagine musical compositions, which is deemed too deterministic. By using chance to control musical composition, John Cage allowed the audience (the dancers) to not just be part of the artwork but also be essential for the artwork to exist. We can imagine the audiences in ‘The Infinite Crystal Universe‘ as the dancers in ‘Variations V‘, where the audience is given a set of choices, but their actions are completely unpredictable, while at the same time they become part of the artwork to make it alive. The artwork operates by chance, and through this controlled chance, audiences are encouraged to experiment with different combinations of objects to send out, and in whole, creates interaction. Although 50 years apart, we can draw similarities in the concepts of interactivity between both artworks.

teamLab’s ‘The Infinite Crystal Universe‘ exhibits both their own collective philosophy as well as important principles that characterises interactive art. Even though they are geographically and chronologically distant from previously studied interactive works, the principles still hold true. However,  there is also an evolution not just in terms of the technology used, but also in the way that people interact with the work. In our current society, social media is very prevalent and as such, artworks are made purposefully simple and photogenic for the purpose of being ‘Instagramable’. Artworks have thus incorporated this property and that added to another layer of interactivity. We have seen how teamLab have also included the idea of connectivity between audience and the art such that it could be easily understandable, which is absent from older forms of interactive art like John Cage’s ‘Variations V’.  As such, interactive artworks are still changing, and with the globalised society, the future of interactive art could become more and more advanced.

References:

teamlab planets tokyo: a ‘body immersive’ exhibition of all-encompassing digital art

http://exhibition.team-lab.net/siliconvalley/art/art01.html

https://planets.teamlab.art/tokyo/jp/ew/infinite_crystaluniverse/

https://www.vice.com/en_uk/article/bmyebv/inside-teamlab-stunning-crystal-universe-installation

https://www.ledinside.com/lighting/2016/7/teamlab_lighting_installation_invites_visitors_to_wander_through_the_crystal_universe

http://www.jetset-away.com/right-here-right-now/crystaluniverse

https://edition.cnn.com/style/article/teamlab-art-installation-tokyo/index.html

https://www.designboom.com/tag/teamlab/

https://www.wired.co.uk/article/teamlab-tokyo-head-office-design-art-experiment-invention

https://theartling.com/en/artzine/2016/5/18/interview-teamlab/

5 Minutes With… teamLab!

https://www.teamlab.art/jp

Interactive Installation Transports Viewers to Dazzling Universe of Infinite Lights

Hyperessay Key Work Selection: The Infinite Crystal Universe

I will be looking at the artwork ‘The Infinite Crystal Universe’ by teamLab.

Here’s the artwork description:

Pointillism uses an accumulation of distinct dots of color to create a picture, here light points are used to create three-dimensional objects. This interactive artwork expresses the universe through accumulated light points that spread infinitely in all directions.

People can use their smartphones to select elements that make up the universe by dragging them and releasing them into the The Infinite Crystal Universe. Each element released influences that of other elements and is influenced by the presence of people in the space. The work is created by people in the space and is thus continuously changing forever.


I really love love love this artwork because I also have a personal story tied with this artwork. I visited Art Science Museum alone before entering ADM after experiencing a down period of my life. It was a great experience going there alone as I have all the time to myself interacting with all the artworks.

The one that strike me most was, of course, this artwork. I walked through the curtains of LED thinking it would just be an “Instagram” artwork (seen it online too many times). When I reached the end, I saw an Ipad and the text description of the artwork, and decided to meddle with it. I apparently sent out a ‘star’ which appear in the artwork itself, and it exploded, creating a visual and auditory spectacle. Meanwhile, the crowd of photo-takers are just amazed by the change in environment, unaware that I, 1 person, with 1 swipe, just did all these. It was an overwhelming experience.

What I felt was that, with a small action, I can feel so powerful and yet also feel so lonely. I literally teared. Like really, words can’t describe what I felt.

SO. I feel so connected with this artwork and I also like astronomy so the whole idea of space, planets, and stars are very interesting to me.

The Infinite Crystal Universe, teamLab, 2015-2018, Interactive Installation of Light Sculpture, LED. Image taken from https://www.teamlab.art/ew/infinite_crystaluniverse/

I chose this artwork as its intend is not just straightforward, but also very impactful. My interpretation is that, on a personal level, we can see how small we all are, yet, how easily we can impact the world around us. On a whole, the interactivity is very apparent and forms some kind of relationship between the “universe maker” and the rest of the audience. There is some sense of immersion too, as audiences gets up close with the LEDs.


Through this artwork, teamLab expresses their method of creating immersive works that dissolve borders between viewer and works which allowed for quote: ‘continuous dynamic behavior, visual phenomena, and the ability to transform the canvas’. 

‘by doing so, the boundaries between the body and the work become ambiguous, which may become the starting point for people to think about their relationship with the world.

interactivity, immersion, constantly changing, feedback loop, audience > work > other audience > work > etc

teamlab planets tokyo: a ‘body immersive’ exhibition of all-encompassing digital art

http://exhibition.team-lab.net/siliconvalley/art/art01.html

https://planets.teamlab.art/tokyo/jp/ew/infinite_crystaluniverse/

https://www.vice.com/en_uk/article/bmyebv/inside-teamlab-stunning-crystal-universe-installation

https://www.ledinside.com/lighting/2016/7/teamlab_lighting_installation_invites_visitors_to_wander_through_the_crystal_universe

http://www.jetset-away.com/right-here-right-now/crystaluniverse

https://edition.cnn.com/style/article/teamlab-art-installation-tokyo/index.html

Manifesto – Do Not Make Fiction

Art will always be fiction, no matter how close to reality it will be, while design will always be a piece of reality to consumers, whether invisible or not. Do not make fiction.

Do not create works that, despite speaking so much, might as well spoke nothing. Do not make works with shallow ideas that has almost no meaningful impact, backed up by information that seems to make sense, but is inherently pointless. Do not justify your work with outdated ideas or the ‘-isms’, or get so inspired by them that you lose yourself. Instead, be mindful to your surroundings as to what is purposeful and reasonable, conserve precious resources, and create works that have zero bullshit, like the Droog or the Super Normal. Take the leap of faith and believe in yourself and the influence that speaks to you the most.

History progresses to bring us contemporary work practices, like how Dadaists created artworks to fight oppression, Constructivists made their artworks with a social purpose, or how Bauhaus made design user-centric the way we know today. We should only use them as lessons, not references.

We shall not be artists, we shall be designers.