Introduction: Shimmering Chameleon (smart)Skirt ~
I love to sew and I'm on the LED bandwagon, oh, and it's fashion show season. This would be a unique Prom Outfit, for sure! I created this skirt using neopixels, a Flora, a color sensor and an accelerometer. The color sensor takes a picture of whatever you put in front of it and translates that through the attached neopixels! I also attached an accelerometer so that when you move, the neopixels sparkle that color. Read on to see how I made it!
Step 1: The Code
#include <Wire.h>
#include <Adafruit_TCS34725.h>
#include <Adafruit_LSM303.h>
#include <Adafruit_NeoPixel.h>
// Parameter 1 = number of pixels in strip
// Parameter 2 = pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
// NEO_RGB Pixels are wired for RGB bitstream
// NEO_GRB Pixels are wired for GRB bitstream
// NEO_KHZ400 400 KHz bitstream (e.g. FLORA pixels)
// NEO_KHZ800 800 KHz bitstream (e.g. High Density LED strip)
#define NUM_PIXELS 4
Adafruit_NeoPixel strip =
Adafruit_NeoPixel(NUM_PIXELS, 6, NEO_GRB + NEO_KHZ800);
Adafruit_TCS34725 color_sensor =
Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_50MS, TCS34725_GAIN_4X);
Adafruit_LSM303 accel;
#define STILL_LIGHT // define if light is to be on when no movement.
// Otherwise dark
// our RGB -> eye-recognized gamma color
byte gammatable[256];
int g_red, g_green, g_blue; // global colors read by color sensor
int j;
// mess with this number to adjust TWINklitude :)
// lower number = more sensitive
#define MOVE_THRESHOLD 45
#define FADE_RATE 5
int led = 7;
double newVector;
void flash(int times)
{
for (int i = 0; i < times; i++)
{
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
delay(150); // wait for a second
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
delay(150);
}
}
float r, g, b;
double storedVector;
void setup()
{
pinMode(led, OUTPUT);
// Try to initialise and warn if we couldn't detect the chip
if (!accel.begin())
{
Serial.println("Oops ... unable to initialize the LSM303. Check your wiring!");
while (1)
{
flash(4);
delay(1000);
};
}
strip.begin();
strip.show(); // Initialize all pixels to 'off'
if (!color_sensor.begin())
{
Serial.println("No TCS34725 found ... check your connections");
while (1)
{
flash(3);
delay(1000);
};
}
// thanks PhilB for this gamma table!
// it helps convert RGB colors to what humans see
for (int i = 0; i < 256; i++) {
float x = i;
x /= 255;
x = pow(x, 2.5);
x *= 255;
gammatable[i] = x;
}
//this sequence flashes the first pixel three times
// as a countdown to the color reading.
for (int i = 0; i < 3; i++)
{
//white, but dimmer-- 255 for all three values makes it blinding!
strip.setPixelColor(0, strip.Color(188, 188, 188));
strip.show();
delay(1000);
strip.setPixelColor(0, strip.Color(0, 0, 0));
strip.show();
delay(500);
}
uint16_t clear, red, green, blue;
color_sensor.setInterrupt(false); // turn on LED
delay(60); // takes 50ms to read
color_sensor.getRawData(&red, &green, &blue, &clear);
color_sensor.setInterrupt(true); // turn off LED
// Figure out some basic hex code for visualization
uint32_t sum = red;
sum += green;
sum += blue;
sum = clear;
r = red; r /= sum;
g = green; g /= sum;
b = blue; b /= sum;
r *= 256; g *= 256; b *= 256;
g_red = gammatable[(int)r];
g_green = gammatable[(int)g];
g_blue = gammatable[(int)b];
// Get the magnitude (length) of the 3 axis vector
// http://en.wikipedia.org/wiki/Euclidean_vector#Length
accel.read();
storedVector = accel.accelData.x*accel.accelData.x;
storedVector += accel.accelData.y*accel.accelData.y;
storedVector += accel.accelData.z*accel.accelData.z;
storedVector = sqrt(storedVector);
}
void loop()
{
// get new data
accel.read();
double newVector = accel.accelData.x*accel.accelData.x;
newVector += accel.accelData.y*accel.accelData.y;
newVector += accel.accelData.z*accel.accelData.z;
newVector = sqrt(newVector);
// are we moving
if (abs(newVector - storedVector) > MOVE_THRESHOLD)
{
colorWipe(strip.Color(0, 0, 0), 0);
flashRandom(10, 25); // first number is 'wait' delay,
// shorter num == shorter twinkle
// second number is how many neopixels to
// simultaneously light up
}
#ifdef STILL_LIGHT
else
{
colorWipe(strip.Color(gammatable[(int)r],
gammatable[(int)g], gammatable[(int)b]), 0);
storedVector = newVector;
}
#endif
}
void flashRandom(int wait, uint8_t howmany)
{
for (uint16_t i = 0; i < howmany; i++)
{
for (int simul_pixels = 0; simul_pixels < 8; simul_pixels++)
{
// get a random pixel from the list
j = random(strip.numPixels());
strip.setPixelColor(j, strip.Color(g_red, g_green, g_blue));
}
strip.show();
delay(wait);
colorWipe(strip.Color(0, 0, 0), 0);
// now we will 'fade' it in FADE_RATE steps
for (int x = 0; x < FADE_RATE; x++)
{
int r = g_red * (x + 1); r /= FADE_RATE;
int g = g_green * (x + 1); g /= FADE_RATE;
int b = g_blue * (x + 1); b /= FADE_RATE;
strip.setPixelColor(j, strip.Color(r, g, b));
strip.show();
delay(wait);
}
// & fade out
for (int x = FADE_RATE; x >= 0; x--)
{
int r = g_red * x; r /= FADE_RATE;
int g = g_green * x; g /= FADE_RATE;
int b = g_blue * x; b /= FADE_RATE;
strip.setPixelColor(j, strip.Color(r, g, b));
strip.show();
delay(wait);
}
}
#ifdef STILL_LIGHT
colorWipe(strip.Color(gammatable[(int)r], gammatable[(int)g], gammatable[(int)b]), 0);
#endif
}
// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
for (uint16_t i = 0; i < strip.numPixels(); i++) {
strip.setPixelColor(i, c);
strip.show();
delay(wait);
}
}
Step 2: The Test
First I needed to conduct some tests for what I wanted to accomplish, using the materials I had. I had to test the resistance of the conductive thread for the distances I was going.
I made a mock-up on the sewing machine, creating 3 rows of conductive thread, doubled up. Stainless steel is very strong, but it has a lot of resistance and can shift and become loose around pin-outs. I wanted to see the max distance the info could travel along this set-up.
I set everything up with alligator clips to test the thread and make sure the code still worked as it was supposed to.
Step 3: Supplies and Fashioning
First I made a skirt out of a stretchy spandex fabric that was futuristic silver, and just used the wrong side. I had some leftover gold stretchy silk from when I hemmed a couture wedding dress and got to keep the cutoff. This allows me to have the skirt fit a range of sizes, BUT also means that I have to do a lot of hand-sewing. I chose to put the Party of the skirt at the bottom, which has a large enough circumference to be unaffected by the stretch limitations.
Most of the electronics are from Adafruit. The color-tip glove I made from a pair of beautiful gloves from the 40's. I love mixing old with new!
I marked with disappearing ink where I wanted all the neopixels to go. I then sewed them on with a small amount of regular and conductive thread. The real connections would come later.
Step 4: The Brain
This combo is the brain of the system. It is a Flora, attached to the Color Sensor attached to the Accelerometer/compass.
I sewed everything with the 2-ply conductive thread, making solid connections with plenty of passes and spacing lines sufficiently apart.
For the pin-out connections of data, power and ground that would be traveling down the length of the skirt, I used beefier, insulated wire. You could just use the 3-ply conductive thread, but you'd need to have at least 6 wires bundled together for each of the three lines.
I then sewed the patch onto the skirt, feeding the battery wires though a small opening and into a pocket I created for the LiPo. The battery is 1200mAh, 3.7V.
Step 5: My Work Is Cut Out for Me
The first pic is the first neopixel of the 8 neopixel train. The rest would all be connected with 3-ply stainless steel conductive thread, strung with semi-precious stones and beads. These would all add a nice weight and rigidity, plus look more intentional than just dotted lines of wire connecting the neopixels.
The trick was finding a needle eye big enough to accept the steel thread but small enough to fit though the stones/beads. There were a lot of beads that didn't make the cut. : D
Step 6: The Underneath
I wanted to cover all the exposed thread so as to minimize any chance of shorts. I used iron-on interfacing, clipping to allow curves, and ironed on with a single layer of cheesecloth between the skirt and iron. The initial wires I just wove in between the serged seam.
Step 7: In Action!
I have entered this into the Code Creations Contest and would love a vote if you think I deserve one!
: D
~ Cynthia





