Project showcase

SURFACE X

SURFACE X is an interactive installation focusing on the moment when the self-created digital and our physical identities collide.

  • 4,493 views
  • 1 comment
  • 13 respects

Components and supplies

About this project

SURFACE X by Picaroon is an interactive art installation, consisting of 35 umbrellas which get scared when a human is coming close. 2 Arduino Mega are the heart of the installation. One of them, the Master, is checking 20 PIR Sensors, while the other one controls the behavior of the umbrellas. The umbrellas are operated with pneumatic. It took Picaroon three years to building the installation. Read more about the artistic background of our installation:

Questioning Surface and Substance

SURFACE X questions the discrepancy between our self-created digital surface and the real-world substance underneath. By letting people experience the removal of the surface as they approach the interactive installation, SURFACE X draws attention to what is hidden and inspires reflection on one's own different identities.

In the digital world, we present ourselves in the best possible light—#nofilter, of course. In the hopes of being loved, employed, liked and followed, we carefully choose the best parts of our identity to display. By adding a photo filter here and highlighting a detail there, we constantly work on creating the perfect surface. Our digital identity is flawless and impressive.

Until… someone comes closer. When we actually meet our Tinder date face to face. Or go to that job interview we got invited to. SURFACE X captures the very moment when our digital and our physical identities collide and merge into the real us.

At this moment, it becomes impossible to keep the perfect surface intact. It cracks and folds and our true self is revealed.Like our digital identity, SURFACE X appears large and impressive from a distance. The interactive installation is made up of 35 black umbrellas that form a single, spherical body 3.5 meters in diameter. The umbrellas represent an impenetrable shield, protecting the inside from unwanted looks.However, once a person approaches SURFACE X, the umbrellas immediately shy away and close within milliseconds. It crumbles and shrinks and loses its polished look. Up close, one sees less surface but more of what lies behind, cables, sensors and a steel frame.

It is left to the approaching person to judge: Does it look ugly or broken? Or rather interesting, maybe even beautiful?

Code

MASTERArduino
The Master is checking all PIR sensors
/*LAST CHANGES 2017-10-26
 * /*THIS IS THE MASTER! 
  This programm is setting the communication pins (Master > Slave)
  for each of the 35 umbrellas*/
//PAU = PinAssignmentUmbrella
//----------------------------------------------------------------------//
//----------------------------------------------------------------------//
//----------------------------------------------------------------------//
/*START defining global Master-Slave Outputs*/
int DO_PAU[6] = {14, 15, 16, 17, 18, 19}; //ARDUINO PINs: Digital outputs for PAU communication
int Takt = 1; //ARDUINO PIN 1: Takt manages whether SLAVE listens (if HIGH, Slave listens)
int Data = 20; //ARDUINO PIN 20: Data indicates whether umbrella should be closed (LOW) or opened (HIGH)
int Busy = 21; //ARDUINO PIN 21: Busy indicates whether Slave is Busy with reading PAUS (HIGH) or finished (LOW)
/*END defining globalMaster-Slave Outputs*/
//----------------------------------------------------------------------//
/*START UmbrellaSetPins INT*/
int PAU[] = {//Pin assignment for each umbrella
  1, 0, 0, 0, 0, 0, //1
  0, 1, 0, 0, 0, 0, //2
  1, 1, 0, 0, 0, 0, //3
  0, 0, 1, 0, 0, 0, //4
  1, 0, 1, 0, 0, 0, //5
  0, 1, 1, 0, 0, 0, //6
  1, 1, 1, 0, 0, 0, //7
  0, 0, 0, 1, 0, 0, //8
  1, 0, 0, 1, 0, 0, //9
  0, 1, 0, 1, 0, 0, //10
  1, 1, 0, 1, 0, 0, //11
  0, 0, 1, 1, 0, 0, //12
  1, 0, 1, 1, 0, 0, //13
  0, 1, 1, 1, 0, 0, //14
  1, 1, 1, 1, 0, 0, //15
  0, 0, 0, 0, 1, 0, //16
  1, 0, 0, 0, 1, 0, //17
  0, 1, 0, 0, 1, 0, //18
  1, 1, 0, 0, 1, 0, //19
  0, 0, 1, 0, 1, 0, //20
  1, 0, 1, 0, 1, 0, //21
  0, 1, 1, 0, 1, 0, //22
  1, 1, 1, 0, 1, 0, //23
  0, 0, 0, 1, 1, 0, //24
  1, 0, 0, 1, 1, 0, //25
  0, 1, 0, 1, 1, 0, //26
  1, 1, 0, 1, 1, 0, //27
  0, 0, 1, 1, 1, 0, //28
  1, 0, 1, 1, 1, 0, //29
  0, 1, 1, 1, 1, 0, //30
  1, 1, 1, 1, 1, 0, //31
  0, 0, 0, 0, 0, 1, //32
  1, 0, 0, 0, 0, 1, //33
  0, 1, 0, 0, 0, 1, //34
  1, 1, 0, 0, 0, 1 //35
};
int NumberEffect[20] = {1, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2}; //How many umbrellas does the sensor effect?
int EffectedUmbrella[40] = {0,10,1,11,2,12,3,13,4,14,5,15,6,16,7,17,8,18,9,19,0,20,30,21,0,22,31,23,0,24,32,25,0,26,33,27,0,28,34,29};
/*END UmbrellaSetPins INT*/
//----------------------------------------------------------------------//
/*To be adapted: FPS for SensorChecking*/
int DurationSensorChecking = 5000; //Duration in FPS for Trigger > Echo
//int DurationSensorChecking = 30000; //Duration in FPS for Trigger > Echo
int SecurityDelaySensor = 50; //Wait between two sensors for safety reasons to avoid interference.
//----------------------------------------------------------------------//
/*START ints for all Sensor-Changes*/
int SensorChange[20] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; //Indicates whether a sensor changes its Data and therefore needs umbrella action
int CurrentSensorData[20] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; //Managed by the actual sensors > Sth Detected = 1 / Nothing detected = 0
int PreviousSensorData[20] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; //Saved data from previous checking
/*END ints for all Sensor-Changes*/
//----------------------------------------------------------------------//
/*START defining Sensor ARDUINO Pins*/
int SensorTrigger[20] = {3, 5, 7, 9, 11, 13, 24, 28, 32, 36, 40, 44, 48, 52, 25, 29, 33, 37, 41, 45}; //ARDUINO PINs: Digital Outputs
int SensorEcho[20] = {2, 4, 6, 8, 10, 12, 22, 26, 30, 34, 38, 42, 46, 50, 23, 27, 31, 35, 39, 43}; //ARDUINO PINs: Digital Inputs
/*END defining Sensor ARDUINO Pins*/
int WhichSensor = 0;
int AllSensorsNull = 0;
boolean newStart = true;
/*DelayCounter so that Umbrella stays open some time*/
int DelayCounterUmbrella[20] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; //Stores delay for each umbrella
int DelayCounter = 5000; //Delay tbd.
int secondUmbrellaDelay = 300; //Delay until 2nd Umbrella reacts.
//----------------------------------------------------------------------//
//----------------------------------------------------------------------//
//----------------------------------------------------------------------//
void setup() {
  //Serial.begin(9600);
  Serial.end();
  Serial1.end();
  Serial2.end();
  Serial3.end();
  //START Defining all communication pins//
  for (int x = 0; x < 6; x++) { //Declaring all 6 DO-PAUs as Digital Outputs
    pinMode(DO_PAU[x], OUTPUT);
    digitalWrite(DO_PAU[x], LOW);//Setting all 6 DO-PAUs to LOW
  }
  pinMode(Takt, OUTPUT); digitalWrite(Takt, LOW);
  pinMode(Data, OUTPUT); digitalWrite(Data, LOW);
  pinMode(Busy, INPUT);
  //END Defining all communication pins//
  //START Defining all ARDUINO sensor pins//
  for (int x = 0; x < 20; x++) { //Declaring all Trigger Pins as Digital Output, Echo as Digital Input
    pinMode(SensorTrigger[x], OUTPUT);  digitalWrite(SensorTrigger[x], LOW);
    pinMode(SensorEcho[x], INPUT);
  }
  //END Defining all ARDUINO sensor pins//
}
//----------------------------------------------------------------------//
//----------------------------------------------------------------------//
//----------------------------------------------------------------------//
void loop() {
   if (newStart == true){
    newStart = false;
    delay(1000);
  }
  //START Checking Sensor [WhichSensor] for x FPS
  if(digitalRead(SensorEcho[WhichSensor]) == HIGH){CurrentSensorData[WhichSensor] = 1;
        DelayCounterUmbrella[WhichSensor] = 0;}
  else {
    if(DelayCounterUmbrella[WhichSensor] == DelayCounter){
        CurrentSensorData[WhichSensor] = 0;
        }
    else{DelayCounterUmbrella[WhichSensor]++;}
    }
  //END Checking Sensor [WhichSensor] for x FPS
   //START Checking if something changed regarding the current sensor
  if (CurrentSensorData[WhichSensor] == PreviousSensorData[WhichSensor]) {
    SensorChange[WhichSensor] = 0;
  }
  else {
    SensorChange[WhichSensor] = 1;
  }
  
  //END Checking if something changed regarding the current sensor
  //START communicating Change to SLAVE
  if (SensorChange[WhichSensor] == 1) { // if change = true, start communication
    while (digitalRead(Busy) == HIGH) {
      delay(1); // >>while SLAVE busy, don't continue.
    }
    //START Setting PAU for current Umbrella (NrUmbrella)//
    digitalWrite(DO_PAU[0], (PAU[(((EffectedUmbrella[WhichSensor])* 6) + 0)])   );
    digitalWrite(DO_PAU[1], (PAU[(((EffectedUmbrella[WhichSensor])* 6) + 1)])   );
    digitalWrite(DO_PAU[2], (PAU[(((EffectedUmbrella[WhichSensor])* 6) + 2)])   );
    digitalWrite(DO_PAU[3], (PAU[(((EffectedUmbrella[WhichSensor])* 6) + 3)])   );
    digitalWrite(DO_PAU[4], (PAU[(((EffectedUmbrella[WhichSensor])* 6) + 4)])   );
    digitalWrite(DO_PAU[5], (PAU[(((EffectedUmbrella[WhichSensor])* 6) + 5)])   );
    //END Setting PAU per Umbrella//
    if (CurrentSensorData[WhichSensor] == 1) {
      digitalWrite((Data), 1); //Set Data for Slave.
    } else {
      digitalWrite((Data), 0);
    }
    PreviousSensorData[WhichSensor] = CurrentSensorData[WhichSensor]; //"Previous state" is now the current one
    SensorChange[WhichSensor] = 0; //There's no current change on this sensor
    digitalWrite((Takt), 1); //Now the date is ready to be read by SLAVE
    //AS SOON AS SLAVE STARTS READING DATA (>> BUSY > HIGH), TAKT > 0. WAIT FOR IT.
    while (digitalRead(Busy) == LOW) {
      delay(1); // >>while SLAVE busy, don't continue.
    }
    digitalWrite((Takt), 0);
    //START Sensor affects 2 umbrellas, second umbrella is set
    if(NumberEffect[WhichSensor] == 2){
      delay(secondUmbrellaDelay); //Short Delay until 2nd umbrella reacts.
        while (digitalRead(Busy) == HIGH) {
      delay(1); // >>while SLAVE busy, don't continue.
    }
    //START Setting PAU for current Umbrella (NrUmbrella)//
    digitalWrite(DO_PAU[0], (PAU[(((EffectedUmbrella[WhichSensor+20])* 6) + 0)])   );
    digitalWrite(DO_PAU[1], (PAU[(((EffectedUmbrella[WhichSensor+20])* 6) + 1)])   );
    digitalWrite(DO_PAU[2], (PAU[(((EffectedUmbrella[WhichSensor+20])* 6) + 2)])   );
    digitalWrite(DO_PAU[3], (PAU[(((EffectedUmbrella[WhichSensor+20])* 6) + 3)])   );
    digitalWrite(DO_PAU[4], (PAU[(((EffectedUmbrella[WhichSensor+20])* 6) + 4)])   );
    digitalWrite(DO_PAU[5], (PAU[(((EffectedUmbrella[WhichSensor+20])* 6) + 5)])   );
    //END Setting PAU per Umbrella//
    if (CurrentSensorData[WhichSensor] == 1) {
      digitalWrite((Data), 1); //Set Data for Slave.
    } else {
      digitalWrite((Data), 0);
    }
    digitalWrite((Takt), 1); //Now the date is ready to be read by SLAVE
    //AS SOON AS SLAVE STARTS READING DATA (>> BUSY > HIGH), TAKT > 0. WAIT FOR IT.
    while (digitalRead(Busy) == LOW) {
      delay(1); // >>while SLAVE busy, don't continue.
    }
    digitalWrite((Takt), 0);
    }
    //END Sensor affects 2 umbrella, second umbrella is set
    }

  
    //START switching to next sensor after the previous one got checked
  if (WhichSensor < 19) {
    WhichSensor++;
  } else {
    WhichSensor = 0;
  }

  //END switching to next sensor after the previous one got checked
}
SLAVEArduino
The Slave is controlling all umbrellas.
/*LAST CHANGES 2017-10-26
 _20171026_SLAVE_SLAVE_DurationOpening
 */
/*THIS IS THE SLAVE! 
  This programm plays each single umbrellas it receives from the Master
/*
//PAU = PinAssignmentUmbrella
//----------------------------------------------------------------------//
//----------------------------------------------------------------------//
//----------------------------------------------------------------------//
int WaitForSglUmbrella = 2000;
/*START defining global Master-Slave Outputs*/
int DO_PAU[6] = {14, 15, 16, 17, 18, 19}; //ARDUINO PINs: Digital outputs for PAU communication
int Takt = 1; //ARDUINO PIN 1: Takt manages whether SLAVE listens (if HIGH, Slave listens)
int Data = 20; //ARDUINO PIN 20: Data indicates whether umbrella should be closed (LOW) or opened (HIGH)
int Busy = 21; //ARDUINO PIN 21: Busy indicates whether Slave is Busy with reading PAUS (HIGH) or finished (LOW)
/*END defining globalMaster-Slave Outputs*/
/*START defining Umbrelal ARDUINO Pins*/
int UmbrellaPin[35] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 23, 25, 27, 29, 31, 33, 35}; //ARDUINO PINs: Digital Outputs
/*END defining Umbrelal ARDUINO Pins*/
boolean JERKPROGRAMM = false; //Special programm if all
int SumOfAllPAUs = 0; //Sum of all PAUs >> Indicates which umbrella it is about
int WhichUmbrella[35] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
/*START INT FOR JERK PROGRAMM*/
int JerkWasRunning = 0;
long DelayTillNextJerk; //Delay till next umbrella jerks
int DelayTillNextJerkCounter = 0; 
int DelayTillNextJerkMIN = 10000; //min FPS till next umbrella jerks
int DelayTillNextJerkMAX = 500000; //max FPS till next umbrella jerks
long JerkUmbrella; //Will store the PIN of the JerkUmbrella
int DurationJerkUmbrella = 200; //Duration of which jerking umbrella closes
int CountingWhileJerking = 0; //Counter till Umbrella stops jerking
/*END INT FOR JERK PROGRAMM*/
boolean newStart = true;
//----------------------------------------------------------------------//
//----------------------------------------------------------------------//
//----------------------------------------------------------------------//
void setup() {
  //Serial.begin(9600);
  Serial.end();
  Serial1.end();
  Serial2.end();
  Serial3.end();

  //randomSeed(analogRead(0));//for my Random numbers;
  //START Defining all communication pins//
  for (int x = 0; x < 6; x++) { //Declaring all 6 DO-PAUs as Digital Inputs
    pinMode(DO_PAU[x], INPUT);
  }
  pinMode(Takt, INPUT); 
  pinMode(Data, INPUT); 
  pinMode(Busy, OUTPUT); digitalWrite(Busy, LOW);
  //END Defining all communication pins//
  //START Defining all ARDUINO sensor pins//
  for (int x = 0; x < 35; x++) { //Declaring all Umbrella Pins as Digital Output
    pinMode(UmbrellaPin[x], OUTPUT); digitalWrite(UmbrellaPin[x], LOW);
  }
  //END Defining all ARDUINO sensor pins//
}
//----------------------------------------------------------------------//
//----------------------------------------------------------------------//
//----------------------------------------------------------------------//
void loop() {
  if (newStart == true){
    newStart = false;
    delay(4000);
  }
  //START Receive Data from Master + set single Umbrella
  if(digitalRead(Takt) == 1){ //Data is ready to be processed
    digitalWrite(Busy, 1); //Now SLAVE is busy reading data
    SumOfAllPAUs = -1;//Umbrella Array starts with 0!
    if(digitalRead(DO_PAU[0]) == HIGH){SumOfAllPAUs = SumOfAllPAUs+1;}
    if(digitalRead(DO_PAU[1]) == HIGH){SumOfAllPAUs = SumOfAllPAUs+2;}
    if(digitalRead(DO_PAU[2]) == HIGH){SumOfAllPAUs = SumOfAllPAUs+4;}
    if(digitalRead(DO_PAU[3]) == HIGH){SumOfAllPAUs = SumOfAllPAUs+8;}
    if(digitalRead(DO_PAU[4]) == HIGH){SumOfAllPAUs = SumOfAllPAUs+16;}
    if(digitalRead(DO_PAU[5]) == HIGH){SumOfAllPAUs = SumOfAllPAUs+32;}
    //START Set Umbrella/JERK Data
    
      if(digitalRead(Data) == 1){WhichUmbrella[SumOfAllPAUs] = 1;}
      else{WhichUmbrella[SumOfAllPAUs] = 0;}
    //END Set Umbrella/JERK Data
   
  //END Receive Data from Master
 
  //START Setting Single Umbrella


    digitalWrite(UmbrellaPin[SumOfAllPAUs], (WhichUmbrella[SumOfAllPAUs]));//Open or Closes Umbrella
 
  digitalWrite(Busy, 0); //Now SLAVE is finished with reading and setting data
//END Setting Single Umbrella
}

}
  

Schematics

PIR Signal Inverter
A Inverter for the PIR Signal to avoid disturbance

Comments

Similar projects you might like

Arduino Quadcopter

Project tutorial by robocircuits

  • 4,292 views
  • 8 comments
  • 25 respects

ARMduino API

Project showcase by JD Sweet

  • 1,341 views
  • 0 comments
  • 6 respects

OpenCat

Project in progress by Petoi

  • 177,538 views
  • 144 comments
  • 1,274 respects

Arduino Controlled Pinball Machine

Project tutorial by Bob Blomquist

  • 28,963 views
  • 40 comments
  • 78 respects

UAV Arduino

Project showcase by Gorceag Victor

  • 23,966 views
  • 24 comments
  • 130 respects

OCS-2: A Digital, Semi Modular Synthesizer

Project showcase by chnry

  • 20,985 views
  • 20 comments
  • 74 respects
Add projectSign up / Login