Description / Narration:
Above viewers see a painting easel that allows them to co-create a visual representation of your interactions with it. The flow of colored ink through tubes mounted on the easel mixes and creates a painting on a paper roll. When viewer is standing nearby, or simply just passing-by, their horizontal position relative to the installation will be sent to the paint sets. This setup transduce the distance between viewer and the installation into a visual representation through the flow of colors, which can vary depending on the flow rates of the ink and the order in which the viewers enter the painting area. Tubes closest to you will have the quickest colors flow, and color sometimes mixes. There are three basic colors: red, blue, yellow, then are four color combinations available: red and blue, red and yellow, yellow and blue, and red and blue. Within a timeframe, such as one night, the viewers’ activity will be documented on the paper through this color flows. The painting can be taken away by the viewers once the paper roll is pulled down and cut.
Process Photo:
Process Reflection
In the process of building Flux, I struggled to integrate design + mechanical + computational, three elements effectively. I found it easy to come up with a concept, but integrating the mechanical components with fabrication, plus the computational aspect was much more challenging. In the project 2, there are several defects that I need to iterate on, which gives another layer of complexity to this final show.
One of the hardest parts of the project was rebuilding the tube settings and calibrate the pumps and sensors. Last presentation, the tubes were not adjusted in a fixed location, so colors sprayed everywhere, and cleaning became a hard problem. This time, I undo, and reconnected all the tubings on the easel, with a better planned mounting steps. I always told myself to stay alert when dealing with the mechanics and fabrication, with the idea that fixing can take much longer than being careful. After the three hours preparation, the tubings finally sit correctly.
The other part was the pumps and sensors, in which are more challenging. As I wanted to control the color flow without letting it went crazy, I re-tested its pwm prior to the show, and re-mounted them with lots of glues. However, this was just the first step. Calibrating the sensors so that they sent appropriate signals to the pump was another thing I tried hard. From rewritting the color arranging code, to testing the performance of the code with varying physical distance, I was managed to use eight sensors and guaranteed at least six would be working. Though this was a algorithmic aspect of the project, I believe this effort did contributed a lot to the performance of this artwork. Looking back to my project 2, the aforementioned instances where I thought I had everything working correctly, only to realize there was an error somewhere that was causing the project to malfunction. Though last time was frustrating, this time I knew the importance of thorough testing and debugging. It became easier to integrate all the different elements and to troubleshoot any issues that arose.
The show was amazing. People were attracted by the interesting flows of colors, as well as the creative paints generated through this interactive sets. In specific, during later part of the show, when the colors were richer on the paper, the painting looked magical. As some of them noticed the sensors, most of them were surprised by the concept of this piece. Though the preparation took a bit longer time than expected, I felt proud to my final work and grateful to everyone who made this happen. Thanks to the lighting, the other art pieces, and everyone, who made the night a poetic co-creation.
Lastly, dealing with the leftover paints after the show taught me valuable skills in organization and patience. I had to disassemble most of the components I had built from scratch and carefully clean them one by one in the sink. It was a time-consuming and tiring process, but I felt a sense of accomplishment and responsibility for not only my own artwork, but for the entire show. Despite being the last student to leave the WQED studio, I left feeling satisfied and proud of the work I had put in. The experience reinforced the importance of being organized and taking care of my surroundings.
Overall, this project was a great learning experience. It pushed me to learn new skills and taught me the importance of careful planning and thorough testing. I’m excited to apply what I learned to future projects and to continue growing as a creative and technical thinker.
Video Demonstration:
Code Submission:
//FLUX code //Sunniva Liu #include <NewPing.h> int myArray1[20]; int myArray2[20]; int myArray3[20]; int myArray4[20]; int myArray5[20]; int myArray6[20]; int myArray7[20]; int myArray8[20]; int sensorValue[8] = {0,0,0,0,0,0,0,0}; int counter1 = 0; int counter2 = 0; int counter3 = 0; int counter4 = 0; int counter5 = 0; int counter6 = 0; int counter7 = 0; int counter8 = 0; int rawValue1; int rawValue2; int rawValue3; int rawValue4; int rawValue5; int rawValue6; int rawValue7; int rawValue8; int pump1 = 6; int pump2 = 7; int pump3 = 8; int pump4 = 9; int pump5 = 10; int pump6 = 11; int pump7 = 12; int pump8 = 13; //1,3,5,8 - on; 2,4,6,7 off int pumpValue1 = 80; //200 int pumpValue2 = 100; //150 int pumpValue3 = 80; int pumpValue4 = 100; int pumpValue5 = 100; int pumpValue6 = 80; int pumpValue7 = 100; int pumpValue8 = 80; int distance_two[2] = {0,0}; int distance_pin[2] = {0,0}; #define MAX_DISTANCE 200 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm. #define TRIGGER_PIN1 22 // Arduino pin tied to trigger pin on the ultrasonic sensor. #define ECHO_PIN1 23 // Arduino pin tied to echo pin on the ultrasonic sensor. #define TRIGGER_PIN2 24 // Arduino pin tied to trigger pin on the ultrasonic sensor. #define ECHO_PIN2 25 // Arduino pin tied to echo pin on the ultrasonic sensor. #define TRIGGER_PIN3 26 // Arduino pin tied to trigger pin on the ultrasonic sensor. #define ECHO_PIN3 27 // Arduino pin tied to echo pin on the ultrasonic sensor. #define TRIGGER_PIN4 28 // Arduino pin tied to trigger pin on the ultrasonic sensor. #define ECHO_PIN4 29 // Arduino pin tied to echo pin on the ultrasonic sensor. #define TRIGGER_PIN5 30 // Arduino pin tied to trigger pin on the ultrasonic sensor. #define ECHO_PIN5 31 // Arduino pin tied to echo pin on the ultrasonic sensor. #define TRIGGER_PIN6 32 // Arduino pin tied to trigger pin on the ultrasonic sensor. #define ECHO_PIN6 33 // Arduino pin tied to echo pin on the ultrasonic sensor. #define TRIGGER_PIN7 34 // Arduino pin tied to trigger pin on the ultrasonic sensor. #define ECHO_PIN7 35 // Arduino pin tied to echo pin on the ultrasonic sensor. #define TRIGGER_PIN8 36 // Arduino pin tied to trigger pin on the ultrasonic sensor. #define ECHO_PIN8 37 // Arduino pin tied to echo pin on the ultrasonic sensor. NewPing sonar1(TRIGGER_PIN1, ECHO_PIN1, MAX_DISTANCE); // NewPing setup of pins and maximum distance. NewPing sonar2(TRIGGER_PIN2, ECHO_PIN2, MAX_DISTANCE); // NewPing setup of pins and maximum distance. NewPing sonar3(TRIGGER_PIN3, ECHO_PIN3, MAX_DISTANCE); // NewPing setup of pins and maximum distance. NewPing sonar4(TRIGGER_PIN4, ECHO_PIN4, MAX_DISTANCE); // NewPing setup of pins and maximum distance. NewPing sonar5(TRIGGER_PIN5, ECHO_PIN5, MAX_DISTANCE); // NewPing setup of pins and maximum distance. NewPing sonar6(TRIGGER_PIN6, ECHO_PIN6, MAX_DISTANCE); // NewPing setup of pins and maximum distance. NewPing sonar7(TRIGGER_PIN7, ECHO_PIN7, MAX_DISTANCE); // NewPing setup of pins and maximum distance. NewPing sonar8(TRIGGER_PIN8, ECHO_PIN8, MAX_DISTANCE); // NewPing setup of pins and maximum distance. void setup() { pinMode(pump1, OUTPUT); pinMode(pump2, OUTPUT); pinMode(pump3, OUTPUT); pinMode(pump4, OUTPUT); pinMode(pump5, OUTPUT); pinMode(pump6, OUTPUT); pinMode(pump7, OUTPUT); pinMode(pump8, OUTPUT); Serial.begin(115200); // Open serial monitor at 115200 baud to see ping results. } void loop() { delay(500); //-----get raw data----- rawValue1 = sonar1.ping_cm(); // Serial.println(rawValue1); if (rawValue1 >0){ myArray1 [counter1] = rawValue1; } counter1 += 1; if (counter1 >= 10) { counter1 = 0; } int allData1 = 0; for (int i = 0; i <= 10; i++) { allData1 = allData1 + myArray1[i]; } int average1 = allData1 / 10; // Serial.println(average1); sensorValue[0] = average1; rawValue2 = sonar2.ping_cm(); // Serial.println(rawValue2); if (rawValue2 >0){ myArray2 [counter2] = rawValue2; } counter2 += 1; if (counter2 >= 10) { counter2 = 0; } int allData2 = 0; for (int i = 0; i <= 10; i++) { allData2 = allData2 + myArray2[i]; } int average2 = allData2 / 10; // Serial.println(average2); sensorValue[1] = average2; rawValue3 = sonar3.ping_cm(); // Serial.println(rawValue2); if (rawValue3 >0){ myArray3 [counter3] = rawValue3; } counter3 += 1; if (counter3 >= 10) { counter3 = 0; } int allData3 = 0; for (int i = 0; i <= 10; i++) { allData3 = allData3 + myArray3[i]; } int average3 = allData3 / 10; // Serial.println(average3); sensorValue[2] = average3; rawValue4 = sonar5.ping_cm(); //sonar4 is broken // Serial.println(rawValue2); if (rawValue4 >0){ myArray4 [counter4] = rawValue4; } counter4 += 1; if (counter4 >= 10) { counter4 = 0; } int allData4 = 0; for (int i = 0; i <= 10; i++) { allData4 = allData4 + myArray4[i]; } int average4 = allData4 / 10; // Serial.println(average4); sensorValue[3] = average4; rawValue5 = sonar5.ping_cm(); // Serial.println(rawValue2); if (rawValue5 >0){ myArray5 [counter5] = rawValue5; } counter5 += 1; if (counter5 >= 10) { counter5 = 0; } int allData5 = 0; for (int i = 0; i <= 10; i++) { allData5 = allData5 + myArray5[i]; } int average5 = allData5 / 10; // Serial.println(average5); sensorValue[4] = average5; rawValue6 = sonar6.ping_cm(); // Serial.println(rawValue2); if (rawValue6 >0){ myArray6 [counter6] = rawValue6; } counter6 += 1; if (counter6 >= 10) { counter6 = 0; } int allData6 = 0; for (int i = 0; i <= 10; i++) { allData6 = allData6 + myArray6[i]; } int average6 = allData6 / 10; // Serial.println(average6); sensorValue[5] = average6; rawValue7 = sonar7.ping_cm(); // Serial.println(rawValue2); if (rawValue7 >0){ myArray7 [counter7] = rawValue7; } counter7 += 1; if (counter7 >= 10) { counter7 = 0; } int allData7 = 0; for (int i = 0; i <= 10; i++) { allData7 = allData7 + myArray7[i]; } int average7 = allData7 / 10; // Serial.println(average7); sensorValue[6] = average7; rawValue8 = sonar8.ping_cm(); // Serial.println(rawValue2); if (rawValue8 >0){ myArray8 [counter8] = rawValue8; } counter8 += 1; if (counter8 >= 10) { counter8 = 0; } int allData8 = 0; for (int i = 0; i <= 10; i++) { allData8 = allData8 + myArray8[i]; } int average8 = allData8 / 10; // Serial.println(average8); sensorValue[7] = average8; //Serial.print(sensorValue) Serial.println(average1); Serial.println(average2); Serial.println(average3); Serial.println(average4); Serial.println(average5);Serial.println(average6);Serial.println(average7);Serial.println(average8); //-----set pump pin----- // if distance > x, off pump is increased //find smallest two vertical distance int small_value1 = 100; //sensor value int small_value2 = 100; int small_pin1 = 0; //find sensor location int small_pin2 = 0; for (int i = 1; i < 4; i++){ // Serial.println(sensorValue[i],i); if (sensorValue[i] < small_value1 && sensorValue[i] != 0){ small_value1 = sensorValue[i]; small_pin1 = i+5; } } for (int i = 5; i < 8; i++){ if (sensorValue[i] < small_value2 && i != small_pin1 && sensorValue[i] != 0){ small_value2 = sensorValue[i]; small_pin2 = i+5; } } //Increase_Pump value int pump_updated = 80; //update the 2+5,4+5,6+5,7+5 if (small_pin1 <= 7){ small_pin1 = 7; } if (small_pin1 > 7){ small_pin1 = 9; } if (small_pin2 <= 11){ small_pin1 = 11; } if (small_pin2 > 11){ small_pin1 = 12; } //send signals analogWrite(small_pin1, pump_updated); analogWrite(small_pin2, pump_updated); int pumpArray1[4] = {7,9,11,12}; int pumpArray2[4] = {6,8,10,13}; for (int n = 0; n<4; n++) { if (pumpArray1[n] != small_pin1 | pumpArray1[n] != small_pin2){ analogWrite(n, 0); Serial.println(pumpArray1[n]); } } for (int n = 0; n<4; n++) { analogWrite(pumpArray2[n], 70); } }