9. WEARABLES¶
In this week of WEARABLES, we are building on our knowledge of E-TEXTILES and using a micro controller to integrate electronics into a wearable device of some kind.
RESEARCH & INSPIRATION¶
There are some really cool Wearables being done by a few different fashion companies. I have a few examples below
Stone Island is ahead of the game with their Thermochromatic fabrics and garments
Junya Watanabe also has experimented with adding electronics into his work
I also looked into what is a growing industry of making garments or wearables that obfuscate surveillance systems.
one of which was a visor that disrupts AI ability to read faces.
TOOLS¶
- FABRIXIAO (seeed studio XIAO RP2040)
- NEOpixels
- Arduino Big Sound Sensor
- Gravity I2C 16x2 Arduino LCD with RGB Font Display (Black) V1.0
- Arduino Joystick
- ThermoChromatic pigment
- Brother Digital Embroidery Machine
ELECTRONIC PIN OUTS¶
SOFTWARE¶
- Arduino IDE
- Inkscape
- InkStich Extension
PROCESS AND WORKFLOW¶
I managed to fry my AdaFruit Flora somehow and so this week i switched to the FabriXiao
I first had to solder the micro controller to the board and learn the differences between the two different boards.
These are the actuator types i will be using and exploring:
-
LED Strips: LEDs are commonly used for visual feedback or decorative lighting. They can be controlled via microcontrollers to change color, brightness, or patterns, often responding to external factors like sound or touch. They are widely used in wearables for their low power consumption and flexibility.
-
Sound Sensors: These sensors pick up sound vibrations and convert them into electrical signals. In wearables, sound sensors can trigger LEDs or other effects in response to music, voice, or environmental noise. This interaction adds an auditory dimension to wearable projects.
-
Thermochromatic Ink: This ink changes color with temperature fluctuations. It can be integrated into textiles for interactive designs, responding to heat from the wearer's body or external sources, creating a dynamic, ever-changing visual effect.
-
Joystick: A joystick is an input device that allows the user to control the wearable's functions. For example, it can control the color or brightness of LEDs by detecting the position of the joystick, offering a tactile way for users to interact with the wearable.
LED JOYSTICK¶
My First sample was a NEOpixel strip that I was controlling with a arduino joystick.
Depending on how I move the joystick it will change the Color and brightness of the LEDS.
If I click the button of the joystick it will also flash the LEDS and switch to a different mode where the LEDS blink while also still having the same color changing properties of the joystick.
CODE EXAMPLE 1¶
#include <Adafruit_NeoPixel.h>
// Define pin and number of pixels
#define PIN D5 // Pin for the 4-LED NeoPixel strip
#define NUMPIXELS 4 // Number of pixels in the strip
// Define joystick analog input pins
#define JOY_X A0 // X-axis pin of the joystick
#define JOY_Y A1 // Y-axis pin of the joystick
#define JOY_BTN D9 // Button pin of the joystick
// Create NeoPixel object
Adafruit_NeoPixel strip(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
// Define color states for the button press
int colorState = 0; // Used to cycle through colors when button is pressed
// Variables to store the actual center position of the joystick
int centerX = 512;
int centerY = 512;
// Flag to track the current mode
bool isMode1 = true; // Default to Mode 1 (Joystick controls RGB)
// Deadzone value (tolerance for joystick drift)
int deadzone = 100; // You can adjust this value for higher tolerance
// Color cycling states (you can add more colors here)
unsigned long colors[] = {
0xFF0000, // Red
0x00FF00, // Green
0x0000FF, // Blue
0xFFFF00, // Yellow
0xFF00FF, // Magenta
0x00FFFF // Cyan
};
void setup() {
// Initialize the NeoPixel strip
strip.begin();
strip.show(); // Clear the strip initially
// Set the joystick button pin as input
pinMode(JOY_BTN, INPUT_PULLUP); // Use the internal pull-up resistor
// Calibrate the joystick center
calibrateJoystick();
}
void loop() {
// Read the joystick X and Y axis values (0 to 1023)
int xValue = analogRead(JOY_X); // Read X-axis (left-right)
int yValue = analogRead(JOY_Y); // Read Y-axis (up-down)
// Check if the joystick button is pressed (button is LOW when pressed)
if (digitalRead(JOY_BTN) == LOW) {
// Toggle between Mode 1 and Mode 2 when the button is pressed
toggleMode();
delay(500); // Simple debounce to prevent multiple presses
}
if (isMode1) {
// In Mode 1, control RGB based on joystick movement
controlRGBWithJoystick(xValue, yValue);
} else {
// In Mode 2, control the color cycling with joystick
controlColorCycling(xValue, yValue);
}
delay(50); // Smooth transition delay
}
// Function to set color and brightness for all LEDs in the strip
void setStripColor(int r, int g, int b, int brightness) {
for (int i = 0; i < NUMPIXELS; i++) {
// Apply brightness scaling
int scaledR = r * brightness / 255;
int scaledG = g * brightness / 255;
int scaledB = b * brightness / 255;
strip.setPixelColor(i, strip.Color(scaledR, scaledG, scaledB));
}
strip.show(); // Update the strip with the new colors
}
// Function to control RGB blending using joystick (Mode 1)
void controlRGBWithJoystick(int xValue, int yValue) {
// Apply deadzone to eliminate small unwanted movements
if (abs(xValue - centerX) < deadzone) xValue = centerX;
if (abs(yValue - centerY) < deadzone) yValue = centerY;
// Calculate joystick movement with dead zone tolerance
int xMovement = abs(xValue - centerX); // Calculate absolute movement from center
int yMovement = abs(yValue - centerY);
// Calculate total movement (sum of X and Y) to determine brightness
int totalMovement = xMovement + yMovement;
// Map the total movement to brightness (0-255)
int brightness = map(totalMovement, 0, 1023, 0, 255);
brightness = constrain(brightness, 0, 255); // Ensure brightness is within 0-255
// Map X-axis to red and green channels, Y-axis to blue channel
int red = map(xValue, 0, 1023, 0, 255); // X-axis controls red
int green = map(yValue, 0, 1023, 0, 255); // Y-axis controls green
int blue = map(abs(xValue - yValue), 0, 1023, 0, 255); // Combined movement for blue
// Set the color and brightness of the NeoPixel strip
setStripColor(red, green, blue, brightness);
}
// Function to control color cycling using joystick (Mode 2)
void controlColorCycling(int xValue, int yValue) {
// Use the joystick's X and Y axis to adjust the color state
int xMovement = abs(xValue - centerX);
int yMovement = abs(yValue - centerY);
int totalMovement = xMovement + yMovement;
// Map movement to switch color states
int colorChangeRate = map(totalMovement, 0, 1023, 0, 5); // Adjust rate of color change
if (colorChangeRate > 0) {
colorState = (colorState + colorChangeRate) % 6; // Cycle through the colors
}
// Set all pixels to the color corresponding to the current state
setStripColor(
(colors[colorState] >> 16) & 0xFF, // Red
(colors[colorState] >> 8) & 0xFF, // Green
colors[colorState] & 0xFF, // Blue
255
);
}
// Function to toggle between Mode 1 and Mode 2 when the button is pressed
void toggleMode() {
isMode1 = !isMode1; // Toggle the mode
if (isMode1) {
// Clear strip when switching back to Mode 1
strip.clear();
strip.show();
}
}
// Function to calibrate the joystick center position
void calibrateJoystick() {
// Read the joystick values when it's at rest (before beginning the loop)
centerX = analogRead(JOY_X);
centerY = analogRead(JOY_Y);
// Add some delay to make sure we get the stable readings
delay(500); // Calibrate for half a second
Serial.print("Calibrated Center - X: ");
Serial.print(centerX);
Serial.print(" Y: ");
Serial.println(centerY);
}
DECIBLE COUNTER AND DISPLAY¶
My second sample was a decible counter connected to an LCD screen.
The big sound sensor is basically acting as a microphone to pick up noise from the surroundings.
The LCD screen then displays the decible level.
It also changes the backlight color at different decible levels.
CODE EXAMPLE 2¶
#include <Wire.h>
#include <DFRobot_RGBLCD1602.h> // Library for Gravity I2C LCD
#define SOUND_SENSOR_PIN A0 // Analog pin for Big Sound Sensor
const int sampleWindow = 50; // Time window for sound measurement (ms)
// LCD setup: Set I2C address (default: 0x27)
DFRobot_RGBLCD1602 lcd(/*RGBAddr*/0x60 ,/*lcdCols*/16,/*lcdRows*/2);
void setup() {
Serial.begin(9600);
// Initialize the LCD
lcd.init();
lcd.setRGB(0, 0, 255); // Set LCD backlight to blue (quiet)
lcd.setCursor(0, 0);
lcd.print("Decibel Meter");
delay(2000);
lcd.clear();
}
void loop() {
unsigned long startMillis = millis(); // Start of sampling window
unsigned int signalMax = 0;
unsigned int signalMin = 4095; // RP2040 ADC is 12-bit (0-4095)
// Measure sound level
while (millis() - startMillis < sampleWindow) {
int sample = analogRead(SOUND_SENSOR_PIN);
if (sample < 4096) { // Ensure value is within ADC range
if (sample > signalMax) signalMax = sample;
if (sample < signalMin) signalMin = sample;
}
}
unsigned int peakToPeak = signalMax - signalMin;
double voltage = (peakToPeak * 3.3) / 4095.0; // Convert ADC value to voltage
double decibels = 20 * log10(voltage / 0.00631); // Approximate dB calculation
// Update LCD
lcd.setCursor(0, 0);
lcd.print("dB: ");
lcd.print((int)decibels); // Display decibels as an integer
lcd.print(" "); // Clear trailing characters
// Change backlight based on decibel levels
if (decibels < 0) {
lcd.setRGB(0, 0, 255); // Blue (Quiet)
} else if (decibels < 10) {
lcd.setRGB(0, 255, 0); // Green (Moderate)
} else if (decibels < 16) {
lcd.setRGB(255, 105, 180); // Pink (Loud)
} else if (decibels < 25) {
lcd.setRGB(128, 0, 128); // Purple (Very Loud)
} else {
lcd.setRGB(255, 0, 0); // Red (Extremely Loud)
}
// Optional: Print to Serial Monitor
Serial.print("dB: ");
Serial.println(decibels);
delay(100); // Short delay for stability
}
THERMOCHROMATIC INK¶
For my third sample, I created a embroidery with conductive thread and coated it in thermochromatic ink.
Thermochromatic ink is ink that is that reacts to different temperatures turning the ink transparent or into another color. there are various types that have different temperatures that they react at.
I was using an ink that goes from red to transparent, however i ended up mixing it with a white base paint so that it would transform from a pink to a white when heated.
The ink we used, has a high activation temperature, meaning that it takes more than body heat to really make it react.
this is why we used embroidery with conductive thread so that we could use electricity to make the ink react.
To do this safely, we created a heating circuit to make sure that we could properly control the electricy flow into the the embroidery.
here is a photo of the circuit.
Using the InkStich Extension for Inkscape I converted my logo into an embroidery file.
One issue I had was that I mistakenly used a fill function as inkscape was not treating my logo as a single line vector.
This caused my embroidery to be too densly packed with conductive thread, making the circut not complete / infinite.
With no clear start and end point the current takes the path of least resistance.
Even with the above problems I was able to get a pretty good effect with the thermocromatic ink
FUTURE¶
A quick sketch showing how I might iterate both electronic wearables into a garmet.
Left side: LED epaulette controlled by joystick integrated into breast pocket
Right side: decible counter LCD with electronics integrated into breast pocket