Threshold of Harmony
Project by Jingjing Wang & Jonathan Zhai
Instructor: Andy Garcia
Project by Jingjing Wang & Jonathan Zhai
Instructor: Andy Garcia
"Threshold of Harmony" is an interactive installation that reflects on the delicate relationship between humans and nature, emphasizing the consequences of crossing ecological boundaries. As viewers approach the tree, it blossoms, symbolizing the beauty and potential of respectful coexistence. However, when they come too close or touch the tree, it withers, and toxic gas is released—representing nature’s retribution when pushed beyond its limits.
This piece draws from real-world environmental crises, such as deforestation and pollution, to illustrate how human exploitation of nature can lead to its destruction and, ultimately, harm to ourselves. The tree's response to human presence symbolizes how maintaining a careful balance and respecting nature's boundaries is crucial for sustaining ecological health. It reminds us that our actions toward the environment have a direct impact on its well-being, and by extension, our own.
Through this interaction, the project encourages reflection on the interdependence between humans and the natural world, urging viewers to consider the consequences of overstepping boundaries. It calls for a more mindful, sustainable relationship with nature, emphasizing that when the balance is broken, both nature and humanity suffer.
Project by Jingjing Wang & Jonathan Zhai
Instructor: Andy Garcia
Oct, 2024
,,
Mimosa retracts his leaves to protect himself when touched. In Mimosa, we see the defensive behavior of plants when they are attacked or destroyed. In the past, we tend to think of plants as unresponsive, but Mimosa's behavior shows us that nature responds in its own way and to human behavior. When the Mimosa is not touched, he slowly spreads his leaves again. This also symbolizes nature's ability to heal itself.
Inspired by this natural plant response, we wanted to explore how human behavior interferes with the rhythms of nature and how we can interact with nature without upsetting the balance.
INPUT (Sensor)
Ultrasonic Distance Sensor
OUTPUT (Actuators)
RGB LED
DC Motor *2
180 Degree Servo *2
Atomizing Nozzle
Buzzer
Base, Plastic Trunk, Brunches
At the beginning, we decided to work with real tree brunches and cardboard. For the tree trunk, we want something that is hollow so that cables can go through. The plastic pipe is picked because it is easy to drill holes on its surface.
Cardboard was initially used as the base, but we switch to the foam board later as we found it not stable enough to hold the pipe.
I drilled holes on the pipe and put the brunches in. Then I put a small screw at the bottom of each brunch for threading.
Servos, Ultrasonic Sensors
In this step, we want to acheive the main function: moving brunches up and down with distance signal from the ultrasonic sensor. Here we connect the servos and the ultrasonic sensor to the Arduino. To make the servo pull the strings, we drilles one hole on each side of the pipe to pass the strings of the other side's brunches through. So there three strings for each hole, depending on the direction of the brunches.
DC Motors, RGB LED, Buzzer
As our instructor Andy suggested that we could build more stages of interaction to make it more engaging and more fun, we decided to build two more stages with different status depending on the user's distance.
We added DC Motors to spin the flowers when people come close. In order to engage with more senses, we also added the buzzer for audio reaction and RGB LED for lighting reaction.
Stage 0: When there is no human detected by the "nature" sensor.
Stage 1: When someone detected walking away from the "close up range", the branches grow up back, and the music restarts to play.
Stage2: When someone is detected too close to the nature "sensor", the flowers stop spinning, the branches drop and the alarm rings, the nature starts to defend by spraying moisture.
}
}
Some Random Users
Here we find that some users are not very clear about each stage because the interval of stage 2 is too short. Also, the spinning flowers are not obvious enough to be seen, and users often neglect stage 2.
Visually, the real leaves begin to wither as they lost water, and most of them dropped. To solve this, I decided to use fake brunches.
We thought it would be better to add some effects that are more obvious so that the users can see the reaction.
Atomizing Nozzle, Cardboard and Cloth Decorations
Based on the user test, we added the smoke effect with atomizing nozzle. This conveys to the user a more clear message that nature would revenge if you try to damage it. Also, we changed all the brunches into fake ones to keep visually looking good.
For the decoration part, I added a hollow base with cardboards in addition to the original solid ones. This base covers up all the circuits, Arduino board and breadboard. The Atomizing nozzle is also covered under it. I put some cloth around the side of the base and on top of it to cover up the cables on the surface and gives a more complete garden feel.
#include "Servo.h"
Servo servo1;
Servo servo2;
bool was_1 = false;
long interval = 2000;
long previousMilis = 0;
int previous_state;
// controls the servo
int buzzerPin = 2;
int servoPin = 6;
int servoPin2 = 7;
// atomizer
int atomPin = 8;
// controls the rgb
int redPin = 11;
int greenPin = 12;
int bluePin = 13;
// controls the ultrasonic sensor
int triggerPin = 5;
int echoPin = 3;
// controls the dc motors
int dcmotor_1 = 9;
int dcmotor_2 = 10;
// controls the photoresistor
//int resistorPin = A0;
// values
int mapped_servo;
int mapped_rgb;
int mapped_speed;
//int resist_val;
int def_servo = 180;
long distance;
float smoothing = 1;
float smoothed;
int r = 0;
int g = 0;
int b = 0;
int r1 = 255;
int g1 = 255;
int b1 = 0;
void setup() {
Serial.begin(9600);
// put your setup code here, to run once:
// buzzer
pinMode(buzzerPin, OUTPUT);
// servo
servo1.attach(servoPin);
servo2.attach(servoPin2);
// rgb
pinMode(redPin, OUTPUT);
pinMode(greenPin, OUTPUT);
pinMode(bluePin, OUTPUT);
// sensor
pinMode(triggerPin, OUTPUT);
pinMode(echoPin, INPUT);
// dc motors
pinMode(dcmotor_1, OUTPUT);
pinMode(dcmotor_2, OUTPUT);
// photoresistor
//pinMode(resistorPin, INPUT);
pinMode(atomPin, OUTPUT);
digitalWrite(atomPin, LOW);
}
void loop() {
// code for ultrasonic sensor: https://github.com/ima-nyush/Interaction-Lab/tree/main/Tutorials/Ultrasonic%20Distance%20Sensor
// put your main code here, to run repeatedly:
digitalWrite(triggerPin, LOW);
delayMicroseconds(2);
digitalWrite(triggerPin, HIGH);
delayMicroseconds(10);
digitalWrite(triggerPin, LOW);
// pulseIn waits for signal to go from HIGH to LOW,
// timeout according to max range of sensor
long duration = pulseIn(echoPin, HIGH, 17400);
// sound travels roughly 29cm per microsecond so we divide by 29,
// then by 2 since we recorded sound both going forth and back
distance = duration / 29 / 2;
// code for smoothing: https://docs.google.com/presentation/d/1GFIeQhnZZoYaiiaeomb2JWSyjVptC_Q__s2Wvs6S0f4/edit#slide=id.g2beb8277a25_0_130
smoothed = smoothed * (1.0 - smoothing) + distance * smoothing;
mapped_servo = map(smoothed, 4, 30, 0, 45);
mapped_servo = constrain(mapped_servo, 0, 15);
mapped_speed = map(smoothed, 4, 30, 0, 500);
mapped_speed = constrain(mapped_speed, 0, 220);
mapped_rgb = map(smoothed, 4, 30, 0, 100);
mapped_rgb = constrain(mapped_rgb, 0, 32);
//resist_val = analogRead(resistorPin);
//for test
Serial.println(distance);
if (smoothed == 0|| smoothed > 80) {
state0();
} else if (smoothed >= 40 && smoothed <= 80) {
state1();
} else if (smoothed < 40) {
state3();
}
//if (smoothed >= 14 && smoothed < 50) {
//setColor(r1, g1, b1);
//state2();
//}
//delay(20);
}
void state0() {
// no ren
def_servo = 0;
servo1.write(def_servo);
servo2.write(def_servo);
//delay(50);
Serial.println(smoothed);
Serial.println("Running STATE 0");
setColor(0, 128, 0); // green
//analogWrite(dcmotor_1, 0);
//analogWrite(dcmotor_2, 0);
birdChirp();
digitalWrite(dcmotor_1, LOW);
digitalWrite(dcmotor_2, LOW);
}
void state1() {
// when the user is not within a certain range of the artifact,
// the RGB light is blinking and music plays, the branches go back up
//birdChirp();
def_servo = 0;
servo1.write(def_servo);
servo2.write(def_servo);
//delay(50);
Serial.println(smoothed);
Serial.println("Running STATE 1");
setColor(0, 128, 0); // green
digitalWrite(dcmotor_1, HIGH);
digitalWrite(dcmotor_2, HIGH);
}
void state2() {
// when the user is within a certain range of the artifact,
// the RGB light starts turning red depending on distance, the branches droop as well music changes
if (previous_state == 3) {
servo1.write(15);
servo2.write(15);
delay(50);
} else {
setColor(r1, g1, b1);
servo1.write(mapped_servo);
servo2.write(mapped_servo);
//analogWrite(dcmotor_1, mapped_speed);
//analogWrite(dcmotor_2, mapped_speed);
Serial.println(smoothed);
Serial.println("Running STATE 2");
previous_state = 2;
analogWrite(dcmotor_1, 150);
analogWrite(dcmotor_2, 150);
}
}
void state3() {
// when the user is too close to the artifact,
// the RGB completely turns red, and the branches fall
def_servo = 180;
servo1.write(def_servo);
servo2.write(def_servo);
//analogWrite(dcmotor_1, 220);
//analogWrite(dcmotor_2, 220);
setColor(255, 0, 0);
Serial.println(smoothed);
Serial.println("Running STATE 3");
hornSound();
digitalWrite(dcmotor_1, LOW);
digitalWrite(dcmotor_2, LOW);
spray();
}
// https://gist.github.com/zachflower/79df9ed5ca398264d3b6
void setColor(int red, int green, int blue) {
while (r != red || g != green || b != blue) {
if (r < red) r += 1;
if (r > red) r -= 1;
if (g < green) g += 1;
if (g > green) g -= 1;
if (b < blue) b += 1;
if (b > blue) b -= 1;
_setColor();
}
}
void _setColor() {
analogWrite(redPin, r);
analogWrite(greenPin, g);
analogWrite(bluePin, b);
}
void birdChirp() {
tone(buzzerPin, 2000, 100); // Start with a high-pitched tone
delay(200); // Short pause to simulate a chirp
tone(buzzerPin, 1500, 150); // Lower the pitch for variation
delay(400);
tone(buzzerPin, 1800, 120); // Another variation in pitch
delay(300);
}
void hornSound() {
tone(buzzerPin, 1000); // Play a tone at 1000 Hz
delay(500); // Sound duration for 500 milliseconds
noTone(buzzerPin); // Stop the tone
delay(300); // Pause between sounds
}
void spray() {
long currentMilis = millis();
if ((currentMilis - previousMilis) >= interval) {
digitalWrite(atomPin, HIGH);
delay(400);
digitalWrite(atomPin, LOW);
}
}
We did a great job!
Overall, our project achieved all the functions we designed initially, and presents a very unifying concpet. "There is a balance between human activities and nature. We should not cross such threshold, or we will damage both." This artifact is educational and thought-evoking, which let people themselves to discover how nature react differently to their different activities. It is friendly to audience from all age, cultural and educational backgrounds, which they can all enjoy and learn from it.
Collaboration - We meet regularly to work on the project together, and listen to each other when having different ideas.
Labelled Circuit - All the cables are labelled with tapes. The cables on the breadboard are shortened so that they do not look messy, which is easier for adjustments.
Organized Code - The code is organized into different code blocks and stages. Each actuator and stage has an own code block. This helped a lot later in debugging.
Production Sequence - We started to make the physical shells before solving the circuit and code. This made us very hard to build the circuit later on because we need to build, fix and test it through the tiny holes. It would be easier if we connect the circuit and test the code first, then add physical decorations and shells.
Code Comments - Even though we orgainized our code into different categories, we lack comments for inner codes, especially codes regarding conditions and judgement. It takes a lot of time to figure out the logical problem wh debugging because we need to translate the codes again.
Interaction Level - Our project is at a rather low interaction level and less engaging because only the 3rd stage seems to be clear to the audience. The rest two stages are not so obvious, or the limited motions cannot bring up the audience's interest. We could solve this either by adding different sensors for responding to more diversive actions , or make it into a more game-like artifact that hooks people's attention。
Phrasing and Expression - Initially, our project is called "Close to Nature", which seems very positive. Actually it is important to be close to nature for humans, but the point is to keep harmony with nature. So, instead of stressing the physical distance between human and nature, we shifts to the more metaphoric distance, which is the behavioral threshold that could maintain nature & human balance.
We disassembled all parts of the circuit, actuators and sensors for future uses!