Every Drop Counts
Sarah Blosser and Eliana Wang
Instructor: Viola He
Our project's concept is an attempt at data visualization in the context of excessive water usage during mundane activities. These mundane activities that we wanted to convey consisted of brushing one's teeth, doing laundry, watering plants, and taking a shower. We were inspired by a project by Antonin Fourneau titled Water Light Graffiti that uses LEDs to respond to water. To convey the 4 activities that we chose, we had small artifacts to represent each action, and once that was picked up, a large water droplet would light up with the amount of water usage each activity uses, with one LED being equivalent to one gallon of water, as well as a short video that had a corresponding blurb about the action. The interaction that we originally intended for the user and how that ideation developed definitely affected our design process and decisions. We originally wanted the user to merely pick up the artifacts and putting them back down, but in practice, that idea developed into picking them up and placing them somewhere, which affected the fabrication of our design. We needed to design and construct holder specific for each artifact which we decided would be mounted onto the frame the droplet is hanging on. During the User Testing Session, we hadn't made the artifacts yet, so we substituted those with cardboard pieces labeled with the 4 activities. We also didn't have any housing for the Arduino or breadboard, as well as our wires were all exposed. Our frame, water droplet, and code were mostly done though, so from then on we were merely working on the expanding the fabrication aspect. Much of our feedback consisted of ways to develop the presentation of the project, as well as the interaction itself. It was at the User Testing Session where we decided on creating places for the artifacts to be placed rather than just picked up from a table and put back down. Also a big suggestion that proved to be really helpful in wire management was to wrap each artifacts corresponding wires in almost a telephone cord spiral, which give another level of interesting interaction for the user. All of these feedbacks, we did our best to incorporate, by creating holders for the artifact, creating housing for the arduino by making a base on the frame, and consolidating the wires in a telephone cord-like way. All these contributed greatly to the progress of our final product from the User Testing Session to the end. In conclusion the ideation of our project went through many iterations.
Our idea, from its inception, I think fundamentally stayed consistent throughout the process, with changes being made in the consideration of not making anything too complicated to the point where it'd be unrealistic for someone of our skill level to create. With that in mind, our first conceptual design included not an LED light strip but physical ball that rolled on a ramp and accumulated, as shown in our original sketch below.
As development with the idea continued, the idea of physical balls rolling down a spiral ramp became too ambitious. With that we pivoted to now include LED light strip within the water droplet. Now with a finalized idea, we started the construction of the circuit itself, making it with 4 tilt sensors, and LED neopixel strip, and videos queued to play on the computer. The videos were simply made in iMovie, putting text over a small clip of each activity. We chose to use tilt sensors instead of other options here because we wanted the 4 items to be easily played with and lifted while still triggering the reaction of the lights and video. While building the circuit, the wiring was relatively simple. I started by finalizing the code for the tilt sensors to cause a video to play, as seen by video here.
Once that interaction was finalized, I then focused on the other interaction of the tilt sensor to the neopixel animations. In the process, I did end up changing the neopixel animation from falling one by one to accumulate on the bottom, to going from the bottom one by one as it was faster. The video above is depicting the initial animation that I changed to accumulate from the bottom up.
The video above is depicting the final interaction that I made, with the tilt sensors triggering both the video and the lights with the new animation, the code is included below as well.
#include <FastLED.h>
#define NUM_LEDS 60
#define DATA_PIN 3
CRGB leds[NUM_LEDS];
int litCount = 0;
void setup() {
Serial.begin(9600);
pinMode(10, INPUT);
pinMode(2, INPUT);
pinMode(4, INPUT);
pinMode(7, INPUT);
FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
FastLED.setBrightness(50);
}
void loop() {
int sensor0 = digitalRead(10);
int sensor1 = digitalRead(2);
int sensor2 = digitalRead(4);
int sensor3 = digitalRead(7);
if (sensor0 == 0){
clearLED();
starttoothBrushAnimation();
}
else if (sensor1 == 0) {
clearLED();
startplantAnimation();
}
else if (sensor2 == 0) {
clearLED();
startlaundryAnimation();
}
else if (sensor3 == 0) {
clearLED();
startshowerAnimation();
}
// send the values keeping this format
Serial.print(sensor0);
Serial.print(","); // put comma between sensor values
Serial.print(sensor1);
Serial.print(",");
Serial.print(sensor2);
Serial.print(",");
Serial.print(sensor3);
Serial.println(); // add linefeed after sending the last sensor value
// too fast communication might cause some latency in Processing
// this delay resolves the issue
delay(20);
}
void clearLED(){
for (int i = 0; i < NUM_LEDS; i=i+1) {
leds[i] = CRGB(0, 0, 0);
}
FastLED.show();
//delay(50);
}
void starttoothBrushAnimation() {
for (int i = 0; i < 10; i=i+1) {
leds[i] = CRGB(173, 216, 230);
FastLED.show();
delay(50);
}
}
void startplantAnimation(){
for (int i = 0; i < 50; i=i+1) {
leds[i] = CRGB(173, 216, 230);
FastLED.show();
delay(50);
}
}
void startlaundryAnimation(){
for (int i = 0; i < 40; i=i+1) {
leds[i] = CRGB(173, 216, 230);
FastLED.show();
delay(50);
}
}
void startshowerAnimation(){
for (int i = 0; i < 25; i=i+1) {
leds[i] = CRGB(173, 216, 230);
FastLED.show();
delay(50);
}
}
import processing.video.*;
import processing.serial.*;
Serial serialPort;
int NUM_OF_VALUES_FROM_ARDUINO = 4;
int arduino_values[] = new int[NUM_OF_VALUES_FROM_ARDUINO];
Movie toothBrush;
Movie plant;
Movie laundry;
Movie shower;
Movie myMovie;
void setup() {
size(1250, 700);
//size(displayWidth, displayHeight);
myMovie = new Movie(this, "toothbrush.mp4");
toothBrush = new Movie(this, "toothbrush.mp4");
plant = new Movie(this, "plant.mp4");
laundry = new Movie(this, "laundry.mp4");
shower = new Movie(this, "shower.mp4");
printArray(Serial.list());
serialPort = new Serial(this, "/dev/cu.usbmodem101", 9600);
}
void draw() {
getSerialData();
if(arduino_values[0] == 0) {
switchVideo(toothBrush);
} else if(arduino_values[1] == 0){
switchVideo(plant);
} else if(arduino_values[2]==0){
switchVideo(laundry);
} else if(arduino_values[3] == 0){
switchVideo(shower);
}
if (myMovie.available()) {
myMovie.read();
}
image(myMovie, 0, 0, width, height);
}
//void keyPressed() {
// if (key == 't') {
// myMovie = new Movie(this, "toothbrush.mp4");
// myMovie.play();
// } else if (key == 'p') {
// myMovie = new Movie(this, "plant.mp4");
// myMovie.play();
// } else if (key == 'l') {
// myMovie = new Movie(this, "laundry.mp4");
// myMovie.play();
// } else if (key == 's') {
// myMovie = new Movie(this, "shower.mp4");
// myMovie.play();
// }
//}
void switchVideo(Movie newMovie) {
if (myMovie != newMovie) {
myMovie.stop();
myMovie = newMovie;
myMovie.loop();
}
}
void getSerialData() {
while (serialPort.available() > 0) {
String in = serialPort.readStringUntil( 10 ); // 10 = '\n' Linefeed in ASCII
if (in != null) {
print("From Arduino: " + in);
String[] serialInArray = split(trim(in), ",");
if (serialInArray.length == NUM_OF_VALUES_FROM_ARDUINO) {
for (int i=0; i<serialInArray.length; i++) {
arduino_values[i] = int(serialInArray[i]);
}
}
}
}
}
Once the wiring and code was finalized, we moved to the fabrication of the design itself, starting with the construction of the frame. This design went through many iterations, first being designed using laser cut pieces of plywood, then once we realized that that wouldn't be strong enough, we decided to use thicker pieces of wood, cut using the wood shop tools, as shown in the video here.
We cut the pieces of wood to measure a 70 cm frame with a cross section going across the top so that we could attach a hook to hang the water drop from. The picture here depicts the finished frame that was held together using nails and diagonal pieces to reinforce the structural integrity of the frame. We ended up painting the frame white as well to contribute to the aesthetics.
After making the frame, we moved to cutting the acrylic water droplet shape that would hang from the top of the frame. We decided to use frosted acrylic as we thought the light would diffuse nicely from it. We cut two of the same shape to connect using the small disks cut out stack together using acrylic glue as a binder. We also used the holes in the top of the drop shape to thread fish wire through and attach it to the top of the frame. In terms of the light strip that we wanted to be in between the two pieces of acrylic, we tried to attach the light strip using hot glue, but that wasn't working, so we resorted to glueing. Once we had that structure confirmed, we wanted to add some texture within the droplet, so we bought blue fabric to place within and make the texture more water like. Then when we went to attach the two sides of the droplet together using acrylic glue, it wasn't staying put, so we ended up drilling holes in the bottom as well to attach using the same method of fish wire. Below are some pictures of that process.
We also wanted to develop the base of the frame to house the Arduino and Breadboard and to develop the aesthetics of project. We used the extra fabric that we had from the drop, and a piece of blue plastic to create the base using cardboard, as depicted here.
Another addition that contributed greatly to the development of the project was the wire management aspect. We wanted to develop a way to consolidate the wires in a neat way while making the interaction more interesting. And to do this, we took the feedback from the User Testing Session and creating coiled wire. I started by try to make it using stranded wire, wrapping it around a metal pipe and heating it up so it would hold its shape. This didn't end up working because the stranded wires I was using were vinyl coated, and this method would only work with a silicone coating. When this obstacle came up, the way I solved it was by using solid wires, heat shrinking them together, while wrapped around a plastic pipe. Because of the difficulty in threading the wires through the heat shrink, I needed to make two small sections and solder them together. I did this for all 4 tilt sensors, and soldered them onto the tilt sensors as well. To make the visuals consistent, I also wrapped the exposed wiring from the soldering with electrical tape. Pictures of the process are below.
One of the last component that we worked on was the 3D printing of the artifacts. We found the models online, and printed them in a size that was appropriate. Also on the underside of the artifacts, we drilled holes to put the tilt sensors in. Below are pictures of the process.
The last addition we made was holders for the 3D printed artifacts. We made this by laser cutting plywood boxes that had holes measures to fit the artifacts themselves. The goal of this addition was to give the user a destination to put the items. Below are pictures of the different files we used to laser cut the boxes.
Lastly, here is a picture of our final product.
In conclusion, our goals of our project were met with pretty good accuracy. Although we wanted a more physical element to convey a unit of water, the light strip ended up being a visually appealing portion of the project. During the IMA show, I think we both didn't anticipate the intuitve responses of some if not most of the users. Because the holders were oriented the way they were, many people instinctively tried to put the object in from the bottom to the top instead of our intended placing on the top of the holders. This caused occasional confusion and need for explanation on our part. If we had more time, I think we would try and create more intuitive holders, or even just turn the holders upside down. Also if we had more time, refining the code so that when the object are lifted, they wouldn't need to pick them up one at a time to trigger the lights and video. Another point of improvement that would be a great addition if we had more time would be if we somehow incorporated the video onto the frame in some way. Maybe projecting it onto the water drop itself or onto a backdrop attached to the frame. This way the visuals would be consolidated all in one place. With the many complications and setbacks, edits that we made to the original idea, etc. came a lot of appreciation for what we ultimately accomplished. Although there were changes made, what we ended up with is something to be proud of. A main lesson and accomplishment that I learned was the lesson of flexibility and the ability to adapt to moving parts, as well as the ability to creatively address an issue without feeling stuck. Teamwork was also something that I feel was undervalued in the process, but now in reflecting, was the only reason the project turned out the way it did. Overall, coming into the class with no background in an fabrication or coding, being able to end and create a product like we did was a very satisfying result.