Skip to content

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

  1. 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.
  1. State Variables

    bool isClose = false;
    bool isFar = false;
    bool vibratorsOn = false;
    int rssiValue = -100;
    

  2. These flags control what state the device is in based on RSSI proximity:

  3. isClose, isFar: To determine proximity zone.

  4. vibratorsOn: Used to only vibrate once when close.

  5. rssiValue: Stores signal strength from BLE device.

  6. BLE Scanner Callback Class

    class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
        void onResult(BLEAdvertisedDevice advertisedDevice) {
            if (advertisedDevice.getName() == deviceName) {
                rssiValue = advertisedDevice.getRSSI();
    

  7. When a BLE device is found, the callback checks if the name matches deviceName.
  8. 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
  1. Setup Function

    void setup() {
        Serial.begin(115200);
        pinMode(VIBRATOR_PIN, OUTPUT);
        digitalWrite(VIBRATOR_PIN, LOW);
    

  2. Initialize serial monitor for debugging.

  3. Set vibrator pin as output and turn it off initially.


strip1.begin();
strip2.begin();
strip1.show();
strip2.show();
- Initialize both LED strips and clear them.


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);
- Set up active BLE scanning and register the callback.

  1. 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);
    }
    
  2. 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);
}
- All LEDs flash white and then turn off, like a heartbeat blink.

  1. Main Loop Function
    pBLEScan->start(1, false);
    delay(100);
    
  2. 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);
}
- If the BLE device is close, vibrate once and do fade animation.


else if (isFar) {
    blinkingEffect(300);
}
If far, trigger blinking lights.

else {
    movingLines(100);
}
- If medium range, show the moving light effect.


FABRICATION FILES

  • Dress 01 Pattern 01 - Branches
  • Dress 02 Pattern 01 - Lichens
  • Dress 02 Pattern 02 - Lichens 02