As I teased a little bit in another post, here's my latest project: GrownUp LA Gears!
For those of us who were growing up in the mid 90s, LA Gears were the best thing you could strap to your feet. They had LEDs in the heal that would flash when you walked. I wasn't lucky enough to have a pair when I was a kid, so maybe this whole thing is just me living out a lost childhood fantasy.....
Much like the WS2811 driver library this project is being used to demo, I also snagged the idea from AdaFruit: https://learn.adafruit.com/firewalker-led-sneakers/overview
I recommend reading through the post, since they do a better job of explaining things than I will here.
While their design is good, there are some improvements to be made. Mainly, there isn't an MSP430 in it.
Hardware
I didn't want to strap a launchpad to my shoe, so I deadbuged a 430 with the minimal requirements to run it. A small 3.3V LDO, pins broken out for input and programming, and a pullup on RST. I don't have pictures of the final build, but you get the idea. Once all the joints were made, they were encased in hot glue, the best strain-reliever and sealer known to man.
For the shoe itself, the LEDs where mounted around the perimeter and glued in with RTV silicon adhesive (https://learn.adafruit.com/firewalker-led-sneakers/attach-neopixel-led-strip). I ended up drilling some holes in the battery case and sewing it to the side of the shoes. The Chucks worked well because they have handy vent holes on the sides to run wires through (they are also classy for every occasion).
AdaFruit used a custom sensor made of velostat, a material which changes resistance when force is applied. If you connect the sensor between ground and an analog input, then turn on an internal pullup for that IO, you can essentially make a simple voltage divider. The problem here was that the velostat sensor I made went from 1kohm with no pressure, to 300 with pressure. This in series with the internal 40k of the MSP was just too small a range to detect well. I ended up using a force sensor from SparkFun that goes from 1Mohm down to 1kohm. It saturate at 10kg, but it works well. I may revisit the velostat for cost reasons, but I'm happy with this guy: https://www.sparkfun.com/products/9376
I ended up just gaff taping it down inside the heal.
With LEDs on, and sensor in place, it just has to be wired up. Here's a quick block diagram and image of what it all looks like mounted. You can see that I left TEST and RST on there for programming.
Software
The main push behind these was that I had the modifications to Rickta59's WS2811 driver done, and needed a demo platform ( http://forum.43oh.com/topic/2882-energia-library-ws2811driver-led-controller-class/ ).
Since that lib does the hard part, the rest of the Energia project is pretty easy, and hopefully well documented in line.
#include <WS2811Driver.h>
#define N_LEDS 44 // TOTAL number of LEDs in strip
#define SHOE_LEN_LEDS 23 // Number of LEDs down ONE SIDE of shoe
#define SHOE_LED_BACK 8 // Index of REAR-MOST LED on shoe
#define STEP_PIN 2 // Analog input for footstep
#define LED_PIN 3 // NeoPixel strip is connected here
#define MAXSTEPS 3 // Process (up to) this many concurrent steps
#define STEP_TRIGGER 30
#define STEP_HYSTERESIS 200
WS2811Driver strip = WS2811Driver(N_LEDS, LED_PIN, NEO_GRB);
//Globals, becouse lazy
boolean stepping = true; // If set, step was triggered, waiting to release
uint8_t dup[SHOE_LEN_LEDS]; // Inside/outside copy indexes
uint16_t Filtered;
uint8_t step_order = 1;
void setup()
{
//Enable internal pullup for analog sensor
pinMode(STEP_PIN, INPUT_PULLUP);
//Setup the array to index the two sides of the shoe
memset(dup, 255, sizeof(dup));
int8_t a, b;
for(a=1 , b=SHOE_LED_BACK-1 ; b>=0 ;) dup[a++] = b--;
for(a=SHOE_LEN_LEDS-2, b=SHOE_LED_BACK+SHOE_LEN_LEDS; b<N_LEDS;) dup[a--] = b++;
//Start the LEDStrip
strip.begin();
//Max desired drightness
strip.setBrightness(255);
}
void loop()
{
//Wait until a step is detected
while (stepping == false)
{
pinMode(STEP_PIN, INPUT_PULLUP);
Filtered = analogRead(STEP_PIN);
if(Filtered < STEP_TRIGGER) stepping = true;
}
//A step has been detected, so play the desired pattern
//Pulse a different color each step and then fade out
switch(step_order){
case 1:
colorWipe(strip.Color(0, 0, 255), 5); // Blue
step_order = 2;
break;
case 2:
colorWipe(strip.Color(255, 0, 0), 5); // Red
step_order = 3;
break;
case 3:
colorWipe(strip.Color(0, 255, 0), 5); // Green
step_order = 1;
break;
}
for(uint16_t i=0; i<128; i++)
{
strip.setBrightness(255-(2*i));
strip.show();
}
colorWipe(strip.Color(0, 0, 0), 1); // blank
strip.setBrightness(255); //Restore brightness for next pass
//Simple back to front color wipe
/*
colorWipe(strip.Color(128, 0, 10), 5); // Redish
colorWipe(strip.Color(255, 255, 255), 5); // White
colorWipe(strip.Color(0, 0, 0), 5); // blank
*/
//Holdoff until the foot has been lifted
while (stepping == true)
{
pinMode(STEP_PIN, INPUT_PULLUP);
Filtered = analogRead(STEP_PIN);
if(Filtered > STEP_HYSTERESIS) stepping = false;
}
}
// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
uint8_t j;
for(uint16_t i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i+SHOE_LED_BACK, c);
// Pixels along inside are funny...
j = dup[i];
if(j < 255) strip.setPixelColor(j, c);
strip.show();
delay(wait);
}
}
Final Product
And here it is!
I wore then to a friend of mines baby gender reveal party, and the three AAAs lasted all night. No idea what the actual battery life is yet, but I'll probably do a V2 with a LiPo system.
The rainbow pattern is actually in the sample code I put with the library, I was just testing it here.
The videos really show it off. Just ignore my messy living room. These are both out of the code I posted above, just comment out the different sections.