Long post ahead!
The aim of the project was simply to add some sub-dermal (sub-furmal?) LEDs to jazz up my fursuit a bit. My suit is only a partial (this means it's not a full body suit), so I was limited to the arms and the head. I quickly decided against modifying the head because I'd wreck it, however I struck on the idea of wearing a headcollar/halter and adding LEDs to that. This gave me three LED zones: two arms, and the halter. In the interests of future expandability I decided that my circuit design should support up to 8 zones.
As a wearable project it would have to be battery powered. I wanted a target battery life of at least 5 hours (the amount of time I spent continuously on the dance floor in my fursuit at last year's Eurofurence!)
I decided that each LED would be individually addressable, rather than using strips or panels of LEDs that were all the same colour. This makes it vastly more complicated, but I thought that using LED strips would be too simple ;)
Finally, I wanted a target framerate of at least 40fps to ensure smooth animation.
In order to produce a full colour display I needed RGB LEDs. I settled on buying surface mount 5mm PLCC-6 RGB LEDs. These were somewhere in the region of £15 from eBay (via Hong Kong, naturally).
These LEDs gave me a nice low profile - important because I didn't want lumpy fur! I bought SMT rather than through-hole LEDs because I would have had to bend the legs outwards, and they have a tendency to snap off if you do that. The other option would have been to use "straw hat" style leaded LEDs, but these seem to give a nice round spot of colour whereas the straw hat ones give more of a point light.
Driving the LEDs
There are two principle ways to drive LEDs: directly, or in a matrix.
Direct drive is the simplest - you just connect your LED directly to your I/O pin, and you're done. Giving the LED its own dedicated I/O pin has the advantage that you can get maximum brightness from the LED, and of course it's simple. The down side is that it takes a lot of I/O pins, and with 3 channels per LED (red, green blue), it wasn't going to be practical.
Driving LEDs in a matrix is a little more complicated, but it allows you to save on I/O pins. Each I/O pin is split over time between a number of LEDs, and it lights them in sequence. Because of this time-sharing the LED will never reach maximum brightness, but you save on a lot of wiring and I/O pins. This was the obvious choice for the suit, as I wanted to keep circuitry and wiring to a minimum. It's only really for looking at from a fairly close range at night, so I'm not too bothered about the loss of brightness - it's a worthwhile tradeoff. It also has the incidental advantage of extending battery life.
Shift registers are often used to drive LED matrices. They are very simple to operate - you pump in data serially, and it comes out in parallel on the pins. However after careful consideration I determined that it would actually be cheaper and better to use PICs instead of shift registers. This seems to be a recurring theme whenever I try to make any electronics - I design the circuit, and then realise it's cheaper and better to just do it all with a PIC.
Using a PIC instead of a shift register means I don't need a 'blanking' signal. If you pump data through a shift register, then when it comes time to shift in the next frame your data will momentarily appear on all the LEDs down the line. This causes a faint ghosting which I wanted to avoid.
After going through several design iterations, I decided on using a 20x6 matrix of LEDs. This gives me 120 channels, enough for 40 RGB LEDs, which I decided was sufficient for each zone. They can be driven by a single 40 pin PIC18. This gives me a maximum duty cycle of 1 in 6, or a maximum LED brightness of 1/6th their possible brightness, and I decided that this was about the sweet-spot for the number-of-LEDs vs LED-brightness tradeoff. It fit nicely on the PIC, 20 I/O lines for the LEDs, 6 I/O lines for the column drivers, and a few for the data bus plus some spares in case I want to add anything in the future.
Having decided how to drive the LEDs, I now needed to decide how to create the patterns/pictures they would be displaying. I settled on a PIC24 (16-bit PIC). An 8-bit PIC probably would have sufficed, however I haven't used 16-bit PICs before and I wanted to give it a go.
The pattern generation is quite simple - an interrupt fires at 40Hz, triggering my software to draw a frame and output it across the data bus. There are a number of simple patterns that it picks at random. I had planned to synchronize it to music by tapping out a few beats on the controller and having it sync to that frequency, but there wasn't time for this. I have also learnt from the Electric Giraffe project that music synchronization isn't really necessary - the human brain is so good at finding patterns that it will tell you it's synchronized even when it's just chance.
The PIC24 was a bit more of a departure from the 8-bit PICs than I expected, so it took me a little longer than I'd hoped to get it up and running. One thing that held me up a bit was that you don't seem to be able to do poor-man's interrupts by polling the interrupt flag like you can on the PIC18.
In order to have it display a different sequence each time, I needed to seed the random number generator. Normally I store a number in the FLASH EEPROM and increment it each time the chip is booted, giving me a fresh random seed each time, but the PIC24 I'd chosen didn't have any FLASH. The solution I came up with is a bit ugly, but it works. I take an analogue to digital reading from an open-circuit pin, essentially sampling whatever electrical noise is in the aether and using that to seed my random number generator. Incidentally, the random number generator in the PIC C standard library is atrocious if you just look at the lower order bits - they just count up in sequence. This means that you can't use the mod (%) operator like you might be used to - "rand() % 5", for example. What you need to do instead is to normalize it into the range you want - "(unsigned long)rand() * 5 / (RAND_MAX + 1)". It's slower of course, but it works.
The next thing to do was to get the data from the pattern generator to the LED drivers. A serial bus was was the obvious choice to keep the wiring to a minimum, and the PIC has a hardware UART for RS-232 support, so that was the perfect choice.
LED controllers like this usually use a bus topology where data is shifted through each controller until it gets to the destination, however I decided on a star topology to reduce wiring. This also allows me to send more data in less time, because I can send it in parallel to each LED driver. There was one disadvantage though - the PIC only has a singled UART, and the pattern generator would need one per zone. This meant I had to bit-bang the protocol on the transmit side, rather than using the hardware. This turned out to be trickier than I'd hoped, mostly due to a lack of tools. It looked ok in the code, it looked ok on the scope, but I kept getting framing errors. After many hours of fiddling around with it I finally got it to work, although it was one of those things where you put some debug in, it starts working, you take the debug out, and it still works. Who knows. A signal analyser would have been really helpful, or at least an oscilloscope with an accurate timebase.
I had originally intended to use the PICs' internal oscillators as the timing source to reduce the component count, but I decided that they might be too inaccurate and so I used external ceramic resonators.
I set the data rate at 115kbps. I could probably push it much higher, maybe up to 1Mbps, but there's no need. I put a small filter on the receiving end (a 750 ohm resistor to +ve and a 220 ohm resistor in series with a 1nF capacitor to ground) to keep the signal clean and make sure there weren't any problems with reflections over the length of the transmission line.
Soldering a large number of surface mount LEDs freehand (i.e. without a PCB) isn't an easy prospect, so I put some thought into how I was going to do it.
Step one was to produce a template for the layout. I wrapped my arm in cling-film and then wrapped that in packing tape, and used a permanent marker to draw a grid where I wanted the LEDs to be placed. I then cut the tape off and laid it out flat, and used it as a template to copy the grid onto paper. I taped the paper to the grid, and then placed masking tape sticky-side-up along the grid lines. This was to hold the LEDs in place while I soldered them. It's important to use masking tape not sellotape, because sellotape will melt!
Each LED required four connections: A common anode, and a cathode for red green and blue. The cathodes would be commoned between LEDs to form the matrix. The solder pads on the LEDs are very small, and connecting two wires to a single pad is extremely difficult, so I devised a novel solution to this: Rather than make 'in' and 'out' connections with a series of short jumpers, I stripped all the insulation off lengths of wire and tacked it to the LED solder pads, using heatshrink in between. This meant that I only had to cut heashrink to the correct length, not jumper wires, which was much easier because it didn't have to fit together perfectly. If you are butting two wires together then they must fit exactly, but with heatshrink you have a good margin for error around how much wire is exposed at the end. The soldering is extremely easy because you only have to tin the solder pads and then tack the wire down with a blob of solder, rather than worry about the first wire falling off while you are trying to attach the second wire.
Hopefully a diagram will explain this technique a bit better - the top shows the 'obvious' way of wiring the LED. The bottom shows how I did it.
Stripping the wire turned out to be the most difficult part. The wire was so thin that you couldn't use it to tear through its own insulation. The solution I found was to hold one end of the wire in a vice, hold it taught with one hand, and slide a hot scalpel blade along the insulation. I used a candle to heat the blade for a few seconds, and that allowed it to slide through the insulation much more easily than when cold. Even so, it was a delicate operation as the tiniest nick in the wire would break one of the strands.
This shows the first row being constructed. You can see the bare wire with heatshrink on it running vertically and connecting the RGB commons between the LEDs. The anodes go off to the left, to be attached to the circuit.
And here's what it looks like with an entire zone soldered together. Physically they are arranged in an 8x5 matrix, but electrically they are arranged in a 20x6 matrix. The way it's wired isn't immediately obvious: I interleaved the matrix in such a way that the wiring is simplified. All it takes is a simple conversion in software to process this interleaving, and it saves a lot of effort with the wiring.
In this picture you can see the wired up zone, the template and tape used to lay it out, the box of pre-tinned LEDs ready for the next zone, the big soldering iron I use to shrink the heatshrink tubing, the prototype circuits for the chips, the candle I used to heat the scalpel blade, and a nifty soldering fume fan I made a couple of months ago.
The halter was a much easier build. I used RGB 4-pin straw-hat LEDs, 10 per cheek. I originally intended to have them across the noseband and headband as well, but the buckles were in the way. I pushed a scalpel in point-first to create a small slit for each LED, pushed it through from the front, then bent the legs and soldered them on the back. There was no need for heatshrink this time - because the legs were solid, I could just bend them away from each other. When I was done, I glue-gunned a strip of fabric tape as a backing, to protect the LEDs and make sure they did not catch the fur.
As a wearable circuit it would obviously need to be battery powered, so I chose a 7.4V 5500mAh LiPo battery pack. I bought a small switched-mode regulator to reduce it down to the 5V needed for the chips. I chose this over a simple linear regulator because of its increased efficiency. the PIC24 needs a 3V supply, so I used an LM317 adjustable linear regulator for that, as the current draw is extremely small. I used a buffer chip to interface the PIC24 with the PIC18s, to convert the 3V signal to a 5V signal. It probably wasn't strictly required, but I decided I'd be better off using a higher voltage range over the transmission line.
With the electronics completed, I had to actually attach it to the shirt. I convinced my brother to wear the shirt while I put a dab of hot melt glue on the back of each LED and attached them one at a time. After that I sewed and glued down the wires to keep everything neat, and made some little pockets on the underside of the arms to hold the LED driver circuit boards.
I placed the controller circuit in a little box that will go in my pocket, and added a power switch, RJ-45 socket for the data connection, and 6.8mm jack plug for the power connector.
This is what my room looked like while working on all of this...
... it's tidier now.
Congratulations if you've read all that. You probably want to see it in action now... unfortunately you'll have to wait a bit longer. I have taken a video, but I can't get it off the camera yet due to lack of a firewire port. I'll post it when I get back from EF.
Thanks for reading!