Making of LÜM¶
Garment 01 - Vera¶
-
Vera (The Matulastic)
/vɛ-rah/
A calm force of nature.
Inspired by mutualism, Vera reflects the quiet harmony between fungi and tree roots — where both give, and both grow.
Earthy veins, soft layers, and glowing connections.
Design Pattern¶
Parametric Design¶
Pattern 01
Slicing¶
Pattern 01
Cura Slicing Settings
Setting | Value |
---|---|
Printer | Ultimaker S5 |
Material | nGen_FLEX (TPU-like) |
Color | Transparent Nude |
Layer Height | 1.0 mm |
Wall Line Count | 1 |
Wall Thickness | 0.4 mm |
Top Layers | 2 |
Bottom Layers | 2 |
Infill Density | 0% |
Infill Pattern | None |
Print Speed | 20 mm/s |
Travel Speed | 60 mm/s |
Nozzle Temperature | 230°C |
Build Plate Temp | 85°C |
Retraction Distance | 4.5 mm |
Cooling Fan | On (60%) |
Supports | None |
Adhesion Type | Brim |
Pause at Layer | Layer 1 |
Special Effect | None (Standard Print Mode) |
Pattern 02
Cura Slicing Settings
Setting | Value |
---|---|
Printer | Ultimaker S5 |
Material | PLA Filament |
Color | White |
Layer Height | 0.15 mm |
Wall Line Count | 2 |
Wall Thickness | 0.8 mm |
Infill Density | 20% |
Infill Pattern | Grid |
Print Speed | 50 mm/s |
Travel Speed | 120 mm/s |
Nozzle Temperature | 200°C |
Build Plate Temp | 60°C |
Retraction Distance | 6.5 mm (default Ultimaker) |
Cooling Fan | On (100%) |
Supports | None |
Adhesion Type | Brim |
Pause at Layer | Layer 4 |
3D Print¶
Pattern 01
Swatches
final Swatches
- Dress 01 Pattern 01 - Branches
Pattern 02
- Dress 01 Pattern 02 - Branches
Pattren Layout¶
*Layer 01 - Base
This Process was duplilcated on both Dress 01 & Dress 02
01 Design Measurments
02 Prototype
03 Assembly
*Layer 02 - 3D Printing on Tull
- Collect all prints together
Garment 02 - Luma¶
-
Luma (The Endosymbiosis)
/loo-mah/
A light that lives within.
Inspired by endosymbiosis, Luma channels the curious bond between lichens and trees — two lives intertwined as one.
Nestled shapes, hidden lights, and a pulse that glows from the inside out
Design Pattern¶
Parametric Design 01¶
Pattern 01
Pattern 02
Slicing¶
Pattern 01
Cura Slicing Settings
Setting | Value |
---|---|
Printer | Ultimaker S5 |
Material | nGen_FLEX (TPU-like) |
Color | Transparent Nude |
Layer Height | 0.3 mm |
Wall Line Count | 1 |
Wall Thickness | 0.4 mm |
Top Layers | 0 |
Bottom Layers | 0 |
Infill Density | 0% |
Infill Pattern | None |
Print Speed | 25 mm/s |
Travel Speed | 60 mm/s |
Nozzle Temperature | 230°C |
Build Plate Temp | 85°C |
Retraction Distance | 4.5 mm |
Cooling Fan | On (60%) |
Supports | None |
Adhesion Type | Brim |
Pause at Layer | Layer 7 |
Special Effect | Spiralize Outer Contour (Vase Mode) |
Pattern 02
Cura Slicing Settings
Setting | Value |
---|---|
Printer | Ultimaker S5 |
Material | PLA Filament |
Color | White |
Layer Height | 0.15 mm |
Wall Line Count | 2 |
Wall Thickness | 0.8 mm |
Infill Density | 20% |
Infill Pattern | Grid |
Print Speed | 50 mm/s |
Travel Speed | 120 mm/s |
Nozzle Temperature | 200°C |
Build Plate Temp | 60°C |
Retraction Distance | 6.5 mm (default Ultimaker) |
Cooling Fan | On (100%) |
Supports | None |
Adhesion Type | Brim |
Pause at Layer | Layer 4 |
3D Print¶
Pattern 01
Swatches 01
Phinal Swatches
- Dress 02 Pattern 01 - Lichens
Pattern 02
Swatches
final Swatches
- Dress 02 Pattern 02 - Lichens 02
Pattren Layout¶
*Layer 01 - Base
same as Layer Base Dress 01
*Layer 02 - 3D Printing on Tull
Electronics¶
What if garments could communicate? What if they could move beyond aesthetics and become an interactive language? This question is what led me to develop a garment that reacts to human connection—lighting up in response to movement and distance, creating a visual dialogue between the wearer and their surroundings.
I started by exploring electronic textiles and microcontrollers, testing how sensors and LEDs could respond dynamically. Through a series of experiments with XIAO ESP32 boards, I created a system where two garments communicate through proximity-based lighting—turning an outfit into an interactive performance. The journey involved material exploration, coding, and refining how light and movement could merge seamlessly into fabric.
🔌 First Spark¶
I dipped my toes into electronics with the good old breadboard—just me, some wires, and a sprinkle of chaos.
- 💡 LED, Meet Xiao
I started by hooking up an LED strip to the Seeed Studio XIAO ESP32C3. With the classic Blink code from Arduino, I got those lights to flash like a tiny rave. Success!
- 🔊 Then Came the Vibes
Next, I swapped the LEDs for a vibration motor. Using the same Blink logic, I made it buzz to life. Instant feedback—literally.
// Define the pin where your LED or vibration motor is connected
int pin = 2; // D2 on Xiao ESP32C3
void setup() {
pinMode(pin, OUTPUT); // Set the pin as output
}
void loop() {
digitalWrite(pin, HIGH); // Turn on
delay(500); // Wait 0.5 second
digitalWrite(pin, LOW); // Turn off
delay(500); // Wait 0.5 second
}
- 📶 Going Wireless
The final challenge? Bluetooth. I connected everything wirelessly through the Xiao ESP32 and watched it all come together—vibes and lights responding without a single cable in sight. Felt like magic. 🔮
#include <Arduino.h>
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <BLEService.h>
#include <BLECharacteristic.h>
BLECharacteristic *pCharacteristic;
bool deviceConnected = false;
#define SERVICE_UUID "12345678-1234-5678-1234-56789abcdef0"
#define CHARACTERISTIC_UUID "12345678-1234-5678-1234-56789abcdef1"
void setup() {
Serial.begin(115200);
BLEDevice::init("XIAO_BLE_Server"); // Name of the BLE device
BLEServer *pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
BLEService *pService = pServer->createService(SERVICE_UUID);
pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE
);
pService->start();
BLEAdvertising *pAdvertising = pServer->getAdvertising();
pAdvertising->start();
Serial.println("Waiting for a client to connect...");
}
void loop() {
// Server does nothing in the loop, just waits for connections
delay(1000);
}
class MyServerCallbacks : public BLEServerCallbacks {
void onConnect(BLEServer *pServer) {
deviceConnected = true;
Serial.println("Device connected!");
}
void onDisconnect(BLEServer *pServer) {
deviceConnected = false;
Serial.println("Device disconnected!");
}
}
E-Textile Circuit Layer¶
This layer is the functional tech core behind both interactive dresses. It holds all electronics: XIAO ESP32 board, RGB LEDs, vibrating motors, and their connections. It’s modular, washable, and connected to gloves via plug connectors. Two similar versions exist for Dress 1 (White) and Dress 2 (Pink).
🧰 Tools & Materials Used
Tool/Material | Purpose |
---|---|
XIAO ESP32 board | Microcontroller to control lights and haptics |
RGB LED Neopixel Strips | For visual feedback (3 per side = 6 per dress) |
Vibrating motors – Flat Coin | Used in Dress 2 (pink), flat design |
Vibrating motors – Round Type | Used in Dress 1 (white) |
2-pin Plug Connectors (15cm) | Modular glove-to-dress connection |
E6000 Glue | Fixing LED strips to fabric |
Zip ties | Stabilizing LED strips |
Heat shrink tubing | Reinforcing vibrator wire endings |
Spray paint | Aesthetic + insulation for wires |
Soldering iron + solder wire | Assembling all electrical joints |
Fabric base (custom cut) | Carries the circuit layer |
Velcro strips | Attaching/removing circuit from dress |
Power bank (USB-C) | Portable power source |
🧵 1. Base E-Textile Layer¶
A detachable textile layer sitting under the visible dress, containing all primary components.
- Starting with connecting everything together
now that eveything works by its own , the xiaos, the Ble , the vibrator , the LEDS lets connect them
- Built from a fabric sheet with 6 glued LED strips (3 on each side).
- E6000 glue + zip ties used to fix strips securely.
- Mounted inside dress using Velcro for easy detachment.
- Concealed pocket holds power bank on back interior.
- Spray-painted wires for insulation and aesthetic blend.
⚡ 2. Power & Microcontroller¶
🔋 Power Source - Powered by a USB-C portable power bank (placed in dress pocket).
🧠 XIAO ESP32 Pin Mapping
Board Label | GPIO | Role | Dress 1 | Dress 2 |
---|---|---|---|---|
D10 | 20 | LED Strip L | Pin 10 | Pin 9 |
D21 | 2 | LED Strip R | Pin 21 | Pin 10 |
D7 | 7 | Vibrators | Shared for both dresses |
- Pins chosen to allow for duplicated logic between both dress versions.
- Power routed from bank to ESP32 via USB-C.
- Ground, 3.3V, and signal lines distributed from board to LEDs and vibrators.
🧤 3. Glove Integration¶
🦾 The Glove Prototype Adventure¶
I started crafting a prototype for my interactive glove project. At first, I thought I'd need a vibrator motor, resistor, and an LDR to get things working. The idea was simple: when the light level dropped (because both models held hands), the LDR would detect the darkness, triggering the vibrators. Easy, right?
-
3D Printed Swatches as a prototype
-
adding vibrator, LDR, Resistor
What Prototyping helped me with ?
- 🔋 But Wait, There's More!
After some testing, I realized the Xiao ESP32 could handle the whole thing without a resistor or LDR! It could handle the vibrators directly and manage everything I needed. No extra parts needed! 🙌 The Xiao was ready to rock and roll, just like a superhero in disguise.
- 📶 Bluetooth to the Rescue
I then decided to add Bluetooth—not just to sync the gloves, but to use it as a distance sensor instead the LDR. Now, the distance between the two gloves could control the LED lights and vibrators. When the models were too far apart, the LEDs wouldn’t light up, and no vibration would happen. But as they got closer? Magic. ✨ Vibration and lights. No LDR required. Xiao’s got it all covered.
- 💡 In the End...
The Xiao was my hero, turning a complicated mess into a simple, sleek setup. No extra parts, no struggle—just pure creative bliss. Just the way I like it. 😎
Each glove includes 2 sewn-in vibrating motors that connect to the circuit via modular plugs.
Construction: - Made with 2 textile layers: base + 3D printed tulle overlay.
- Vibrating motors placed in sensational contact zones.
- Wires reinforced with heat shrink tubing.
Modular Connection: - Uses 15cm male-female 2-pin plug connectors: - Female end on the dress base layer. - Male end on the gloves. - Allowing quick snap-in and disconnect during wear.
Vibrator Types by Dress¶
Dress | Motor Type | Specs & Link |
---|---|---|
Dress 01 (White) | Round Vibrator | Aexit DC 3V Electric Motors 10000RPM 4mm x 12mm Cylindrical |
Dress 02 (Pink) | Flat Coin | BestTong 10000RPM Wired Vibration Motors 10mm x 2mm |
- Detachable gloves allow for independent wear or interaction.
- Plug system makes the glove modular and easy to repair.
- Vibrators are aesthetically hidden within glove seams.
📊 Schematic Diagram
+-----------------------------+
| XIAO ESP32 |
| [USB] [RESET] |
| |
| D10 / GPIO 20 → LED Strip L1 (Signal)
| D21 / GPIO 2 → LED Strip L2 (Signal)
| D9 / GPIO 21 → LED Strip L3 (Signal)
| D7 / GPIO 7 → Vibrators (Signal)
| GND -------- GND (LEDs + Vibrators)
| 3.3V ------- Power (LEDs only)
+-----------------------------+
| |
______|__ __|_____
| | | |
Vibrator 1 Vibrator 2 (→ gloves)
← LED Strip L1 LED Strip R1 →
← LED Strip L2 LED Strip R2 →
← LED Strip L3 LED Strip R3 →
[Each LED strip has 3 wires: GND (black), 3.3V (red), Signal (green)] [Each vibrator has 2 wires: Signal (red), GND (black) via GPIO7]
🧩 Design Highlights by Section¶
- Base Layer:
- Fabric base holds all electronics without impacting comfort.
-
Double-securing with glue + zip ties for LED stability.
-
Connectivity:
- Uses modular plug-ins to keep electronics detachable.
-
Wires painted and arranged aesthetically for visual blend-in.
-
Maintenance:
- Velcro system allows layer to be fully removed and washed.
-
All connections reinforced with shrink tubing or zip ties.
-
Aesthetics:
- Spray-painted wires blend into the fabric.
- Circuit design follows the contours of the body for minimal visibility.
Feature | Function |
---|---|
Modular | Gloves + circuit detach easily |
Interactive | LEDs + vibration respond to logic |
Wearable | Comfortable textile base, washable |
Duplicated | Designed identically for both dresses with slight pin changes |
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¶
🎬 Credits¶
This project was brought to life by a passionate team of creatives and technical talents. Deep gratitude to everyone involved:
- Models: Maria Abu Liel & Leen farraj
- Makeup Artist: Batoul
- Hairstylist: Hamzeh
- Director & Photographer: Alaa Makhlouf
- Soldering & Technical Support: Omar Baalbaki
- Tailors: Abo Omar & Waleed
- Lighting: Ahmad Kashkah
- Setup & Location Assistance: Hamid
- Sponsor: Bank Al Etihad
- Shooting Space: The MakerSpace CPf
-
Instructor:
- Claudia Simonelli - Anastasia Pistofidou - Cecilia Raspanti - Oscar Tomico -
Content Creation Support: Aya Al Mufti
- Event Location: The Spark by Bank Al Etihad
- Project Coordinator: Diala
- Endless Love & Support: My family & my friends – thank you for standing by me through every stitch and solder.
This wearable vision wouldn’t have existed without each and every one of you.