"THE EXPERIMENT"
INSTALLATION INTERACTIVE
"THE EXPERIMENT" INTERACTIVE INSTALLATION

(description to come)

The Experiment : A tongue-in-cheek interactive audio-visual installation about an Artificial Intelligence that tries too hard to control its human counterpart.

"HUMANS VOLUNTEERS NEEDED FOR A PERFECTLY SAFE EXPERIMENT. DURATION : 5 MINUTES. SERIOUS AND HEALTHY CANDIDATES ONLY."

Explores the relationship between human and machine, data collection and an ultimate, pathethic attempt from a machine to control people who care less and less about it.

My first artistic installation !
Duration : about 5 min
I discovered this place when I helped Marie with her installation.

Code Arduino


#include <CapacitiveSensor.h>

#include <Servo.h>

Servo servo;


int lampPin = 7;

int laserCagePin = 8;

int smokeServoPin = 3;

int laserpointerPin = 12;

int presenceSensorPin = 9;

int rightPhotoResistorPin = A0;

int leftPhotoResistorPin = A2;

int laserpointerButtonPin = A5;

CapacitiveSensor cs_4_2 = CapacitiveSensor(4, 2);    //sphere capacitive sensor


int proximityThreshold = 2500;                        //sphere hand proximity threshold

int touchThreshold = 17000;                          //sphere hand touch threshold

int rightPhotoResistorThreshold = 250;                // lower = less perturbed by smoke

int leftPhotoResistorThreshold = 150;                // lower = less perturbed by smoke

int laserpointerButtonThreshold = 850;


bool presenceDetected = false;

bool sphereActive = true;

bool sphereTouched = false;

bool laserCageActive = false;

bool laserpointerActive = false;

bool laserpointerButtonPressed = false;

bool laserpointerButtonTimerStarted = false;

bool laserpointerButtonTimerEnded = false;

bool mainEloignee = false;

bool mainApproche = false;

bool drawingVoiceTimerStarted = false;

bool drawingVoiceTimerEnded = false;


unsigned long currentMillis = 0;

unsigned long previousMillis = 0;

unsigned long previousDrawingVoiceMillis = 0;

unsigned long previousLaserpointerButtonMillis = 0;

int sphereTouchedDelay = 2000;

int laserDelay = 0;

int drawingVoiceDelay = 20000;

int laserpointerButtonDelay = 32000;                                  //for how long people can draw with the blue laser pointer

int smokeServoDuration = 3000 + sphereTouchedDelay + laserDelay;

bool smokeServoTimerStarted = false;

bool smokeServoOn;

bool presenceStarted = false;


int rightPhotoResistor;

int leftPhotoResistor;

int laserpointerButton;





void setup() {

  

  Serial.begin(9600);

  Serial.setTimeout(1);


  pinMode(lampPin, OUTPUT);

  pinMode(laserCagePin, OUTPUT);

  pinMode(smokeServoPin, OUTPUT);

  pinMode(laserpointerPin, OUTPUT);

  pinMode(presenceSensorPin, INPUT);


  servo.attach(smokeServoPin);

  servo.write(10);

  digitalWrite(laserCagePin, HIGH);

  digitalWrite(laserpointerPin, HIGH);

  digitalWrite(lampPin, HIGH);

  smokeServoOn = false;


  //cs_4_2.set_CS_AutocaL_Millis(0xFFFFFFFF);             //disable capacitivesensor autocalibration


    

}







void smokeServo() {

    if (smokeServoOn == false) {

      servo.write(40);

      smokeServoOn = true;

      previousMillis = currentMillis;

      smokeServoTimerStarted = true;

    }

}





void smokeServoTimer() {

   if (smokeServoOn == true && currentMillis - previousMillis > smokeServoDuration) {

      servo.write(10);

      smokeServoOn = false;

      smokeServoTimerStarted = false;

  }

}





void drawingVoiceTimer () {

  if (drawingVoiceTimerEnded == false && currentMillis - previousDrawingVoiceMillis > drawingVoiceDelay) {

      if (laserpointerButtonPressed == false) Serial.println("Voix dessin");

      drawingVoiceTimerEnded = true;

  }

}




void laserpointerButtonTimer () {

  if (laserpointerButtonTimerEnded == false && currentMillis - previousLaserpointerButtonMillis > laserpointerButtonDelay) {

      Serial.println("Fin dessin");

      laserpointerButtonTimerEnded = true;

      digitalWrite(laserCagePin, HIGH);

      digitalWrite(laserpointerPin, HIGH);

      digitalWrite(lampPin, HIGH);

      laserCageActive = false;

      laserpointerActive = false;

      laserpointerButtonPressed = false;

      drawingVoiceTimerStarted = false;

      laserpointerButtonTimerStarted = false;

      sphereActive = true;

      delay(10000);                                       //delay to match python time.sleep

  }

}





void laserpointerButtonTimerReset () {

    previousLaserpointerButtonMillis = currentMillis;

    laserpointerButtonTimerStarted = true;

    laserpointerButtonTimerEnded = false;

  }



void drawingVoiceTimerReset () {

    previousDrawingVoiceMillis = currentMillis;

    drawingVoiceTimerStarted = true;

    drawingVoiceTimerEnded = false;

  }





void touched() {

    digitalWrite(lampPin, LOW);

    delay(sphereTouchedDelay);

    digitalWrite(laserCagePin, LOW);

    digitalWrite(laserpointerPin, LOW);

    laserCageActive = true;

    laserpointerActive = true;

    delay(laserDelay);

    smokeServo();

    smokeServoTimerStarted = true;

    sphereTouched = false; 

    delay(100);                                     //delay for photoresistor to pick up light signal from lasers

}






void lampFlicker() {

  digitalWrite(lampPin, LOW);

  delay(15);

  digitalWrite(lampPin, HIGH);

  delay(30);

}




void laserCageTouched() {

  digitalWrite(laserCagePin, HIGH);

  digitalWrite(laserpointerPin, HIGH);

  digitalWrite(lampPin, HIGH);

  if (laserpointerButtonPressed == true) {

    Serial.println("Fin dessin");

    delay(10000);

  }

  else {

    Serial.println("CageLaserTouche");

    delay(3500);   

  }

  laserCageActive = false;

  laserpointerActive = false;

  laserpointerButtonPressed = false;

  drawingVoiceTimerStarted = false;

  laserpointerButtonTimerStarted = false;

  sphereActive = true;

                                   //delay to match python time.sleep

}



void laserpointerPressed() {

  Serial.println("PointeurLaserAppuye");

  laserpointerButtonPressed = true;

}




void sphereInteractivity () {

  

  long sensorValue =  cs_4_2.capacitiveSensor(300);

  Serial.println(String("                       sphereValue: ") + sensorValue + String("        "));

  //Serial.println("  \t");


  if (sensorValue < proximityThreshold && mainEloignee == false && mainApproche == true) {

    Serial.println("MainEloignee");

    mainEloignee = true;

  }

  if (sensorValue > proximityThreshold+1 && sensorValue < touchThreshold) {

    Serial.println("MainApproche");

    mainEloignee = false;

    mainApproche = true;

    lampFlicker();

  }

  if (sensorValue > touchThreshold+1) {

    Serial.println("MainTouche");

    sphereTouched = true;

    sphereActive = false;

    mainEloignee = false;

    mainApproche = false;

  }

}




void welcomeVoice() {

  if (presenceDetected == true && presenceStarted == false) {

    Serial.println("Message de bienvenue");

    presenceStarted = true;

  }

  if (presenceDetected == false) {

    presenceStarted = false;

  }

  

}






void loop() {

  delay(50);                                                //delay to slow down everything

  //delay(200);                                                   //delay to read serial.print

  currentMillis = millis();

  presenceDetected = digitalRead(presenceSensorPin);

  //Serial.println(presenceDetected);

  Serial.println(String("                                            rightPhotoResistor: ") + rightPhotoResistor);

  Serial.println(String("                                             leftPhotoResistor: ") + leftPhotoResistor);


  if (laserCageActive == false) welcomeVoice();

    

  if (smokeServoTimerStarted == true) smokeServoTimer();

  

  if (sphereActive == true) sphereInteractivity();


  if (sphereTouched == true) touched();


  rightPhotoResistor = analogRead(rightPhotoResistorPin);

  leftPhotoResistor = analogRead(leftPhotoResistorPin);

  laserpointerButton = analogRead(laserpointerButtonPin);

  //Serial.println(String("laserpointerButton: ") + laserpointerButton);


  if (rightPhotoResistor < rightPhotoResistorThreshold && leftPhotoResistor < leftPhotoResistorThreshold && laserCageActive == true) laserCageTouched();        //COMMENT OFF TO CALIBRATE LASERS POSITIONS


  if (laserpointerButton < laserpointerButtonThreshold && laserCageActive == true && laserpointerButtonPressed == false) laserpointerPressed();


  if (laserCageActive == true && drawingVoiceTimerStarted == false) drawingVoiceTimerReset();


  if (laserCageActive == true && drawingVoiceTimerEnded == false) drawingVoiceTimer();


  if (laserCageActive == true && laserpointerButtonTimerStarted == false && laserpointerButtonPressed == true) laserpointerButtonTimerReset();


  if (laserCageActive == true && laserpointerButtonTimerEnded == false && laserpointerButtonPressed == true) laserpointerButtonTimer();


  //Serial.println(currentMillis - previousDrawingVoiceMillis);


  void reset_CS_AutoCal();          //reset capacitivesensor ?

  

}

Fabrication :
Building process :


The cable is a fake. No electric current will run through the sphere.

The lasers would start when the sphere is touched by someone. They all are under 5 mW of optical power, making them harmless (Class II).


Code Python
(to communicate with computer)


import time

import serial

import keyboard

import winsound

import vlc


ArduinoSerial = serial.Serial('com5',9600) 

time.sleep(0.5)


player = vlc.Instance()

media_player = player.media_player_new()


welcome = player.media_new("welcome.mp3")

electricity = player.media_new("electricity.mp3")

thunder = player.media_new("thunder.mp3")

tryagain = player.media_new("tryagain.mp3")

voixdessin = player.media_new("voixdessin.mp3")

thankyou = player.media_new("thankyou.mp3")


welcomeIsPlaying = False

electricityIsPlaying = False

thunderIsPlaying = False

tryagainIsPlaying = False

voixdessinHasPlayed = False

thankyouIsPlaying = False





while True:


    incoming = str (ArduinoSerial.readline())

    print (incoming)

    time.sleep(0.001)

    


    if ('Message de bienvenue' in incoming and media_player.is_playing() == False):

        media_player.set_media(welcome)

        media_player.play()

        voixdessinHasPlayed = False

        #welcomeIsPlaying = True



    if ('MainEloignee' in incoming):

        media_player.stop()

        electricityIsPlaying = False

        

    if ('MainApproche' in incoming and electricityIsPlaying == False):

        media_player.stop()

        media_player.set_media(electricity)

        media_player.play()

        electricityIsPlaying = True


    if (media_player.is_playing() == False and electricityIsPlaying == True):

        media_player.set_media(electricity)

        media_player.play()

        electricityIsPlaying = True

        

    if ('MainTouche' in incoming):

        media_player.stop()

        electricityIsPlaying = False

        voixdessinHasPlayed = False

        media_player.set_media(thunder)

        media_player.play()

        #thunderIsPlaying = True

        #time.sleep(6)


    if ('CageLaserTouche' in incoming):

        media_player.stop()

        media_player.set_media(tryagain)

        media_player.play()

        #tryagainIsPlaying = True

        voixdessinHasPlayed = False

        time.sleep(3.5)


    if ('Voix dessin' in incoming):

        media_player.stop()

        media_player.set_media(voixdessin)

        media_player.play()

        voixdessinHasPlayed = True


    if ('PointeurLaserAppuye' in incoming and voixdessinHasPlayed == False):

        #media_player.stop()

        media_player.set_media(voixdessin)

        media_player.play()

        #voixdessinIsPlaying = True


    if ('Fin dessin' in incoming):

        media_player.stop()

        media_player.set_media(thankyou)

        media_player.play()

        voixdessinHasPlayed = False

        time.sleep(10)

        #thankyouIsPlaying = True