Skip to content

5. E-textiles

describe what you see in this image describe what you see in this image

Research & Exploration: Interactive Wearables

Overview

describe what you see in this image

This week’s assignment focused on exploring the world of e-textiles—the fusion of electronic components with fabric to create interactive, functional garments. My project centered on enhancing the wearability and usability of a previously designed costume by incorporating a touch-sensitive interface into the electronics system.

Specifically, I set out to replace the physical button on the back of the costume—which previously activated the wing lighting—with a touch sensor. By moving the control to a more accessible location, such as the wrist, I aimed to create a smoother and more intuitive user experience. This change would allow the performer or wearer to activate the lighting without the awkwardness of reaching behind their back.

References & Inspiration

describe what you see in this image

This project builds upon earlier work from Fab Academy 2024, particularly the custom PCB I designed for the backplate and wing system. The board was originally built to manage lighting effects across the wings, controlled by a simple digital button.

To make the system more user-friendly, I modified the existing PCB layout and hardware configuration to accommodate a capacitive touch sensor. This shift marks a meaningful step toward more seamless and gesture-based control systems for wearable technology.

Tools & Materials Used
  • Arduino Uno
  • Arduino IDE (Software)
  • Custom PCB board (Fab Academy 2024)
  • Copper tape (for the touch sensor)
  • Conductive thread (optional for future wearable integration)

Process & Workflow

Step 1: Testing the Chip & Identifying Connection Points

describe what you see in this image

The first task was to examine the existing PCB to locate the pins associated with the physical button. After identifying the correct connection point, I removed the button and prepared to replace it with a custom touch sensor.

To create the sensor, I used copper tape, arranging it in a pattern designed to maximize surface area while remaining discreet. This tape was adhered to the wrist area of the costume, ensuring it could be touched naturally during wear.

I ran initial tests to ensure the copper sensor responded correctly to human touch and could send signals to the microcontroller, mimicking the behavior of the original button.

Step 2: Coding the Touch Sensor

describe what you see in this image

I developed a custom code in Arduino IDE to program the microcontroller to respond to touch input from the copper sensor. The code controlled the LEDs on the wings, turning them on or off based on a single tap.

The challenge here was to ensure the sensor was responsive and stable, preventing flickering or accidental triggers. Debounce timing and sensitivity thresholds were adjusted for reliability and smooth operation.

Code Example

AnimatronicWingsWithLights_Works
#include 
#ifdef __AVR__
 #include  // Required for 16 MHz Adafruit Trinket
#endif

#include 

#define PIXEL_PIN    10
#define PIXEL2_PIN   2

#define BUTTON_PIN   7
#define PIXEL_COUNT  40

Adafruit_NeoPixel strip(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip2(PIXEL_COUNT, PIXEL2_PIN, NEO_GRB + NEO_KHZ800);

bool modeChanged = false; 
int mode = 0; // 0 for rainbow, 1-7 for solid colors, 8 for off
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50;

Servo servoR;
Servo servoL;

int servoRPin = 6;
int servoLPin = 20;

void setup() {
  Serial.begin(9600);
  strip.begin();
  strip.show();
  strip2.begin();
  strip2.show();
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  servoR.attach(servoRPin, 500, 2500);
  servoL.attach(servoLPin, 500, 2500);
}

void loop() {
  int reading = digitalRead(BUTTON_PIN);

  // Check button state and debounce
  if (reading == LOW) {
    if ((millis() - lastDebounceTime) > debounceDelay) {
      if (!modeChanged) {
        mode++;
        modeChanged = true;
        if (mode > 8) { // Update the maximum mode number
          mode = 0;
        }
        Serial.print("Mode changed to: ");
        Serial.println(mode);
      }
      lastDebounceTime = millis();
    }
  } else {
        modeChanged = false; // Reset mode changed flag when button is not pressed
  }

  if (mode == 0) {
    rainbowAnimation();
  } else if (mode >= 1 && mode <= 7) {
    solidColor(mode - 1);
  } else if (mode == 8) {
    turnOffLights();
  }

  if (mode != 8) { // Flap wings only if not in "off" mode
    flapWings(getFlapSpeed(mode));
  }
}

void flapWings(int speed) {
  static unsigned long lastUpdate = 0;
  static bool flapping = true;
  static int pos = 0;

  if (millis() - lastUpdate > speed) {
    if (flapping) {
      servoR.write(pos);
      servoL.write(180 - pos);
      pos++;
      if (pos >= 90) {
        flapping = false;
      }
    } else {
      servoR.write(pos);
      servoL.write(180 - pos);
      pos--;
      if (pos <= 0) {
            flapping = true;
      }
    }
    lastUpdate = millis();
  }
}

int getFlapSpeed(int mode) {
  switch (mode) {
        case 0: return 30;
        case 1: return 60;
        case 2: return 50;
        case 3: return 40;
        case 4: return 30;
        case 5: return 20;
        case 6: return 15;
        case 7: return 10;
        default: return 30;
  }
}

void rainbowAnimation() {
  static unsigned long lastUpdate = 0;
  static uint16_t j = 0;

  if (millis() - lastUpdate > 20) {
        for (int i = 0; i < strip.numPixels(); i++) {
          strip.setPixelColor(i, Wheel((i + j) & 255));
          strip2.setPixelColor(i, Wheel((i + j) & 255));
        }
        strip.show();
        strip2.show();
        j = (j + 1) % 256;
        lastUpdate = millis();
  }
}

void solidColor(int color) {
  uint32_t col;
  switch(color) {
        case 0: col = strip.Color(255, 0, 0); break;
        case 1: col = strip.Color(255, 165, 0); break;
        case 2: col = strip.Color(255, 255, 0); break;
        case 3: col = strip.Color(0, 255, 0); break;
        case 4: col = strip.Color(0, 0, 255); break;
        case 5: col = strip.Color(75, 0, 130); break;
        case 6: col = strip.Color(238, 130, 238); break;
        default: col = strip.Color(0, 0, 0); break;
  }
  for(int i = 0; i < strip.numPixels(); i++) {
        strip.setPixelColor(i, col);
        strip2.setPixelColor(i, col);
  }
  strip.show();
  strip2.show();
}

uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85) {
        return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if(WheelPos < 170) {
        WheelPos -= 85;
        return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

void turnOffLights() {
  for(int i = 0; i < strip.numPixels(); i++) {
        strip.setPixelColor(i, strip.Color(0, 0, 0));
        strip2.setPixelColor(i, strip.Color(0, 0, 0));
  }
  strip.show();
  strip2.show();
}

Step 3: Final Assembly & Testing

After the hardware and code were integrated, I carefully assembled the system into the costume. The sensor was secured at the wrist, wired to the PCB via jumper cables. Unfortunately, during the final round of testing, the chip overheated and burned out, likely due to a power supply misconfiguration or short circuit in one of the connections.

This prevented a live demonstration of the completed setup, but all preliminary tests with the sensor were successful.

I plan to revisit the setup with improved power protection and possibly switch to a more robust microcontroller to support future upgrades.

Secondary Sensor Exploration – Potentiometer for Light Frequency Control¶

During the development phase, I also experimented with adding a secondary analog sensor: a potentiometer. The goal was to allow manual adjustment of the blinking speed (frequency) of the LED lights on the wings. This would have given the wearer dynamic control over the visual effect in real-time, enhancing interactivity and theatrical impact.

The potentiometer was connected to an analog input pin on the microcontroller. I wrote preliminary Arduino code that mapped the potentiometer’s analog readings (ranging from 0–1023) to different delay times between LED flashes, effectively speeding up or slowing down the light animations based on the dial position.

Initial testing showed that the potentiometer worked smoothly with the system and gave intuitive control over the blinking rate. However, as the design of the costume and the electronics became more finalized, this feature was ultimately not needed. The program running on the custom PCB already handled multiple lighting modes and speeds through the touch interface, making the addition of a manual frequency control redundant.

Although it wasn’t used in the final assembly, this exploration was valuable. It provided an additional proof of concept for how analog inputs can expand the expressiveness of wearable electronics.

Key lessons from this test:

  • Analog sensors like potentiometers can easily integrate with digital wearable systems.

  • Simplicity often improves the user experience—adding too many controls can overwhelm rather than enhance.

  • Future iterations could explore using soft potentiometers or fabric-based analog sensors to maintain a fully textile-friendly design.

Code Example Analog Input

int sensorPin = A0;   // select the input pin for the potentiometer
int ledPin = 13;      // select the pin for the LED
int sensorValue = 0;  // variable to store the value coming from the sensor

void setup() {
  // declare the ledPin as an OUTPUT:
  pinMode(ledPin, OUTPUT);
}

void loop() {
  // read the value from the sensor:
  sensorValue = analogRead(sensorPin);
  // turn the ledPin on
  digitalWrite(ledPin, HIGH);
  // stop the program for <sensorValue> milliseconds:
  delay(sensorValue);
  // turn the ledPin off:
  digitalWrite(ledPin, LOW);
  // stop the program for <sensorValue> milliseconds:
  delay(sensorValue);
}

Reflection

This project provided valuable hands-on experience in merging electronics with textiles in a functional and user-centered way. Despite the hardware failure at the end, I was able to test and verify the core concept of replacing mechanical controls with touch-sensitive interfaces in wearable designs.

Key takeaways include: - The importance of testing hardware under realistic conditions - The need for proper voltage regulation and current protection - How user accessibility can be dramatically improved with thoughtful design choices

Moving forward, I intend to iterate on this prototype with more refined PCB designs, better power management, and potentially integrate conductive fabric to make the sensor completely embedded into the costume for an even cleaner look.

This exercise reinforced the creative possibilities of e-textiles and how they can be used to make wearables not only more functional, but also more magical and intuitive.


Next Steps

  • Redesign the PCB with built-in touch sensor input ports
  • Add voltage regulation circuits to prevent chip damage
  • Explore conductive fabric or thread as alternatives to copper tape
  • Produce a video demonstration once the revised prototype is working
  • Document the updated version as a step-by-step guide for others