Media Control
Installation Art with User-Generated Physical and Digital Motion
Tools (My Role)
Collaborator
Date
Rhino
Arduino
Processing
Blender
3D Printing
ChatGPT
FigJam
Arduino
Processing
Blender
3D Printing
ChatGPT
FigJam
Tangtang Cai
Sept. 2023 - Nov. 2023
Project Information
Media Control is an installation art which discussed the impact of big data algorithms and media guidance on contemporary human cognition. Taking a macro perspective, the project explores motivations behind those who are steering media to promote specific information. While on a micro level, the project investigates the behaviors individuals unintentionally acquire from media exposure. It questions whether individuals possess the ability to discern and acquire beneficial information consciously. Furthermore, the exploration delves into whether people are aware of taking advantage of big data to access information they need.
In the experience, users are able to press the buttons to control the apps dropping into the skull. While they pressed all three buttons, the rail slide table begins to work, pushing a brain spit from the skull’s mouse. While the rail slide table goes to the front, the user see the brain, and the animation starts.
The whole box looks like an information cocoon, while people originally think that they are just having fun, in reality, they are already manipulated by all social media information if they don’t spontaneously filtrate information they get. While user press the button, they switch the place from browsing social media to manipulate social media.
In the experience, users are able to press the buttons to control the apps dropping into the skull. While they pressed all three buttons, the rail slide table begins to work, pushing a brain spit from the skull’s mouse. While the rail slide table goes to the front, the user see the brain, and the animation starts.
The whole box looks like an information cocoon, while people originally think that they are just having fun, in reality, they are already manipulated by all social media information if they don’t spontaneously filtrate information they get. While user press the button, they switch the place from browsing social media to manipulate social media.
Animation
In this animation, I explored cognitive decay, illustrating the moment when individual cease critical thought, their brain melts through their head and becomes garbage. This symbolizes that those who neglect deliberate consideration may unintentionally cause potential harm. At last, when the deteriorated brain submerges into the box, their own living environment is also affected.
User Journey
Press all three buttons to trigger the brain spit from the skull’s mouth and the animation:
Process
Inspiration
-
Research
- Sketch
Materials
- 28 Stepper Moter
- 19inch LCD Screen
- Arduino Uno
- CNC shield v3
- PVC expansion sheet
- ...
3D Modeling & Printing
- Skull (two parts)
- Apps
- Stepper moter supporters *3
- Fish line roller *3
Coding
- Arduino
- Processing
Prototyping
- Challenges
- Next Step
Inspiration
Research
Liu, Wei, and Wei, Zhou. “Research on Solving Path of Negative Effect of ‘Information Cocoon Room’ in Emergency” Semantic Scholar, April 29, 2022. https://www.semanticscholar.org/paper/Research-on-Solving-Path-of-Negative-Effect-of-in-Liu-Zhou/6ac48b6c95d9818da9d5ec025005544f6ea86192
Sketch
Main Materials
19inch LCD Screen
CNC shield v3
28 Stepper Moter
Arduino Uno
PVC expansion sheet
Power Charger
Rail Slide Table
Self Reset Button
Acrylic Spray Paint
3D Modeling & Printing
Front View
Side View
Top View
PVC Expansion Sheet Cutting
Coding
Arduino
Processing
#include <AccelStepper.h> //Download AccelStepper Library
/*Author: Tangtang Cai*/
// 定义电机控制用常量
const int enablePin = 8; // 使能控制引脚
const int xdirPin = 5; // x方向控制引脚
const int xstepPin = 2; // x步进控制引脚
const int ydirPin = 6; // y方向控制引脚
const int ystepPin = 3; // y步进控制引脚
const int zdirPin = 7; // z方向控制引脚
const int zstepPin = 4; // z步进控制引脚
const int adirPin = 13; // a方向控制引脚
const int astepPin = 12; // a步进控制引脚
const int moveSteps = 5000; //test stepper 123运行使用的运行步数
const int moveSteps1 = 3400; //t
est stepper 4运行使用的运行步数
unsigned long Time;
int val1,val2,val3;
AccelStepper stepper1(1, xstepPin, xdirPin); //set 步进电机对象1
AccelStepper stepper2(1, ystepPin, ydirPin); //set 步进电机对象2
AccelStepper stepper3(1, zstepPin, zdirPin); //set 步进电机对象3
AccelStepper stepper4(1, astepPin, adirPin); //set 步进电机对象4
void setup() {
Serial.begin(9600);
pinMode(9, INPUT_PULLUP); // 1号按钮
pinMode(10, INPUT_PULLUP); // 2号按钮
pinMode(11, INPUT_PULLUP); // 3号按钮
pinMode(xstepPin, OUTPUT);
pinMode(xdirPin, OUTPUT);
pinMode(ystepPin, OUTPUT);
pinMode(ydirPin, OUTPUT);
pinMode(zstepPin, OUTPUT);
pinMode(zdirPin, OUTPUT);
pinMode(astepPin, OUTPUT);
pinMode(adirPin, OUTPUT);
pinMode(enablePin, OUTPUT);
digitalWrite(enablePin, LOW); // 将使能控制引脚设置为低电平从而让电机驱动板进入工作状态
stepper1.setMaxSpeed(5000.0); // 设置电机最大速度5000
stepper1.setAcceleration(4000.0); // 设置电机加速度4000
stepper2.setMaxSpeed(5000.0);
stepper2.setAcceleration(4000.0);
stepper3.setMaxSpeed(5000.0);
stepper3.setAcceleration(4000.0);
stepper4.setMaxSpeed(2000.0);
stepper4.setAcceleration(20000.0);
while (stepper1.currentPosition() > -5000) {
stepper1.moveTo(-5000);
stepper1.run();
//Serial.println(stepper1.currentPosition());
}
while (stepper2.currentPosition() > -5000) {
stepper2.moveTo(-5000);
stepper2.run();
//Serial.println(stepper2.currentPosition());
}
while (stepper3.currentPosition() > -5000) {
stepper3.moveTo(-5000);
stepper3.run();
//Serial.println(stepper3.currentPosition());
}
while (stepper4.currentPosition() <3400) {
stepper4.moveTo(3400);
stepper4.run();
//Serial.println(stepper4.currentPosition());
}
stepper1.setCurrentPosition(0);
stepper2.setCurrentPosition(0);
stepper3.setCurrentPositio
n(0);
stepper4.setCurrentPosition(0);
Serial.println("Ready");
}
void loop() {
if (digitalRead(9) == 0) {
val1=1; Time = millis();
stepper1.moveTo(moveSteps);
stepper1.runToPosition();
}
if (digitalRead(10) == 0) {
val2=1;
Time = millis();
stepper2.moveTo(moveSteps)
;
stepper2.runToPosition();
}
if (digitalRead(11) == 0) {
val3=1;
Time = millis();
stepper3.moveTo(moveSteps);
stepper3.runToPosition();
}
if (millis() - Time > 10000) {
stepper1.moveTo(0);
stepper2.moveTo(0);
stepper3.moveTo(0);
stepper1.run();
stepper2.run();
stepper3.run();
val1=0; val2=0; val3=0;
}
if(val1==1 && val2==1 && val3==1){
stepper4.moveTo(-3400);
stepper4.runToPosition();
Serial.println("AllDone");
delay(7000);
stepper4.moveTo(0);
stepper4.runToPosition();
delay(1000);
stepper1.moveTo(0);
stepper2.moveTo(0);
stepper3.moveTo(0);
stepper1.run(); stepper2.run(); stepper3.run();
val1=0; val2=0; val3=0;
}
}
/*Author: Tangtang Cai*/
// 定义电机控制用常量
const int enablePin = 8; // 使能控制引脚
const int xdirPin = 5; // x方向控制引脚
const int xstepPin = 2; // x步进控制引脚
const int ydirPin = 6; // y方向控制引脚
const int ystepPin = 3; // y步进控制引脚
const int zdirPin = 7; // z方向控制引脚
const int zstepPin = 4; // z步进控制引脚
const int adirPin = 13; // a方向控制引脚
const int astepPin = 12; // a步进控制引脚
const int moveSteps = 5000; //test stepper 123运行使用的运行步数
const int moveSteps1 = 3400; //t
est stepper 4运行使用的运行步数
unsigned long Time;
int val1,val2,val3;
AccelStepper stepper1(1, xstepPin, xdirPin); //set 步进电机对象1
AccelStepper stepper2(1, ystepPin, ydirPin); //set 步进电机对象2
AccelStepper stepper3(1, zstepPin, zdirPin); //set 步进电机对象3
AccelStepper stepper4(1, astepPin, adirPin); //set 步进电机对象4
void setup() {
Serial.begin(9600);
pinMode(9, INPUT_PULLUP); // 1号按钮
pinMode(10, INPUT_PULLUP); // 2号按钮
pinMode(11, INPUT_PULLUP); // 3号按钮
pinMode(xstepPin, OUTPUT);
pinMode(xdirPin, OUTPUT);
pinMode(ystepPin, OUTPUT);
pinMode(ydirPin, OUTPUT);
pinMode(zstepPin, OUTPUT);
pinMode(zdirPin, OUTPUT);
pinMode(astepPin, OUTPUT);
pinMode(adirPin, OUTPUT);
pinMode(enablePin, OUTPUT);
digitalWrite(enablePin, LOW); // 将使能控制引脚设置为低电平从而让电机驱动板进入工作状态
stepper1.setMaxSpeed(5000.0); // 设置电机最大速度5000
stepper1.setAcceleration(4000.0); // 设置电机加速度4000
stepper2.setMaxSpeed(5000.0);
stepper2.setAcceleration(4000.0);
stepper3.setMaxSpeed(5000.0);
stepper3.setAcceleration(4000.0);
stepper4.setMaxSpeed(2000.0);
stepper4.setAcceleration(20000.0);
while (stepper1.currentPosition() > -5000) {
stepper1.moveTo(-5000);
stepper1.run();
//Serial.println(stepper1.currentPosition());
}
while (stepper2.currentPosition() > -5000) {
stepper2.moveTo(-5000);
stepper2.run();
//Serial.println(stepper2.currentPosition());
}
while (stepper3.currentPosition() > -5000) {
stepper3.moveTo(-5000);
stepper3.run();
//Serial.println(stepper3.currentPosition());
}
while (stepper4.currentPosition() <3400) {
stepper4.moveTo(3400);
stepper4.run();
//Serial.println(stepper4.currentPosition());
}
stepper1.setCurrentPosition(0);
stepper2.setCurrentPosition(0);
stepper3.setCurrentPositio
n(0);
stepper4.setCurrentPosition(0);
Serial.println("Ready");
}
void loop() {
if (digitalRead(9) == 0) {
val1=1; Time = millis();
stepper1.moveTo(moveSteps);
stepper1.runToPosition();
}
if (digitalRead(10) == 0) {
val2=1;
Time = millis();
stepper2.moveTo(moveSteps)
;
stepper2.runToPosition();
}
if (digitalRead(11) == 0) {
val3=1;
Time = millis();
stepper3.moveTo(moveSteps);
stepper3.runToPosition();
}
if (millis() - Time > 10000) {
stepper1.moveTo(0);
stepper2.moveTo(0);
stepper3.moveTo(0);
stepper1.run();
stepper2.run();
stepper3.run();
val1=0; val2=0; val3=0;
}
if(val1==1 && val2==1 && val3==1){
stepper4.moveTo(-3400);
stepper4.runToPosition();
Serial.println("AllDone");
delay(7000);
stepper4.moveTo(0);
stepper4.runToPosition();
delay(1000);
stepper1.moveTo(0);
stepper2.moveTo(0);
stepper3.moveTo(0);
stepper1.run(); stepper2.run(); stepper3.run();
val1=0; val2=0; val3=0;
}
}
import processing.video.*;
import processing.serial.*;
Movie video1; // First video
Movie video2; // Second video
boolean isPlayingFirstVideo = true; // Flag to track which video is playing
int secondVideoDuration = 8000; // Duration of the second video in milliseconds
Serial arduinoPort; // Serial port object
String message = "";
void setup() {
fullScreen();
size(810, 1080);
video1 = new Movie(this, "ani1.mp4");
video2 = new Movie(this, "ani2.mp4");
video1.play target="_blank">video1.play(); // Start with the first video
video2.pause();
//Open the Arduino serial port (change the port name as needed)
arduinoPort = new Serial(this, "/dev/cu.usbmodem21301", 9600);
}
void draw() {
background(0);
// Check which video is playing and display it
if (isPlayingFirstVideo) {
if (video1.available()) {
video1.read();
}
image(video1, 0, 0, width, height);
} else {
if (video2.available()) {
video2.read();
}
image(video2, 0, 0, width, height);
}
}
void movieEvent(Movie m) {
m.read();
}
void serialEvent(Serial p) {
while (arduinoPort.available() > 0) {
char receivedChar = (char)arduinoPort.read();
message += receivedChar;
if (receivedChar == 'n') {
message = message.trim();
if (message.equals("AllDone")) {
video1.stop();
video2.play(); // Switch to the second video
isPlayingFirstVideo = false;
// Set a timer to switch back to the first video
timer(secondVideoDuration);
}
message = "";
}
}
}
void timer(int waitTime) {
Thread t = new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(waitTime);
switchToFirstVideo();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
);
t.start();
}
void switchToFirstVideo() {
video2.stop();
video1.play(); // Automatically switch to the first video
isPlayingFirstVideo = true;
}
import processing.serial.*;
Movie video1; // First video
Movie video2; // Second video
boolean isPlayingFirstVideo = true; // Flag to track which video is playing
int secondVideoDuration = 8000; // Duration of the second video in milliseconds
Serial arduinoPort; // Serial port object
String message = "";
void setup() {
fullScreen();
size(810, 1080);
video1 = new Movie(this, "ani1.mp4");
video2 = new Movie(this, "ani2.mp4");
video1.play target="_blank">video1.play(); // Start with the first video
video2.pause();
//Open the Arduino serial port (change the port name as needed)
arduinoPort = new Serial(this, "/dev/cu.usbmodem21301", 9600);
}
void draw() {
background(0);
// Check which video is playing and display it
if (isPlayingFirstVideo) {
if (video1.available()) {
video1.read();
}
image(video1, 0, 0, width, height);
} else {
if (video2.available()) {
video2.read();
}
image(video2, 0, 0, width, height);
}
}
void movieEvent(Movie m) {
m.read();
}
void serialEvent(Serial p) {
while (arduinoPort.available() > 0) {
char receivedChar = (char)arduinoPort.read();
message += receivedChar;
if (receivedChar == 'n') {
message = message.trim();
if (message.equals("AllDone")) {
video1.stop();
video2.play(); // Switch to the second video
isPlayingFirstVideo = false;
// Set a timer to switch back to the first video
timer(secondVideoDuration);
}
message = "";
}
}
}
void timer(int waitTime) {
Thread t = new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(waitTime);
switchToFirstVideo();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
);
t.start();
}
void switchToFirstVideo() {
video2.stop();
video1.play(); // Automatically switch to the first video
isPlayingFirstVideo = true;
}
Note: Arduino controls the moter circuit, while Processing code enables the animation to switch from pure white to blender animation, which is triggered by Arduino.
Prototyping
Challenges
3D Printing Crashing, Wire Connecting Unmatching, Button Wire Soldering, PVC Expansive Sheet unmatching, Skull color unsuitable, Arduino & Processing Transmission Failure, LCD Screen Crashing, Light Dimmed ...
Inspiration Story
In early 2020, I was blocked at home for 3 months in Wuhan, the first city reported COVID. During the lockdown, our access to information were tightly connected to internet. I gradually realized that social media plays a pivot role in shaping and controlling us of how we view the world. Modern people are unintentionally guided by a variety of big data algorithms. Without the ability to think, a person is just like a skeleton.
I combined plain acrylics with stereoscopic strings and app-like cards. These cards are sticked to magnets, allowing them to move. This signifies that applications are well-designed but users just mechanically focus on interested topics while I use sketch pastel instead of acrylics for the skeleton to represent its roughness. Some of the five app icons are slightly different from the original one. While Instagram and YouTube are cut out, they immerse into people’s brain. TikTok has not yet been cut out, but the button color of it gradually becomes the same to the brain, showing that people are addicted into it.
I combined plain acrylics with stereoscopic strings and app-like cards. These cards are sticked to magnets, allowing them to move. This signifies that applications are well-designed but users just mechanically focus on interested topics while I use sketch pastel instead of acrylics for the skeleton to represent its roughness. Some of the five app icons are slightly different from the original one. While Instagram and YouTube are cut out, they immerse into people’s brain. TikTok has not yet been cut out, but the button color of it gradually becomes the same to the brain, showing that people are addicted into it.