Bring the serenity of nature into your home with Caeruleo. Designed as both a calming decor piece and an interactive art installation, this project features a single light source that glides gracefully along the inner perimeter, creating mesmerizing glimmers and dynamic patterns. Its sound-responsive LEDs adjust to their surroundings—brightening and accelerating in noisy environments, and dimming and slowing down in quiet spaces—bringing a sense of harmony to your living area.
Building the code and circuit for our project from scratch was definitely a steep learning curve, but it was rewarding to see the project come to life
Process management is key for a project with so many steps: always planning ahead to avoid material delay/ burnouts, and keep things moving
Iterative thinking: prepare to tackle unexpected changes (eg: the frame)
What to Improve
I’d like to refine the frame’s finish with a mixed medium of air-dry clay and sand to experiment material mixes and achieve a more texturized, organic look
With fewer commitments from other classes, I’d love to create a more polished video to show the product in use + reaccentuate the design concept
I want to move away from utilitarian features and embrace a “less is more” philosophy to create something beautiful. Specifically, I’m drawn to the idea of crafting a round wall sculpture with a light source (narrow or wide) that slowly glides along the inner perimeter of the frame. I believe there’s a certain truth in this specific movement and aim to evoke a sense of calm and timelessness.
Here are my brainstorming drawings (very abstract) that explore the location of the light source, featured objects, light and shade, etc. I’m particularly fond of the fifth idea at the central bottom. It’s a flat, round wall decor piece with a light-colored frame. It features a base layer of light blue (made out of acrylic/ painted canvas/ wood/ another material) and a transparent layer of acrylic engraved with leaf veins. The concept involves a single light source on the inner perimeter that either physically moves around or creates this illusion with an LED strip. I also plan to hand paint transparent relief paste/ UV resin on top of the laser engraing to enhance the texture of leaf veins.
To enhance interaction, I plan to integrate a sound sensor that increases brightness when it’s noisy and decreases it when it’s quiet.
Problem Addressed/ Purpose of Making
Life in NYC is stressful; I miss the greenery of nature, and my meditation time is plummeting. I want to create an unconventional piece of house decor that can help me regain focus at home. The decor’s calming look symbolizes harmony; the gliding light will be a powerful tool for focus and meditation. Its smart reaction to ambient sound levels makes me feel connected to the space’s mood
_______________________________________________
*Previous Ideas
Split-Flap Clothing Palette Selector
A split flap clothes selector. It is attached to a gesture sensor and has three color wheels layered on top of each other, spinning independently on the same motor. The idea is I take pictures of my tops/ bottoms/ accessories and print them out on the color wheel, every time before I head out, I wave at the selector to help me pick a random (and hopefully good) outfit combination.
A police beacon with an LDR sensor on top that starts screaming whenever its surrounding gets too dark. It can be used to alert poor lighting in our studio.
A radar sensor setup to keep my desk area free of random objects. The idea is to use an Arduino radar sensor that scans the space and alerts me whenever anything out of place enters the zone. To avoid picking up hands or other moving objects, I might need an extra heat sensor to ignore any skin detection, etc. (Not totally sure if one sensor will cut it or if I’ll need a combo). (personal least favorite idea)
The result looks great and I’m really proud of this first cosplaying & Halloween parade attempt!! The character is Medusa Gorgon from Soul Eater (the anime) and the goal was to create replicates of her arrows that pair well with the costume. The purple fading light at the arrow heads turned out to be a perfect point of direction for my big classmate group at the parade too and I was recognized by the standby audience. 🥳🥳🥳
What Medusa and Dr. Stein looks like in Soul Eater:
📷Process photos
📘Reason of making
I wanted to cosplay Medusa from Soul Eater and thought NeonPixel and basic Arduino would be the best tools to product a glowing arrow effect, which by itself is a good wearable to wear around the waist and extend from behind.
🎩 How to wear
The plan was to attach 6 arrows around a waist band vertically to prevent sliding but I fell sick half of the week and only got to get 2 arrows done. Becky suggested it is common practice for cosers to wear the gears with a small backpack and that’s what I did with my costume in black. I basically shoveled the root of the arrows, connected to the Gemma M0 board and a power bank, into my backpack. I then fastened the structure by bending and securing the body of the arrow onto the shoulder belts as well as with tightened zippers. It turned out to be pretty sturdy and well.
📚 What I learned
Improved soldering skills on tiny LEDs
Improvising with material to achieve great outcomes
Basic Arduino coding
💭 What I would do differently
Plan better and order side LEDs earlier so to reserve more time to the most tedious soldering & wiring process
🧱 Materials
LEDs
Gemma M0
wires (blue, red, black)
soldering supplies
black foam tube (1 1/4” inner diameter)
blue foam
black acrylic paint
🔌 Circuit Diagram
(Will upload tomorrow morning)
⌨️ Arduino Code
// NeoPixel test program showing use of the WHITE channel for RGBW
// pixels only (won't look correct on regular RGB NeoPixel strips).
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif
// Which pin on the Arduino is connected to the NeoPixels?
// On a Trinket or Gemma we suggest changing this to 1:
#define LED_PIN 1
// How many NeoPixels are attached to the Arduino?
#define LED_COUNT 25
// NeoPixel brightness, 0 (min) to 255 (max)
#define BRIGHTNESS 50 // Set BRIGHTNESS to about 1/5 (max = 255)
// Declare our NeoPixel strip object:
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
// Argument 1 = Number of pixels in NeoPixel strip
// Argument 2 = Arduino pin number (most are valid)
// Argument 3 = Pixel type flags, add together as needed:
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
// NEO_RGBW Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
void setup() {
// These lines are specifically to support the Adafruit Trinket 5V 16 MHz.
// Any other board, you can remove this part (but no harm leaving it):
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
clock_prescale_set(clock_div_1);
#endif
// END of Trinket-specific code.
strip.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
strip.show(); // Turn OFF all pixels ASAP
strip.setBrightness(BRIGHTNESS);
Serial.begin(9600);
colorWipe(strip.Color(0, 0, 0, 0) , 0);
}
void loop() {
// Fill along the length of the strip in various colors...
/*
colorWipe(strip.Color( 0, 255, 0) , 50); // Green
colorWipe(strip.Color( 0, 0, 255) , 50); // Blue
colorWipe(strip.Color( 0, 0, 0, 255), 50); // True white (not RGB white)
whiteOverRainbow(75, 5);
pulseWhite(5);
rainbowFade2White(3, 3, 1);
*/
fadeToPurple(120);
}
void fadeToPurple(int wait) {
//for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
//strip.setPixelColor(i, color); // Set pixel's color (in RAM)
// fade in from min to max in increments of 5 points:
for (int fadeValue = 0; fadeValue <= 255; fadeValue += 5) {
// sets the value (range from 0 to 255):
colorAll(strip.Color(fadeValue, 0, fadeValue,0), 0);
//strip.setPixelColor(i, strip.Color(fadeValue, 0, 255,0));
// analogWrite(ledPin, fadeValue);
// wait for 30 milliseconds to see the dimming effect
delay(40);
Serial.print("fadevalue= ");
Serial.println(fadeValue);
strip.show(); // Update strip to match
}
// fade out from max to min in increments of 5 points:
for (int fadeValue = 255; fadeValue >= 0; fadeValue -= 3) {
// sets the value (range from 0 to 255):
colorAll(strip.Color(fadeValue, 0, fadeValue,0), 0);
//strip.setPixelColor(i, strip.Color(fadeValue, 0, 255,0));
// wait for 30 milliseconds to see the dimming effect
delay(40);
Serial.print("fadevalue= ");
Serial.println(fadeValue); }
strip.show(); // Update strip to match
//}
//delay(wait);
}
// Fill strip pixels one after another with a color. Strip is NOT cleared
// first; anything there will be covered pixel by pixel. Pass in color
void colorAll(uint32_t color, int wait) {
for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
strip.setPixelColor(i, color); // Set pixel's color (in RAM)
}
strip.show(); // Update strip to match
delay(wait); // Pause for a moment
}
// (as a single 'packed' 32-bit value, which you can get by calling
// strip.Color(red, green, blue) as shown in the loop() function above),
// and a delay time (in milliseconds) between pixels.
void colorWipe(uint32_t color, int wait) {
for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
strip.setPixelColor(i, color); // Set pixel's color (in RAM)
strip.show(); // Update strip to match
delay(wait); // Pause for a moment
}
}
void whiteOverRainbow(int whiteSpeed, int whiteLength) {
if(whiteLength >= strip.numPixels()) whiteLength = strip.numPixels() - 1;
int head = whiteLength - 1;
int tail = 0;
int loops = 3;
int loopNum = 0;
uint32_t lastTime = millis();
uint32_t firstPixelHue = 0;
for(;;) { // Repeat forever (or until a 'break' or 'return')
for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
if(((i >= tail) && (i <= head)) || // If between head & tail...
((tail > head) && ((i >= tail) || (i <= head)))) {
strip.setPixelColor(i, strip.Color(0, 0, 0, 255)); // Set white
} else { // else set rainbow
int pixelHue = firstPixelHue + (i * 65536L / strip.numPixels());
strip.setPixelColor(i, strip.gamma32(strip.ColorHSV(pixelHue)));
}
}
strip.show(); // Update strip with new contents
// There's no delay here, it just runs full-tilt until the timer and
// counter combination below runs out.
firstPixelHue += 40; // Advance just a little along the color wheel
if((millis() - lastTime) > whiteSpeed) { // Time to update head/tail?
if(++head >= strip.numPixels()) { // Advance head, wrap around
head = 0;
if(++loopNum >= loops) return;
}
if(++tail >= strip.numPixels()) { // Advance tail, wrap around
tail = 0;
}
lastTime = millis(); // Save time of last movement
}
}
}
void pulseWhite(uint8_t wait) {
for(int j=0; j<256; j++) { // Ramp up from 0 to 255
// Fill entire strip with white at gamma-corrected brightness level 'j':
strip.fill(strip.Color(0, 0, 0, strip.gamma8(j)));
strip.show();
delay(wait);
}
for(int j=255; j>=0; j--) { // Ramp down from 255 to 0
strip.fill(strip.Color(0, 0, 0, strip.gamma8(j)));
strip.show();
delay(wait);
}
}
void rainbowFade2White(int wait, int rainbowLoops, int whiteLoops) {
int fadeVal=0, fadeMax=100;
// Hue of first pixel runs 'rainbowLoops' complete loops through the color
// wheel. Color wheel has a range of 65536 but it's OK if we roll over, so
// just count from 0 to rainbowLoops*65536, using steps of 256 so we
// advance around the wheel at a decent clip.
for(uint32_t firstPixelHue = 0; firstPixelHue < rainbowLoops*65536;
firstPixelHue += 256) {
for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
// Offset pixel hue by an amount to make one full revolution of the
// color wheel (range of 65536) along the length of the strip
// (strip.numPixels() steps):
uint32_t pixelHue = firstPixelHue + (i * 65536L / strip.numPixels());
// strip.ColorHSV() can take 1 or 3 arguments: a hue (0 to 65535) or
// optionally add saturation and value (brightness) (each 0 to 255).
// Here we're using just the three-argument variant, though the
// second value (saturation) is a constant 255.
strip.setPixelColor(i, strip.gamma32(strip.ColorHSV(pixelHue, 255,
255 * fadeVal / fadeMax)));
}
strip.show();
delay(wait);
if(firstPixelHue < 65536) { // First loop,
if(fadeVal < fadeMax) fadeVal++; // fade in
} else if(firstPixelHue >= ((rainbowLoops-1) * 65536)) { // Last loop,
if(fadeVal > 0) fadeVal--; // fade out
} else {
fadeVal = fadeMax; // Interim loop, make sure fade is at max
}
}
for(int k=0; k<whiteLoops; k++) {
for(int j=0; j<256; j++) { // Ramp up 0 to 255
// Fill entire strip with white at gamma-corrected brightness level 'j':
strip.fill(strip.Color(0, 0, 0, strip.gamma8(j)));
strip.show();
}
delay(1000); // Pause 1 second
for(int j=255; j>=0; j--) { // Ramp down 255 to 0
strip.fill(strip.Color(0, 0, 0, strip.gamma8(j)));
strip.show();
}
}
delay(500); // Pause 1/2 second
}
Intention: cosplay Medusa from Soul Eater as much as possible! (first cosplay in life ever 👻👻👻)
Arduino technique:
button controlled LED lighting
Fading purple LED light that only glows around the arrow heads so it is recognizable in the dark (against black arrows and black costume)
Material
galvanized wire: to create bendable arrows and a strong frame for waist band where central control is located on
black electrical tape: to wrap around and protect the joints where wires are bent
foam tube: to build the body of tubes
foam block (maybe just blue foam?): to band saw individual arrow heads and spraypaint it black
LED stripe: to wrap around the edges of foam arrow heads and glow
extension cord (from VFL): to connect the LEDs at the far ends of the arrows with the controller on the waist
Medusa cosplay costume: jumpsuit, wig, body paint stick (for Medusa’s snake tatto on the arm), lab coat
(All materials have been purchased and some of them already arrived)
TODO List
test the fitting of foam tubing on galvanized wire & extension cord
saw individual arrow heads x6
stick LED strips around the outline of arrow heads
make the waist band with strong wire support & covered in black clothes to hide the wire & arduino board
cut foam tubes into sections of varying length, then insert wires
solder LED strips onto extension cords insert cords, insert the extension cords through sections of the foam tubing for each arrow, then solder all extension cords to the arduino board with button controller on the waist band
Here’s my plush night light The Cube! The inspiration originates from Rubik’s Cube that often features a highly geometric, structured shape and interesting variations in color.
The Cube with different environmental lighting:
The target user is for myself and the design is meant to be a tool that reminds me of the juxtaposition of material softness and fixed geometry. It is supposed to be a fun toy to show the contrast. It is a light that seduces the audience to pause, observe, and meditate about abstract qualities.
Materials include Superfine 4-Way Stretch Net Fabric Nylon Spandex Power Mesh, cotton, LEDs (red, yellow, blue, white, green), 4.5v battery pack, resistors (100ohm, 150ohm).
Project Progress
Something New: I learned to connect multiple colored LEDs to the same power source, choosing varying resistors per color and
Challenge: It turned out to be very difficult to sew a real-looking ball without breaking it in multiple pieces. The resistor requirement of green LED turned out to be quite different from red and yellow, and the green color did not turn out to be super visible.
Surprise: The huge chunk of combined wires really worked!
If Had More Time
I will try figuring out a way to make better-looking balls and a much more diverse selection of surface fabrics in combination with different colored LEDs inside in order to create more complicated textures and lighting experiences.
But reflecting on the working process, I realized the best way to curate perfectly round balls is by just using ping pong balls, and I would have put more attention into the wrapping materials.
Process Images (so sorry I forgot to take the photos of me wrapping cotton &mesh onto the LED-filled ping pong balls and sewing them)
Here’s how the parts look after I hot glued the color-labeled edges of wires via the small holes on ping pong balls. The sewing to tightly wrap the ping pong balls inside the mesh layer seems pretty random (though did the job) and the shapes become very unpredictable.
Finally I decided on a simple version of the previous “rubik’s cube”:
In total, this design generates 8 small cotton balls tightly bonded to the metal frame in the middle. Ideally the balls should bulge outwards and I also plan on installing different colored lights inside the balls to create a lovely experience.
User: myself
Story/ Intention: I really wanted a night lamp that can be hold and played by hand, instead of as a house decor. I also wanted to make some with that has a structure but also interesting contrasts between the structure and its counterparts. So I decided to manipulate the material structure of rubik’s cube and create a handhold lamp.
Fabric:
I originally bought fabric from a shop for the anglerfish but decided to go for something different, so I ordered it from Amazon and looks like this
The JBL Speaker looks very seamlessly integrated from outside with zero screws. So I used a file and a hammer to pry the curved perforated metal front off to examine further.
I broke off the soft silicon pads on the bottom of the speaker and smashed open one end.
I tried to pry off buttons from the other end to reveal inner structures, then used it as a breaking point to pry open the exterior shell. The exterior shells turned out to have three layers and screwed to the black inner part in an invisible way (screws were hidden behind the two round pads at the ends).
Breaking down the innermost part was very painstaking. I first unscrewed all the screws I could find only to realize the halves of this chunk seems tightly glued along the middle line. I tried to pry it open from multiple angles with no luck. Inspired from the teardown videos of other JBL speakers, I managed to find a hidden screw located at the central back and via here was finally able to break it open.
Here’s what’s at the heart of the JBL Speaker: a tube, some damping foams, two speaker drivers, one main circuit board, and one lithium battery underneath.
Here’s the final look from the JBL teardown with labeling.
Two Interesting Designs
Bass Reflex Tube
How it works: when the speaker is on, the speaker drivers push air through the tube to the outside. The shape of the tube is also carefully designed to resonate in a way that boosts lower frequencies and improves bass response.
Three-Layer Outer Shell
The three layers tightly bind with one another and add extra colors & textures to the speaker’s exteriors. They also provide stronger binding for the relatively delicate inner part and protect it from potential impacts. I also think their particular shape acts as a weight balance for the speaker to stay flat on the table with the perforated steel front always facing forward.
Tools & Techniques during Teardown
Tools
Techniques
Pliers of different sizes
Screwing/Unscrewing
Cutting plier
Prying
Files of different sizes
Smashing (attempted)
Philips screwdriver
Component & Material & Manufacturing
Component
Material
Manufacturing Technique
Perforated Steel Front
Perforated Steel
Sheet Metal Punching, Stamping
Outer Shell (Three-layered)
Plastic (ABS/Polycarbonate)
Injection Molding
Round End Caps
Plastic (ABS or Polycarbonate) with Rubber Inserts
Injection Molding, Overmolding
Speaker Drivers
Diaphragm: Mylar/Polypropylene, Frame: Metal (Steel/Aluminum)
I’m originally from Chongqing, China and completed my B.A. in Classical Studies at University of Chicago in 2023. My education experience mostly concentrated in the field of humanities (literature, cultural studies, cinema studies, history, philosophy, etc.) but I also gained exposure to game studies & design, disability and design, and urban planning & architecture through classes – all of which are topics I look forward to exploring further.
I volunteered for non-profits as a User Researcher before PoD and other work experience includes strategy work at tech companies and management consulting. Equipped with a business scope, I decided to pivot to product design in order to gain more comprehensive knowledge on the product development cycle, to be more involved in the product creation processes, and build impact.
Hobby
Recently developed an interest in aquarium keeping/ aquascaping and I currently have a 5.5 gallon tank at home with one betta fish, two shrimps, and three snails 🐠🐠🐠
Swimming/ Hiking/ Fishing 🌲🌲🌲
Looking forward to get Open Water Diver certificate in the next two years 🤿🤿🤿
Favorite food
It’s so hard to choose honestly! I love hotpot, but I also had a blast trying all the American, Italian, Fusion, and French spots in Chicago and Boston. Definitely excited to explore a bunch of new places in NYC!