With Halloween coming up, we casually asked my 2.5 year old son what costume he wanted to wear this year. He responded with “a stoplight.” At first I thought he was being silly but then I realized it could actually be a pretty cool costume. It could also be a cool little electronics project that I could tackle.
The scope of the project is basically to produce a black T-shirt modded to look and operate as an interactive stop light for Halloween night.
Design requirements include functionality, ruggedness and most importantly, safety. Functionality is described above. Ruggedness is important because it often rains on Halloween. Also, anything in that path of a toddler needs to withstand a beating. Safety is obvious. Reusability is not a priority. Kids grow so fast that this shirt will be unlikely to fit for much more than a few months. Most likely it will only be worn for one night, maybe two if he really likes it. Ideally, the core parts can be salvageable to be used for future projects.
Schematic Design
First order of business was to select the microprocessor. I have used the Arduino platform in the past, so I felt comfortable moving forward with that. Computing capacity isn’t really an issue for this project, it’s not too complicated. But since this is going to be a “wearable” project, I decided to go with the Adafruit FLORA which is specifically meant to be wearable. It is suited for conductive thread.
To sense movement, there are a few accelerators with out-of-the-box Arduino libraries. I chose the Adafruit LSM303DLHC, mostly because I was already placing an order with Adafruit, so it made it easy.
Finally, I needed controllable LEDs. There are many ways to do this. I probably picked the most "overkill" way: NeoPixels. Each NeoPixel has a brain on-board and can be programmed in any fashion, independently of any other NeoPixel.
After choosing those components, I also had to estimate the total the power draw to know what size battery to buy. This was my calc:
Item
|
Quantity
|
Draw (mA)
|
Total
|
Flora |
1 |
30 |
30 |
Accelerometer |
1 |
20 |
20 |
NeoPixels |
6 |
60 | 360 |
2400mAh is a standard LiPo battery size. So if you divide 2400mAh by 410mA you get about 5 hours of runtime with all 6 lights on at a time. It will be less than that with wire resistance taken into account. But it should be more than enough to make it through the night. 2400mAh LiPo battery it is.
Other, small items to buy/order would be
- Conductive Thread
- JST 2 Pin on/off switch
- Alligator Clips
- LiPo Charger
- Black long sleeve shirt
- Black beanie
- Felt (Red, Yellow, Green)
- Sewing hoop
I’m literally starting from scratch for this. But many of these parts will likely be reused.
Detailed Design
In terms of wiring everything up, the accelerometer occupies the I2C connection pins of the FLORA board, plus ground and 3.3V for power. Additional sensors could have been be daisy chained, but that was not necessary in this case.
The NeoPixels are connected to the D9 and D10 pins for PWM control, plus ground and VBatt for power. The NeoPixels all daisy chained.
The idea is to have the battery pack in a pants pocket, running to the FLORA which is attached to the shirt, tucked under the top circle of felt (Red). The accelerometer is also attached to the shirt, right next to the FLORA. They are electrically connected using the conductive thread. The conductive thread is also used to feed all the daisy chained NeoPixels. There are 6 Neopixels total, so each circle has 2 lights side by side.
The "backing" is black felt which insulates the shirt wearer from the conductive wire. Then the colored felt circles go on top of that. The felt covers up the mess of conductive wire.
Arduino Program
Accelerometer Library:
https://github.com/adafruit/Adafruit_LSM303DLHC
NeoPixel Library:
https://github.com/adafruit/Adafruit_NeoPixel
Adafruit Common Sensor Library:
https://github.com/adafruit/Adafruit_Sensor
The hardest part is the accelerometer. Making sure that it registers “moving” and registers “stop.” Even if the accelerometer is at a dead stop, it’s output fluctuates. So there needs to be a buffer.
The device also has a magnetometer built in to track magnetic north, but that's not needed for this application. In fact, the X and Y coordinates are not really needed either. Its basically just the Z coordinates, forward movement and backward movement. It looks like the Z axis reads as nominally 10 at rest.
The NeoPixels are pretty straightforward. I’m just going to be lighting them up in chunks of 2. The chunks will never be on at the same time as the each other. And they will always be the same color. The NeoPixels are actually way overqualified for the job I’m assigning them. But they are pretty affordable and could potentially be used on future projects.
Regarding color and brightness, I used max brightness and the full RGB color code (255,0,0 for example for red).
Here is a sample Arduino program which just runs through Red, Green and Yellow using the NeoPixels.
Sample Code
#include
#define PIN 6
// Parameter 1 = number of pixels in strip
// Parameter 2 = pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(21, PIN, NEO_GRB + NEO_KHZ800);
void setup() {
strip.begin();
strip.show(); // Initialize all pixels to 'off'
}
void loop () {
RedOn()
//check for movement, loop until movement found,
GreenOn()
//check for stop, loop until stop found
YellowOn()
Delay()
}
void RedOn {
//set pixel numbers 1-7 to red
strip.setPixelColor(1,255,0,0)
strip.setPixelColor(2,255,0,0)
strip.setPixelColor(3,255,0,0)
strip.setPixelColor(4,255,0,0)
strip.setPixelColor(5,255,0,0)
strip.setPixelColor(6,255,0,0)
strip.setPixelColor(7,255,0,0)
//turn everything off
//push to LEDs
strip.show()
}
void YellowOn {
//set pixel number 8-14 to yellow
strip.setPixelColor(2,255,255,0)
//turn everything off
//push to LEDs
strip.show()
}
void GreenOn {
//set pixel number 15-21 to green
strip.setPixelColor(3,0,255,0)
//turn everything off
//push to LEDs
strip.show()
}
//push to LEDs
strip.show()
Lessons learned
Sewing with conductive thread is a b*tch. The most difficult part is tying off each end. I ended up using clear nail polish to help keep the ends in place. It’s really time consuming to sew it all together. And programming in earnest really can’t start until you have the physical hardware installed. Note: as you handle it, tiny slivers of the conductive thread get stuck in your skin and can end up bothering you for days. Maximize continuous thread runs as much as possible. Or said another way, minimize tie offs. Keep a good posture while sewing. It gets so meticulous that I found myself slouching and squinting while I sewed. There is lots and lots of wasted thread. Sometimes you can re-use a thread scrap on a short run somewhere else. Constantly tighten the thread. That tightness ensures a strong connection at the pin. Minimize threads jumping over threads. That was the downfall of the circle vision. There was a ton of thread overlap. It got too crazy.
The accelerometer is difficult to work with. It get's "stuck" sometimes and the best way to fix the problem is restarting the program. It would be good to have a physical reset button readily available on the shirt, able to be pressed while out and about.
Minimizing number of LEDs was really helpful to the project. It reduced the load on the battery, it made troubleshooting way easier and the greatest part was that it made the shirt much more reliable. Less places to go wrong. Less potential trouble spots. After simplifying it, I’m confident in the shirt holding up under crazy toddler conditions.