Shimmering Chameleon (smart)Skirt ~
by cdstudioNH in Craft > Fashion
3774 Views, 36 Favorites, 0 Comments
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!
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); } }
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.
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.
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.
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
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.
In Action!
I have entered this into the Code Creations Contest and would love a vote if you think I deserve one!
: D
~ Cynthia