The Haunted Window

The Idea:

For the PCOMP Midterm Project Zhe Wang and I created a Horror themed window display. Requirements for the project stipulated that the project be interactive, have a halloween party theme, and utilize serial communication in some way. Recently I have been really interested in public works of art and just putting pieces in a space and seeing how random passerby’s interact with them. After iterating through a few ideas with public spaces in mind we first thought about using a door then after some time we settled on a window.

It was important for us to focus on drawing people into the interaction and try to have them feel immersed in experience when viewing it.

received_341071519799604 (1).jpeg

Functionality of the Piece:

  • Curtain that opens and closes when user gets within a certain distance of the installation.

  • Sounds that are dependent on the user’s distance.

  • Startling element inside of the display. (End result was a doll with a spinning head)

  • Interactive lighting effects

Trials and Error of Fabrication:

We knew that one of the most difficult parts of getting this project to be feasible was going to be getting the window so we made that a priority. Luckily we were able to find one on our first try at the big reuse in Brooklyn. After that we got the plywood from Home Depot and the doll from a halloween store and rest of the non technical supplies from the soft lab.

The fabrication portion of the project was one of the most labor intensive parts of the project. It included building the container for the window and materials, and building the “chair” for the doll to sit on, and the mount for the inner dc motor.

20181016_190516.jpg
20181020_151355.jpg

Prototyping:

Prototyping for the project included working with the two motors (One Stepper and one regular DC) to make sure that they functioned properly in the environment. It also included building out the lighting display. After all of the pieces were working separately one a breadboard I perf boarded out two separate circuits for the motors, lights and ultrasonic sensor.

20181024_015001.jpg
IMG_2307.jpg

Interactivity and the Workings of the Project:

The final piece had the following elements:

  • When the user walks within 100cm of the window from the front the lights change from white to red and the noise being output from the box changes to a disturbing tone.

  • Shortly after the curtain opens and the user is greeted by a terrifying doll. Within a few seconds the doll’s head begins to spin rapidly.

  • After a few seconds of this the dolls head stops and the curtain shuts.

  • The piece then resets and waits for the next user to approach

The main sensing component for the project was a standard ultrasonic sensor that would send bits of data to p5 from Arduino.

Final Piece:

Below you can watch a short video of the piece being interacted with.

Here is the code for the project:

p5 Code:

/*

Zhe Wang and Morgan Mueller

Physical Computation 2018 Midterm Project P5 code.

The main purpose for this p5 sketch was to communicate with the arduino

serially and play selected sounds when the data being sent in

meets a certain criteria

*/

//define noises

let noise;

let noise2;

let noise3;

let noise4;

let noise5;

let enticingNoises = []

//define serial variables

let serial;

let fromSerial;

let called = true;

let countdown = 0;

let delay = 2000;

let noiseBool;

//load sounds into the program

function preload() {

soundFormats('wav', 'mp3');

noise = loadSound('helpMe.mp3');

noise2 = loadSound('distortedVocals.mp3');

noise3 = loadSound('playWithMe.mp3');

noise4 = loadSound('imSoScared.mp3');

noise5 = loadSound('child_laugh.mp3');

enticingNoises = [noise, noise3, noise4, noise5];

}

function setup() {

createCanvas(500, 500);

// make a new instance of serialport library

serial = new p5.SerialPort();

// callback function for serialport list event

serial.on('list', printList);

// callback for new data coming in

serial.on('data', serialEvent);

// list the serial ports

serial.list();

// open a port

serial.open("/dev/cu.usbmodem1421");

noise.setVolume(0.5);

noise2.setVolume(0.5);

background(0, 0, 0);

}

// function playNoise() {

// if (fromSerial < 50) {

// print("hello");

// noise2.play();

// } else {

// noise.play();

// noise.loop();

// console.log(fromSerial);

// }

// }

function draw() {

}

function printList(portList) {

for (var i = 0; i < portList.length; i++) {

// Display the list the console:

print(i + " " + portList[i]);

}

}

function serialEvent() {

// this is called when data is recieved, data will then live in fromSerial

fromSerial = serial.read();

print(fromSerial);

//if the person is within 100 cm then play the defined sound

if (fromSerial < 100 && !called && millis() - countdown > delay) {

noise.pause();

noise2.amp(100);

noise2.play();

//noise2.pause();

//noise5.play();

countdown = millis();

print("called 1");

called = true;

}

//if there is no person being sensed then play the other sound

else if (fromSerial > 100 && called && millis() - countdown > delay) {

//for (let i = 0; i < enticingNoises.length; i++) {

noise2.pause();

// noise.amp(100);

// noise.play();

// noise.loop();

// noise.pause();

noise3.amp();

noise3.play();

noise3.loop(); t

// noise4.play();

// noise4.pause();

countdown = millis();

print("called 2")

called = false;

noiseBool = false;

}

}

Arduino code:

/*

Zhe Wang and Morgan Mueller PCOMP Midterm 2018

*/

#include <Stepper.h>

#include <Adafruit_NeoPixel.h>

#ifdef __AVR__

#include <avr/power.h>

#endif

#define PIN 6

//pin instantiation for distance sensor

const int trigPin = 2;

const int echoPin = 3;

//pin instantiation for dc motor

const int firstDCPin = 4;

const int secondDCPin = 7;

const int dcEnablePin = 5;

bool test = false;

//stepper revolutions

const int stepsPerRevolution = 1536; // change this to fit the number of steps per revolution

// for your motor

// initialize the stepper library on pins 8 through 11:

Stepper myStepper(stepsPerRevolution, 8, 9, 10, 11);

Adafruit_NeoPixel strip = Adafruit_NeoPixel(56, PIN, NEO_GRB + NEO_KHZ800);

long duration; //duration in microseconds

int distance; // distance in cm

void setup() {

Serial.begin(9600);

// set the speed at 180 rpm:

myStepper.setSpeed(20);

// initialize the serial port:

pinMode(trigPin, OUTPUT);

pinMode(echoPin, INPUT);

//LED Strip

strip.begin();

strip.show(); // Initialize all pixels to 'off'

strip.setBrightness(70);

//DC Motor pins

pinMode(firstDCPin, OUTPUT);

pinMode(secondDCPin, OUTPUT);

pinMode(dcEnablePin, OUTPUT);

//set enable pin high so motor can turn on

digitalWrite(dcEnablePin, HIGH);

}

void loop() {

//colorSwap(strip.Color(255, 255, 255));

// distance sensor functionailty

digitalWrite(trigPin, LOW);

delayMicroseconds(10);

digitalWrite(trigPin, HIGH);

delayMicroseconds(10);

digitalWrite(trigPin, LOW);

duration = pulseIn(echoPin, HIGH);

//calculate the object's/person's distance

distance = duration * (0.034 / 2);

Serial.write(distance);

//if the distance is less than 50cm or ~ 24 inches, then start the interaction

if (distance < 100 && test == true) {

//change the color of the led strip to red

delay(50);

colorSwap(strip.Color(255, 0, 0)); // Red

delay(10);

//pull the curtain back to the wall

myStepper.step(stepsPerRevolution);

delay(5000);

// delay(5000);

//some event needs to happen here in between the motors

//the stepper pulls the curtain back to open the curtain one more time

//myStepper.step(stepsPerRevolution);

digitalWrite(firstDCPin, LOW); // set leg 1 of the H-bridge low

// delay(10);

digitalWrite(secondDCPin, HIGH); // set leg 2 of the H-bridge high

//test = true;

delay(500);

digitalWrite(firstDCPin, LOW); // set leg 1 of the H-bridge low

// delay(100);

digitalWrite(secondDCPin, HIGH); // set leg 2 of the H-bridge high

delay(5000);

//test = true;

digitalWrite(firstDCPin, LOW); // set leg 1 of the H-bridge low

// delay(100);

digitalWrite(secondDCPin, LOW); // set leg 2 of the H-bridge Low

delay(500);

//the curtain goes back to the wall

myStepper.step(-stepsPerRevolution);

delay(5000);

test = false;

}

else if (test == false && distance > 100) {

colorSwap(strip.Color(255, 255, 255)); // White

// Serial.print("Distance: ");

// Serial.println(distance);

test = true;

}

}

//change color of the led strip

void colorSwap(uint32_t c) {

for (uint16_t i = 0; i < strip.numPixels(); i++) {

strip.setPixelColor(i, c);

strip.show();

}

}