Documentation

PROGRESS REFLECTION

The entire idea is from my ambition to expand the interaction to two person. I started the project from aiming to create a fun & spatial experience between people and environment. To fulfill this goal, certain design considerations come to mind that guide me throughout the whole process.

1. The time-based painting needs to be large enough to be seen.
By fulfilling this idea, me and Zach made a large easel from scratch. Marking, cutting, and mounting all the woods took us hours. However, this is a great learning process in that I knew how to use machines in the woodshops.
To create an experience of time, the paper roll was then mounted onto the easel and by manually pulling down when needed, it dropped onto a certain height, and being clamped to the easel.

2. The influx of colors are controllable.
I proceeded to test out the paint texture. The water-ish color flows too fast, which is harder to control, but the acrylic paint has higher viscosity that is more difficult to pump. After testing, I found that acrylic paint has heavier texture, which can be easier to control if we have a robust pump. Also, mixing a little water into the color will make the acrylic paint more fluidic.
When finding the pump that fits, I was trying to find excellent pumps from Amazon, but later I found out that IDEATE has lots of 12V pumps for lending that are also robust enough.

3. Color Mixture looks like a painting that has certain aesthetic.
I was experimenting on multiple color mixture ideas. The initial idea was just doing red and blue mixture — which turns purple only. Then, I found that more color variation could lead to more vibrance and dynamic effect. In the setup, there are three colors mixing together (red, blue, yellow), and there are six kinds of color possibilities each with multiple levels of mixture (red, blue, yellow, green, purple, orange).

4. The control of pumps on the painting are dependent on their distance between each other.
To capture the distance of two people, I used 8 ultrasonic sensors, with each sending signal to one pump. Mounting all the hardwares and manage the wiring + tubing is a super time-consuming process.
Though not managed to calibrate to a “working” state, I got all the required setups (code+hardware).

Things that was hard:
Setting Mechanics up: This took me an entire weekend. First I drew out the schematics, and try to produce a small demo before mounting. Then, the tedius part comes: I individually glued the pumps, sensors, breadboards, and Arduino to the Easel. Then, the wiring process requires a crystal clear mind to avoid making mistakes. Also, there are risks that things are burned. I nearly damaged all the hardwares because one time I was testing, the power supply immediately goes to 21V when turned on. I could even see smokes. All the lession learnt is to Stay Alert.
Cleaning: Thanks to the help from Zach and Erin, I was able to clean up the space after the presentation. The thing that I need to keep in mind in the future is to prepare for the mess beforehand (such as papers, napkins etc.), so that I will not spend lots of time wiping the floor and the table.

Things that I learned:
The installation process requires a huge amount of time and energy, and might result in lots of errors, so plan ahead and leave space for fixing / calibrating would be super important.
The presentation was — a physical MESS. Although my audience’s feedback was that seeing the pumps creating an unexpected effect was fun, I personally was not satisfied because the idea is to “control” my hardware to not go crazy. Before the next presentation (final show), one thing I should do is to make sure all the pumps work correctly, and the color will not be disrupting. But this could be a thing learnt as well: you never know how the final things turn out to be and how the intended effect and the actual one could be.

Finally, this is still a work-in-progess project that I can’t wait to iterate on!

 

Video

(This are just detailed shots of the set-up and not Working Demos!!! – Please wait for the final show :))

Code:

//FLUX
//This is the Arduino Code for operating the interactive painting setups. Pin assignment is listed below.
 
#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;

//Pin Mapping
int pump1 = 6;
int pump2 = 7;
int pump3 = 8;
int pump4 = 9;
int pump5 = 10;
int pump6 = 11;
int pump7 = 12;
int pump8 = 13;

int pumpValue1 = 100; //red
int pumpValue2 = 100; //blue
int pumpValue3 = 100; //red
int pumpValue4 = 100; //yellow
int pumpValue5 = 100; //yellow
int pumpValue6 = 100; //blue
int pumpValue7 = 100; //red
int pumpValue8 = 100; //blue

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 >= 20) {
    counter1 = 0;
  }
  int allData1 = 0;
  for (int i = 0; i <= 20; i++) {
    allData1 = allData1 + myArray1[i];
  }
  int average1 = allData1 / 20;
//  Serial.println(average1);
  sensorValue[0] = average1;


  rawValue2 = sonar2.ping_cm();
//  Serial.println(rawValue2);
  if (rawValue2 >0){
  myArray2 [counter2] = rawValue2;
  }
  counter2 += 1;
  if (counter2 >= 20) {
    counter2 = 0;
  }
  int allData2 = 0;
  for (int i = 0; i <= 20; i++) {
    allData2 = allData2 + myArray2[i];
  }
  int average2 = allData2 / 20;
//  Serial.println(average2); 
  sensorValue[1] = average2;


  rawValue3 = sonar3.ping_cm();
//  Serial.println(rawValue2);
  if (rawValue3 >0){
  myArray3 [counter3] = rawValue3;
  }
  counter3 += 1;
  if (counter3 >= 20) {
    counter3 = 0;
  }
  int allData3 = 0;
  for (int i = 0; i <= 20; i++) {
    allData3 = allData3 + myArray3[i];
  }
  int average3 = allData3 / 20;
//  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 >= 20) {
    counter4 = 0;
  }
  int allData4 = 0;
  for (int i = 0; i <= 20; i++) {
    allData4 = allData4 + myArray4[i];
  }
  int average4 = allData4 / 20;
//  Serial.println(average4); 
  sensorValue[3] = average4;


 
  rawValue5 = sonar5.ping_cm();
//  Serial.println(rawValue2);
  if (rawValue5 >0){
  myArray5 [counter5] = rawValue5;
  }
  counter5 += 1;
  if (counter5 >= 20) {
    counter5 = 0;
  }
  int allData5 = 0;
  for (int i = 0; i <= 20; i++) {
    allData5 = allData5 + myArray5[i];
  }
  int average5 = allData5 / 20;
//  Serial.println(average5); 
  sensorValue[4] = average5;


 
  rawValue6 = sonar6.ping_cm();
//  Serial.println(rawValue2);
  if (rawValue6 >0){
  myArray6 [counter6] = rawValue6;
  }
  counter6 += 1;
  if (counter6 >= 20) {
    counter6 = 0;
  }
  int allData6 = 0;
  for (int i = 0; i <= 20; i++) {
    allData6 = allData6 + myArray6[i];
  }
  int average6 = allData6 / 20;
//  Serial.println(average6); 
  sensorValue[5] = average6;



  rawValue7 = sonar7.ping_cm();
//  Serial.println(rawValue2);
  if (rawValue7 >0){
  myArray7 [counter7] = rawValue7;
  }
  counter7 += 1;
  if (counter7 >= 20) {
    counter7 = 0;
  }
  int allData7 = 0;
  for (int i = 0; i <= 20; i++) {
    allData7 = allData7 + myArray7[i];
  }
  int average7 = allData7 / 20;
//  Serial.println(average7); 
  sensorValue[6] = average7;


  rawValue8 = sonar8.ping_cm();
//  Serial.println(rawValue2);
  if (rawValue8 >0){
  myArray8 [counter8] = rawValue8;
  }
  counter8 += 1;
  if (counter8 >= 20) {
    counter8 = 0;
  }
  int allData8 = 0;
  for (int i = 0; i <= 20; i++) {
    allData8 = allData8 + myArray8[i];
  }
  int average8 = allData8 / 20;
//  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-----
//pump is from 100 to 255 
// if distance > x, red or blue pump is increased 

//find smallest two vertical distance
  int small_value1; 
  int small_value2;
  int small_pin1; //find sensor location
  int small_pin2;
  for (int i = 1; i < 4; i++){
    if (sensorValue[i] < sensorValue[i-1]){
      small_value1 = sensorValue[i];
      small_pin1 = i+5;
      }
    }
  for (int i = 5; i < 8; i++){
    if (sensorValue[i] < sensorValue[i-1] && i != small_pin1){
      small_value2 = sensorValue[i];
      small_pin2 = i+5;
      }
    }
  //Increase_Pump value
  int pump_updated = 200;
  
  Serial.println(small_pin2,small_pin1);
  //color spreading out
  analogWrite(small_pin1, pump_updated);
  analogWrite(small_pin2, pump_updated);

  //-----send signal to pump-----
  //Mixing: more left - more red element, more right - more blue element
  int pump_red = pumpValue1;
  int pump_blue = pumpValue1;
  int pumpArray[8] = {6,8,10,12};
  for (int i = 0; i < 8; i++){
    if (i+6 != small_pin1 | i+6 != small_pin2){
      analogWrite(i+6, pump_red);
    }
    pump_red = pump_red + 30;
    }
  int pumpArray[8] = {7,9,11,13};
  for (int i = 0; i < 8; i++){
    if (i+6 != small_pin1 | i+6 != small_pin2){
      analogWrite(i+6, pump_blue);
    }
    pump_blue = pump_blue - 30;
    }

//Serial.println(small_pin1,small_pin2);Serial.println(small_value1,small_value2);
 //analogWrite(pump1, pumpValue1);
//analogWrite(pump2, pumpValue2);
//analogWrite(pump3, pumpValue3);
//analogWrite(pump4, pumpValue4);
//analogWrite(pump5, pumpValue5);
//analogWrite(pump6, pumpValue6);
//analogWrite(pump7, pumpValue7);
//analogWrite(pump8, pumpValue8);

}