Ring of Fire is a tree ornament I built this year. A big, high-powered, custom-animated tree ornament.
First, there was the idea and a parts list.
Then I wrote a simulator to create animations against.
When that was done, I built the ring and started on the firmware
And then I did a whole bunch of wiring to hook up the microcontroller to the LEDs on the ring, finished the code, and put it up in the tree in my front yard.
Finally, I took a low-quality video of it.
The oldest of my displays. The "landing lights" are blue lights in canning jars dyed blue. All the santas and the reindeer are made of plywood. Some of the lights on the mid and upper santa are burnt out, but I'm not sure I'm going to get around to fixing it before next year.
Animated with an 8-channel custom Motorola HC11-based microcontroller system driving solid-state relays, all coded in assembler
Here's a video of the completed project. The video is from my Canon G3, so the quality isn't very good. For sake of comparison, the blue and red globes in the video are 50 watts each, while each LED is only 350mW. The LEDs a bit brighter than they appear because the video is about 20 degrees off-axis.
My second animated display. This one has 16 channels and runs using a Motorola 68HC11 microcontroller. In the background you can see the house outline lights, which are a four-color dimming system also based on a 68HC11
The last few days have been fairly hectic. I wanted to get "Ring of Fire" into a demo-able state (to take into work on Friday), so that it could go up today.
First up was building the project board. As I mentioned before, the LEDs pull 70mA, so I need a separate transistor to drive them, as the AVR can't handle the current requirements. The switch uses a 2n3904 NPN transistor, a 10K base resistor, and a 100K resistor between the emitter and base. And finally, an 42 ohm current-limiting resistor in line with the LED, in between the collector and 5V. That's 16 transitors and 48 resistors, and after about 5 minutes, it was clear that that wasn't going to fit on the board. I decided to put the current-limiting resistor next to the LEDs, and could barely fit the other components on the board. Here's a picture of the board:
Yep, that's a whole bunch of wires.
Next up was finishing the LED wiring. One of my bike wheels is built with 16 spokes, so I used it to mark the location the LEDs. Then I spent about 4 hours mounting the LEDs onto the ring. Here's a picture of a mounted LED:
The black wire is the 5V bus, and continues all the way around the ring. The yellow part is a 42 ohm resistor attached to the ground side of the LED, which is then attached to a red wire that runs all the way back to the controller. The LED is then attached to the ring with hot glue. Here's what the completed ring looks like.
That completed, I turned back to the software.
Problems that I hit along the way:
Originally, I was going to put ping-pong balls on the LEDs to diffuse the light, but it turned out that the LEDs have a fairly wide viewing angle, so the diffuser wasn't needed.
So, the project is done, up and the tree looks pretty nice.
The Windows team has launched Stay at Home Server, and they've produced a short book that introduces it.
You should read it.
After firming up the animations that I wanted to do, I got two things accomplished in the last few days.
First, I build the "ring" part. I had bought a 5' piece of pvc electrical conduit to use as a form, and my plan was to bend it into a circle by heating it with a heat gun.
Initial results were disappointing. The circle that I got was about as circular as the ones I drew when I was in kindergarten, so I decided I needed a form.
And there, sitting in a box because of my laziness at not putting them away, was a set of spare wheels for my bicycle. A little experimentation showed me three things:
A quick trip to Lowes and another 30 minutes with the heat gun, and I had a nice hoop (size 700c) completed.
After digging out my development board (I use the Atmel STK500) and buying a copy of the CodeWarrior AVR C compiler, I was ready to get started. Well, not quite - I had to set up my work area since we're getting ready to gut and redo our office. My main tools are:
I don't really need the power supply as I'm using a wall wart to power the development board, but it looks nice under the scope. The multimeter is useful to look at LED currents, and because I'm using PWM to control the brightness of the LEDs, the scope is invaluable for debugging. If you don't want a full-sized scope, there are some decent PC-based solutions, but keep in mind that the precision electronics required for 'scopes are never cheap. I like having the real buttons and knobs rather than having to use a UI on the laptop to do things, though I would really like a TDS1000B.
I've often advocated that developers should learn multiple languages because knowing languages effects how you approach problems. If you are fluent in Perl, you're much more likely to know when to use a nice regex in C#.
Similarly, it's good for your skills to spend some time working on a seriously constrained machine like a microcontroller. The 861 I'm using has a whopping 512 *bytes* of memory, which sounds pretty tiny until you note that the 261 only has 128, and some of the 8-pin versions only have 64 bytes. Trying to structure your algorithms and code to use that amount of memory and the 8K of flash for the program memory will stretch your mind in ways that writing C# code won't.
I'm undecided on the benefits of writing in assembler. I can be a learning experience, but I'm not sure if the pain of remembering how indexed address mode works transfers over to more rational languages.
My first order of business was to get the chip in the board, make sure I could burn it, and get a skeleton program running. Getting the chip on the board was trivial, but I had real problems getting it to program (which is done with a PC program that sends the code over a serial cable to the board). After a lot of trial and error - mostly error - a kind soul on avrfreaks.net pointed out that the connections on the STK500 were wrong for my chip, and things started working correctly then.
Codewarrior is a nice product. Microcontrollers require a lot of configuration up front - you need to set how you are using each of the pins, what interrupts you want, and 35 other things. You do this by writing code that stuffs particular values in specific registers on the chips. Something like:
Where you found that by careful reading of the 227 page user's guide for the chip. It's pretty tedious, but CodeWarrior provides a "get started wizard" where you specify what chip you're using and then go through a dialog and choose what options you want and then it generates all the initialization code that is needed for your chip. It's a huge timesaver.
After tracking down one problem that was keeping my interrupts from firing (traced to missing a bit in one of the interrupt configuration registers), my main loop woke up and started operating. I did a bit more debugging and then ported one of my animations over from C# to C.
It looked okay on the scope (minus a few glitches), but it seemed slow. Plugging in the leds on the STK500 to 8 of the output bits I'm using showed that a) the animation was working, but very slowly and ii) the LEDs were flickering like nobody's business.
As I suspectected, the 861 running at 8 MHz doesn't have enough horsepower to handle 256 levels of dimming. I'm not getting the 100 Hz that I need to keep the leds from flickering, and there's not enough free time after the interrupts to do the animation at any reasonable speed.
I'll spend a little time seeing if I can't speed up the interrupt routine, but the real fix is going to be to reduce the number of dimming levels down to 16, which should give me enough time for everything to run smoothly.
Then, it will be time to start attaching components to the ring