04 Deliverables¶
Twin Bond Timeline - GANTT¶
Task | Start Date | End Date | Duration | Status |
---|---|---|---|---|
Research & Surveys | 20/12/2024 | 09/01/2025 | 3 Weeks | âś… Completed |
Electronics Exploration & Prototype 1 | 10/01/2025 | 23/01/2025 | 2 Weeks | ⏳ In Progress |
Testing Recipes & Refining Electronics | 24/01/2025 | 30/01/2025 | 1 Week | ⏳ Pending |
Grasshopper Exploration & Digital Design | 31/01/2025 | 06/02/2025 | 1 Week | ⏳ Pending |
Prototype 2 (Refining & Testing) | 07/02/2025 | 13/02/2025 | 1 Week | ⏳ Pending |
First Swatches & Pattern Exploration | 14/02/2025 | 20/02/2025 | 1 Week | ⏳ Pending |
Garment Pattern & Prototyping | 21/02/2025 | 28/02/2025 | 1 Week | ⏳ Pending |
Final Assembly & Testing | 01/03/2025 | 07/03/2025 | 1 Week | ⏳ Pending |
Documentation & Final Presentation | 08/03/2025 | 14/03/2025 | 1 Week | ⏳ Pending |
Bill of Materials (BOM)¶
BOM for First Dress
Item | Approx. Price (USD) | Quantity | Source |
---|---|---|---|
Mesh Tulle (Transparent) | $10–15/meter | 3 meters | Kalha / Fabricjo / Maraqa Verde |
Base Fabric | $8–12/meter | 6 meters | Kalha / Fabricjo / Maraqa Verde |
TPU Filament (NGEN Phlex, Nude) | $40–60/roll | 1 roll (1kg) | Twins Chip / Micro Electronic |
LED Strips (Transparent) | $10–20/strip | 2–3 strips | Twins Chip / Micro Electronic |
XIAO ESP32 Microcontroller | $10–20 | 1 unit | Twins Chip / Micro Electronic |
Powerbank | $15–25 | 1 unit | Micro Electronic / Local Market |
Connecting Wires | $5–15 | As needed | Twins Chip / Micro Electronic |
Velcro | $2–5 | As needed | Local Market / Haberdashery Shops |
Transparent Thread | $3–5/roll | 1 roll | Local Sewing Stores |
E6000 Glue | $6–8/tube | 1 tube | Local Hardware / Fabric Stores |
Soldering Materials | $10–20 (kit) | As needed | Micro Electronic / Local Tools Market |
BOM for Second Dress
Item | Approx. Price (USD) | Quantity | Source |
---|---|---|---|
Mesh Tulle (Transparent + White) | $10–15/meter | 3 meters | Kalha / Fabricjo / Maraqa Verde |
Base Fabric | $8–12/meter | 6 meters | Kalha / Fabricjo / Maraqa Verde |
TPU Filament (NGEN Phlex, Nude) | $40–60/roll | 1 roll (1kg) | Twins Chip / Micro Electronic |
PLA Filament (White) | $30–50/roll | 1 roll (1kg) | Twins Chip / Micro Electronic |
LED Strips (Transparent) | $10–20/strip | 2–3 strips | Twins Chip / Micro Electronic |
XIAO ESP32 Microcontroller | $10–20 | 1 unit | Twins Chip / Micro Electronic |
Powerbank | $15–25 | 1 unit | Micro Electronic / Local Market |
Connecting Wires | $5–15 | As needed | Twins Chip / Micro Electronic |
Velcro | $2–5 | As needed | Local Market / Haberdashery Shops |
Transparent Thread | $3–5/roll | 1 roll | Local Sewing Stores |
E6000 Glue | $6–8/tube | 1 tube | Local Hardware / Fabric Stores |
Soldering Materials | $10–20 (kit) | As needed | Micro Electronic / Local Tools Market |
🎬 Storyboard – Interactive Garment Experience¶
Scene 01: Arrival
Two individuals—Vera and Luma—enter a dimly lit space. Their garments are quiet, still. The room is charged with anticipation, yet nothing seems out of the ordinary... until they begin to move.
Scene 02: The First Signal
As they take a step toward one another, a subtle shift occurs.
Vera’s garment begins to glow faintly—soft and warm. Luma’s remains still, waiting. The audience leans in.
Scene 03: Dynamic Connection
With each step closer, the system responds. Vera’s LEDs brighten, while Luma’s begin to dim—mimicking a relationship where one gives more, the other receives. A dance of imbalance. A metaphor for emotional dependency.
Scene 04: Recalibration
Suddenly, they pause. They recalibrate—step slightly apart, then move again, this time in sync.
Both garments glow together—equally luminous, equally alive. Balance achieved.
The LEDs shimmer in harmony, creating a visual dialogue of connection, trust, and equilibrium.
Scene 05: Human Interface
From across the room, observers watch this unfolding performance—not just a dance, but an emotional conversation translated through wearable tech. The garments become a medium. The space, a stage.
Each light change tells a story of proximity, emotion, and relationship.
Scene 06: Reflection
As Vera and Luma step apart again, the lights slowly fade, returning to stillness.
The audience is left wondering:
What if our clothing could express our energy? Our connections? Our feelings?
Scene 07: The Takeaway
This is more than just fabric and code—it’s a system of expression.
The garments don’t just respond—they communicate.
They invite interaction, reflection, and emotion—turning presence into poetry.
đź§µ Storytelling Approach – Interactive Garment Project¶
Imagine walking into a space where your presence is not just seen—but felt. Where what you wear responds to your movement, your energy, your connection with others.
But here's the issue: fashion has remained largely static.
Despite all the advancements in digital interaction, our garments remain passive. They don’t communicate. They don’t react.
In a world where everything is smart, why should fashion stay silent?
This project is made for designers, performers, and tech-driven creatives—people who believe that fashion can be more than fabric. That it can be a tool for interaction, expression, and connection.
With a background in digital design, 3D modeling, and visual storytelling, I’ve always been drawn to the in-between space—where fashion meets tech.
So I asked myself: what if garments could communicate? What if they could go beyond aesthetics and become a language—an interactive dialogue?
This led me to develop a garment that reacts to proximity and connection, lighting up as a visual expression of human presence.
I explored e-textiles, microcontrollers, and interaction design—experimenting with how sensors and LEDs could respond dynamically.
Using XIAO ESP32 boards, I built a system where two garments interact with one another based on distance, using light as a medium.
This turned clothing into a living interface—an outfit that performs with the wearer.
Imagine this: two people wearing the garments enter a space. They move closer. Suddenly, the garments glow, shifting based on proximity—a visual symphony of connection.
Now ask yourself: have you ever felt that your clothing could express more than style? What if it could express you—your emotions, your energy, your presence?
This project isn’t just a concept—it’s research-driven and user-tested.
I studied smart textiles and responsive wearables, consulted with experts in fashion tech & interaction design, and iterated on prototypes with real user feedback.
While responsive garments aren’t new, my approach pushes the boundaries—making them wearable, scalable, and emotionally meaningful.
I’m now exploring future collaborations with engineers and material scientists to refine the interaction and elevate the experience.
In a world where we often interact more with screens than with people...
This garment brings back human connection—turning fashion from something you wear into something you feel.
And this is only the beginning.
Imagine this tech in performance art, interactive exhibitions, or even everyday fashion—where your clothing adapts to your mood, your movement, and your moments.
The future of fashion isn’t just about what we wear—
It’s about how it responds to us.
Code¶
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
#include <Adafruit_NeoPixel.h>
// Bluetooth Settings
const char* deviceName = "ESP32-Device";
const int proximityThreshold = -32;
const int farThreshold = -45;
BLEScan* pBLEScan;
// Hardware Pins
#define PIN_1 10
#define PIN_2 21
#define NUM_LEDS 20
#define VIBRATOR_PIN 7
// LED Strips Setup
Adafruit_NeoPixel strip1(NUM_LEDS, PIN_1, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip2(NUM_LEDS, PIN_2, NEO_GRB + NEO_KHZ800);
// State Variables
bool isClose = false;
bool isFar = false;
bool vibratorsOn = false;
int rssiValue = -100;
// Bluetooth Scanning Class
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
void onResult(BLEAdvertisedDevice advertisedDevice) {
if (advertisedDevice.getName() == deviceName) {
rssiValue = advertisedDevice.getRSSI();
Serial.print("RSSI: ");
Serial.println(rssiValue); // Print the RSSI value to the Serial Monitor
if (rssiValue >= proximityThreshold) {
isClose = true;
isFar = false;
Serial.println("Status: Close");
} else if (rssiValue <= farThreshold) {
isFar = true;
isClose = false;
Serial.println("Status: Far");
} else {
isClose = false;
isFar = false;
Serial.println("Status: Medium");
}
}
}
};
void setup() {
Serial.begin(115200);
pinMode(VIBRATOR_PIN, OUTPUT);
digitalWrite(VIBRATOR_PIN, LOW);
strip1.begin();
strip2.begin();
strip1.show();
strip2.show();
BLEDevice::init(deviceName);
BLEServer *pServer = BLEDevice::createServer();
BLEAdvertising *pAdvertising = pServer->getAdvertising();
pAdvertising->start();
pBLEScan = BLEDevice::getScan();
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setActiveScan(true);
}
void fadeLines(int delayTime) {
for (int i = 0; i < NUM_LEDS; i++) {
strip1.setPixelColor(i, strip1.Color(255, 255, 255));
strip2.setPixelColor(NUM_LEDS - i - 1, strip2.Color(255, 255, 255));
strip1.show();
strip2.show();
delay(delayTime);
}
for (int i = 0; i < NUM_LEDS; i++) {
strip1.setPixelColor(i, strip1.Color(0, 0, 0));
strip2.setPixelColor(NUM_LEDS - i - 1, strip2.Color(0, 0, 0));
strip1.show();
strip2.show();
delay(delayTime);
}
}
void movingLines(int delayTime) {
for (int i = 0; i < NUM_LEDS - 1; i++) {
strip1.clear();
strip2.clear();
uint32_t color = strip1.Color(255, 255, 255);
strip1.setPixelColor(i, color);
strip1.setPixelColor(i + 1, color);
strip2.setPixelColor(i, color);
strip2.setPixelColor(i + 1, color);
strip1.show();
strip2.show();
delay(delayTime / 2);
}
}
void blinkingEffect(int delayTime) {
for (int i = 0; i < NUM_LEDS; i++) {
strip1.setPixelColor(i, strip1.Color(255, 255, 255));
strip2.setPixelColor(i, strip2.Color(255, 255, 255));
}
strip1.show();
strip2.show();
delay(delayTime);
strip1.clear();
strip2.clear();
strip1.show();
strip2.show();
delay(delayTime);
}
void loop() {
pBLEScan->start(1, false);
delay(100);
if (isClose) {
if (!vibratorsOn) {
digitalWrite(VIBRATOR_PIN, HIGH);
delay(5000);
digitalWrite(VIBRATOR_PIN, LOW);
vibratorsOn = true;
}
fadeLines(50); // Fades LED strips between each other
}
else if (isFar) {
blinkingEffect(300); // Independent blinking effect on each strip
}
else {
movingLines(100); // Independent moving lines effect on each strip
}
}
ESP32 BLE Proximity-Based LED & Vibration System¶
đź“„ Brief Summary
This code uses an ESP32 to detect a specific Bluetooth Low Energy (BLE) device by name. Depending on how close that BLE device is (based on its signal strength or RSSI), the ESP32 will trigger different lighting effects on two LED strips and activate a vibration motor.
Behaviors: - Close range → Activates the vibrator once + fade animation on LEDs. - Medium range → Moving light line animation. - Far range → Blinking light animation.
This setup can be used in wearables, interactive installations, or proximity feedback systems.
đź§© Code Breakdown
- Library Imports
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
#include <Adafruit_NeoPixel.h>
-
BLEDevice, BLEScan, etc. → Used for scanning nearby Bluetooth devices.
-
Adafruit_NeoPixel → Controls addressable LED strips.
-
BLE Settings and Thresholds
const char* deviceName = "ESP32-Device";
const int proximityThreshold = -32;
const int farThreshold = -45;
BLEScan* pBLEScan;
-
deviceName: The BLE device the ESP32 is scanning for.
-
proximityThreshold: RSSI level for "close" distance.
-
farThreshold: RSSI level for "far" distance.
-
pBLEScan: BLE scanner object used in the loop.
-
Hardware Pins & LED Setup
#define PIN_1 10 #define PIN_2 21 #define NUM_LEDS 20 #define VIBRATOR_PIN 7
-
PIN_1, PIN_2: Control two LED strips.
-
NUM_LEDS: Number of LEDs per strip.
-
VIBRATOR_PIN: Digital pin connected to a vibration motor.
Adafruit_NeoPixel strip1(NUM_LEDS, PIN_1, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip2(NUM_LEDS, PIN_2, NEO_GRB + NEO_KHZ800);
Define two NeoPixel LED strips with 20 LEDs each.
-
State Variables
bool isClose = false; bool isFar = false; bool vibratorsOn = false; int rssiValue = -100;
-
These flags control what state the device is in based on RSSI proximity:
-
isClose, isFar: To determine proximity zone.
-
vibratorsOn: Used to only vibrate once when close.
-
rssiValue: Stores signal strength from BLE device.
-
BLE Scanner Callback Class
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks { void onResult(BLEAdvertisedDevice advertisedDevice) { if (advertisedDevice.getName() == deviceName) { rssiValue = advertisedDevice.getRSSI();
- When a BLE device is found, the callback checks if the name matches deviceName.
- Then it stores the RSSI signal strength.
if (rssiValue >= proximityThreshold) {
isClose = true;
isFar = false;
} else if (rssiValue <= farThreshold) {
isFar = true;
isClose = false;
} else {
isClose = false;
isFar = false;
}
Decides the state based on signal strength:
>= -32: Close
<= -45: Far
Between: Medium
-
Setup Function
void setup() { Serial.begin(115200); pinMode(VIBRATOR_PIN, OUTPUT); digitalWrite(VIBRATOR_PIN, LOW);
-
Initialize serial monitor for debugging.
-
Set vibrator pin as output and turn it off initially.
strip1.begin();
strip2.begin();
strip1.show();
strip2.show();
BLEDevice::init(deviceName);
BLEServer *pServer = BLEDevice::createServer();
BLEAdvertising *pAdvertising = pServer->getAdvertising();
pAdvertising->start();
- Start BLE service and begin advertising (this is optional and not crucial here).
pBLEScan = BLEDevice::getScan();
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setActiveScan(true);
- LED Animation Functions
fadeLines(int delayTime)
for (int i = 0; i < NUM_LEDS; i++) { strip1.setPixelColor(i, white); strip2.setPixelColor(NUM_LEDS - i - 1, white); }
- Lights up the LEDs from outer edges to center (mirrored), then fades them back to black.
movingLines(int delayTime)
for (int i = 0; i < NUM_LEDS - 1; i++) {
strip1.clear();
strip2.clear();
strip1.setPixelColor(i, white);
strip1.setPixelColor(i + 1, white);
- Creates a "snake-like" white light moving across the strip.
blinkingEffect(int delayTime)
for (int i = 0; i < NUM_LEDS; i++) {
strip1.setPixelColor(i, white);
strip2.setPixelColor(i, white);
}
- Main Loop Function
pBLEScan->start(1, false); delay(100);
- Scans for BLE devices for 1 second every loop iteration.
Logic Based on Proximity:
if (isClose) {
if (!vibratorsOn) {
digitalWrite(VIBRATOR_PIN, HIGH);
delay(5000);
digitalWrite(VIBRATOR_PIN, LOW);
vibratorsOn = true;
}
fadeLines(50);
}
else if (isFar) {
blinkingEffect(300);
}
else {
movingLines(100);
}
FABRICATION FILES¶
- Dress 01 Pattern 01 - Branches
- Dress 02 Pattern 01 - Lichens
- Dress 02 Pattern 02 - Lichens 02