"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