W9-Project2-Balloon
Project Demo
My project is a device that can blow up a balloon both in the physical and digital world simultaneously and preserve digital balloons each individual created in a virtual world.
Concept
After coming to the states, I was shocked and excited when I learned there are stores that sell and only sell balloons. For someone who will stop crying if he could get a double-layered balloon outside the hospital before seeing the doctor, that's like the best place in the world. Maybe after the shops only sell candies. Of course, when I still was a child, I don't cry before seeing a doctor now. I enjoyed the satisfaction of blowing a tiny rubber into a large ball. It felt great when you consider blowing a balloon as capturing air, the thing we cannot touch or see. However, a balloon pops and deflates. And you can't get all the colors you want; even you own a balloon shop. So I wanted to create a device that can provide the same physical sensation of blowing a balloon while providing countless colors and preserving each balloon made.
Sketch
My original idea was to build a smart balloon blower that warns people when the balloon reaches the limit before exploding because no one wants that surprise. The idea was to use an air pressure sensor to read the pressure and use the RGB LEDs inside the balloon to show the warning colors. Then, record the balloon's size by getting data from the air pressure sensor to draw and store each balloon on the computer.
Then I shifted the idea from using an electric air pump to manually blowing with mouth and changing the light as a warning indicator to individual balloons' color tool. So the device and the interactive experience is more intimate and personal to the user.
Device setups
The physical device contains a pressure sensor and several RGB LEDs while connecting to a p5 sketch on the laptop. The size of the digital balloon reacts to the physical one in real-time. The user can press the button on the top to pick a color and then blow up the balloon through the device. To push the button again, the user can release the digital balloon he or she just created.
The air pressure sensor communicates with the Arduino with I2C communication. The SDA and SCL pins are connected to A4 and A5 pins on the Arduino. And LEDs are connected to the 9,10,11 digital pins with PWM and the ground from the Arduino. The switch is simply connected to digital Pin 2 on Arduino, and it controls color picking and releasing the digital balloon.
The housing for the device is a metal T-tube. The size perfectly fits in the air pressure sensor. All the wires, except the two for the switch, go into the tube. I used the electrical tape to seal and package everything into one. Quite happy about the finished house for this device.
Software
Arduino
The software part is less complicated after I figured out the air pressure sensor. It wasn't working as I expected. I was experiencing a weird peak right after I started blowing into the tube, and then a sudden drop shortly after. This issue caused a lot of trouble and made the experience less pleasing and confusing. Danny suggested to average the readings overtime to flatten out the sudden spike initially. It helped a lot and solved the initial problem I had. However, the sensor still couldn't fully react to the balloon size correctly. I guessed that the balloon size change influences the air pressure, so it needs time to reflect the actual pressure.
The code I am running now isn't perfect but can achieve most of the ideas I planned to do.
Most of the code for reading the sensor is from the library.
These codes are for mapping the pressure reading, P, and average it over time.
status = pressure.getPressure(P, T); if (status != 0) { mappedValue = map(P, 1022, 1045, 0, 200); averageValue = mappedValue * 0.1 + averageValue * 0.9; }
This is the function to set LED colors
//Changing color for LED void setColors( int red, int green, int blue) { analogWrite(rPin, red); analogWrite(gPin, green); analogWrite(bPin, blue); }
This is for switching different states by the switch
Mode 0 is the initial state where the balloon is flashing with random colors.
Mode 1 is for picking a color, and it will immediately jump to Mode 2 after assigning each RGB pin with a value.
Mode 3 is releasing the balloon, and it will immediately go back to Mode 0
if (switchState == HIGH && lastSwitchState == LOW ) { mode++; delay(1); } lastSwitchState = switchState; if (mode == 0) { rValue = random(255); gValue = random(255); bValue = random(255); setColors(rValue, gValue, bValue); delay(50); } if (mode == 1) { rValue = random(255); gValue = random(255); bValue = random(255); setColors(rValue, gValue, bValue); mode ++; } if (mode == 3) { Serial.print(mode); Serial.print(","); Serial.print(averageValue); Serial.print(","); Serial.print(rValue); Serial.print(","); Serial.print(gValue); Serial.print(","); Serial.println(bValue); delay(50); mode++; } if (mode > 3 ) mode = 0; Serial.print(mode); Serial.print(","); Serial.print(averageValue); Serial.print(","); Serial.print(rValue); Serial.print(","); Serial.print(gValue); Serial.print(","); Serial.println(bValue); delay(5); }
P5
Getting data and sorting and sorting them into an array.
function serialEvent() { // this is called when data is recieved, data will then live in fromSerial //fromSerial = serial.read(); let stringFromSerial = serial.readLine(); // reads everything till the new line charecter if (stringFromSerial.length > 0) { // is the something there ? let trimmedString = trim(stringFromSerial); // get rid of all white space let myArray = split(trimmedString, ","); // splits the string into an array on commas fromSerialState = Number(myArray[0]); // get the first item in the array and turn into integer fromSerialoffSet = Number(myArray[1]); fromSerialr = Number(myArray[2]); fromSerialg = Number(myArray[3]); fromSerialb = Number(myArray[4]); } // get the second item in the array and turn into integer }
I create a class for creating balloon
class Balloon { constructor(offset, r, g, b) { this.offSet = offset; this.x = width / 2; this.y = height - 200; this.xSpeed = random(-1, 1); this.ySpeed = random(0, 1); this.color = color(r, g, b); } display() { push(); translate(this.x, this.y); beginShape(); smooth(); noStroke(); fill(this.color); vertex(65, 150); bezierVertex( -15 - 0.5 * this.offSet, 110 - this.offSet, -25 - 0.5 * this.offSet, 0 - this.offSet, 65, 0 - this.offSet ); bezierVertex( 145 + 0.5 * this.offSet, 0 - this.offSet, 155 + 0.5 * this.offSet, 100 - this.offSet, 65, 150 ); endShape(); pop(); } move() { this.x += this.xSpeed; this.y -= this.ySpeed; console.log(this.y); } stop() { if (this.y < 0) { this.ySpeed = 0; this.xSpeed = 0; } if (this.x < 10 || this.x > width - 152) { this.xSpeed = 0; } } }
function createBalloon() { let balloon = new Balloon( fromSerialoffSet, fromSerialr, fromSerialg, fromSerialb ); balloons.push(balloon); ttlCreated++; }
Took me such a long time to draw the balloon on p5. Using the bezier curve is so much harder than I thought. And the result was just fine.
function blowBallon() { push(); translate(width / 2, height - 200); beginShape(); smooth(); noStroke(); fill(fromSerialr, fromSerialg, fromSerialb); vertex(65, 150); bezierVertex( -15 - 0.5 * fromSerialoffSet, 110 - fromSerialoffSet, -25 - 0.5 * fromSerialoffSet, 0 - fromSerialoffSet, 65, 0 - fromSerialoffSet ); bezierVertex( 145 + 0.5 * fromSerialoffSet, 0 - fromSerialoffSet, 155 + 0.5 * fromSerialoffSet, 100 - fromSerialoffSet, 65, 150 ); endShape(); pop(); }
Displaying all the balloon in the draw loop.
if (fromSerialState == 3) { createBalloon(); //fromSerialState =0; } else { blowBallon(); } for (b of balloons) { b.display(); b.move(); b.stop(); }