Holiday Lights 2008

December 19, 2008 at 1:43 am

Today, I took a break in the snow and finished the installation of the new light display. It’s functional, except for one light that isn’t working.  I’ve been extra busy this year, so while the main displays are up, there aren’t as many additional lights as I would like to have.

Our recent snowstorm has changed the look quite a bit – normally you only get a little light from the streetlight on the left, but now there’s a ton.

On the left, there are 8 strings of multipcolored LEDs in a circle around the light pole. To the right in front of the truck are some other lights. Hiding behind the truck is the first animated display, the “tree of lights”. The big tree (about 40′ tall) has red leds around the trunk, and features to animated displays. At the top is the second animated display, the “ring of fire”, arrayed on the tree is the new display. To the right you can see the original animated display, santa in the sleigh and on the roof. Finally, outlining the house is a red/green/blue/white string, the last animated display.

Tree of Lights

16 channel sequenced controller, about 1500 lights total. From base of tree to top is about 14′.

The controller is 68HC11 based.

 

 

 

 

 

 

 

 

 

 

 

 

 

Ring of Fire

Ring of Fire is 16 high-output red LEDs driven by a custom 16 channel controller, supporting 16 dim levels per LED.

The controller is Atmel AVR based.

I wrote a fair bit about it last year.

 

 

 

 

 

 

Santa

The display that started it all. It animates as follows:

  1. Blue lights in foreground strobe towards santa.
  2. Reindeer, sleigh, and santa appear.
  3. Santa leaves sleight and hops up on the roof edge.
  4. Santa goes up to the peak near the chimney.
  5. Santa disappears, and then his hat disappears soon after.

Then the whole things reverses itself.

The display itself is painted plywood, with about 800 lights in total. After 12 years the lights had gotten a bit dim, so this year we replaced all of them. The santa at the top of the roof is usually a it more distinct, but he has a big snow beard this year.

The controller is based on the Motorola 68HC11, running 8 channels.

House Lights

The house lights are 4 individual strands in red, green, blue, and white, with a 4-channel controller that dims between the colors. So, the house changes between colors.

The controller is based on the Motorola 68HC11, with 4 channels, this time dimmable.

Tree Lights

The tree lights are the new display for this year.

These are jumbo lights lit up with C7 (7 watt) bulbs inside of of a colored plastic housing. They really don’t show up that well in the picture because of all the light coming off the snow, but even so, I think I will likely need to upgrade the bulbs in them to something brighter (say, in the 25 watt range). And I think I will go with clear bulbs – having both colored bulbs and colored lenses works well for yellow and orange but the blues and greens are really dark.

The controller can support up to about 100 watts per channel, though I’m not sure my power budget can support it.

The controller is Atmel AVR based (my new platform of choice), and the code is written in C. There are 15 channels, and each of them has 32 dimming levels.

You can find a lot more boring info here.

Holiday light project 2008 in pictures

December 19, 2008 at 1:42 am

A trip through the new project in pictures:

I was late in getting started on the project due to putting finished touches on the office, but I ended up with this wonderful new workbench. Quite the step up from the old door on top of shelf units that I’ve used for the last 35 years or so (really).

Left to right, we have the Tektronix dual-channel 20MHz oscilloscope (thank you eBay), a bench power supply, a perfboard with sockets on it in front of my venerable blue toolbox (also 35+ years old), a outlet strip with a power supply plugged into it, a perfboard, a STK500 microcontroller programmer, a weller soldering staioin, and a fluke voltmeter.

This the project in its first working version. On the far left partially clipped is the power supply. The upper-left part of the prototype board (the white part) has the zero crossing circuit, and the upper-right has a solid-state relay. A brown wire takes the zero-crossing signal to the microcontroller on the development board, and a brown wire takes the signal back to the relay. The Atmel AVR microcontroller that I use comes in a lot of different sizes, so the development board has any different sockets to support the. On the far-right is a white serial line which leads to my laptop – the AVR is programmed over a serial link.

Back to the zero-crossing circuit. To switch AC power, you use a semiconductor device known as a triac. The triac has a weird characteristic – once you turn it on, it stays on until the voltage goes back to zero. That happens 120 times per second, so to implement diming you need to control when you turn on the power for for each half-cycle.

Here’s a picture that should make it easier to understand.

The wavy part is the AC sine wave, and the nice square pulse is the zero-crossing signal, which goes high whenever the AC voltage is low enough. The microcontroller gets interrupted when the zero-crossing signal goes high, and then waits a little time until just after the real zero crossing happens.

If it turned the output right at that point, it would stay on for the whole half-cycle, which would means the light was on full bright. If it never turned it on, it would mean the light was (does anybody know the answer? class?) off. If it turned it off halfway in between, the light would be at half brightness. To implement the 32 levels of brightness means dividing the half-cycle into 32 divisions of each area, corresponding to areas of equal power.

(To be better, I should take into account the power/luminance curve of the incandescent bulb that I’m using and use that to figure out what the delays are. Perhaps the next version).

To do this for multiple channels, you end up with code that does the following:

  1. Check all channels to see which ones should be turned on at the current time.
  2. Figure out when the next time is to check.
  3. Set an interrupt to that time.

That gives us a set of lights stuck at a given dim level. To animate, you need to change that dim level over time. That is handled at two levels.

The interrupt-level code handles what I call a dim transition. At least, that’s what I call it now, since I didn’t have a name for it before. We have a vector of current dim levels, one for each channel, and a vector of increments that are added to the current dim vector during each cycle.

So, if we want to slowly dim up channel 1 while keeping all the others constant, we would set dimIncrement[0] to 1 and set the count to 31. 31 cycles later, channel 1 would be at full brightness.

If we want to do a cross-fade, we set two values in the increment vector.

That all happens underneath the covers – the main program loop doesn’t know about it. The main program loop figures out what will happen next after the current dim transition, and then blocks.

My early controllers were all table-based, with the tables pre-computed. This was because I was writing in assembler. The current system could also use that approach, but with only 2K of program memory, the procedural approach is more compact, though it is considerably harder to debug. I have a C# program I use to create and test the animations, but I need to rewrite it to use DirectX because I need a 120Hz frame rate to match what I the dimming hardware does.

To get back to the zero-crossing circuit, I first built this circuit using a wall wart with a switching power supply. Such power supplies are small and efficient, but put a lot of noise into the transformer side. I wasted a lot of time on this, and ultimately switched back to a conventional wall wart (from an old Sony discman I used to have) with a linear power supply. Problem solved.

Back to pictures:

Here’s the completed controller board.

In the center is the AVR 2313V microcontroller. The U-shape is the solid-state relays that switch the AC for the lights. These are nice little Panasonic AQH2223 relays, which switch 600mA (about 75 watts) (though you can get the in versions that do 150 watts), are tiny, and, most importantly, they’re less than $2 each.

Note that these do not have built-in zero-crossing circuits built in. Most solid-state relays do, but you can’t use those to do dimming.

The top has the one transistor used to generate the zero-crossing circuit, a 7805 voltage regulator to provide +5V to the circuit, and a few passive components.

Careful viewers will notice that the upper-right socket is empty. That’s because it’s only a 15-channel controller, but I used 16-pin sockets.  The blue wire that holds the AC socket wires on is wire-wrap wire that I had lying around – these are hot-glued down later on. The two black wires provide the rectified voltage (about 15V IIRC) from the wall-wart.

The controller board is in a small plastic box designed to hold 4×6 photos, and then that’s inside of a larger box. This lets me keep all of the electrical connections inside of the box. It’s not really required for safety, but if you have a lot of exposed plugs and some water on them, you can get enough leakage from them to trip the GFI on your circuit. So having them all inside is better.

The box will be enclosed in a white kitchen garbage bag for weather protection when it’s outside. That seems low-tech, but has worked will in all of my controllers over the years.

Cabling

Projects like this often come down to cabling. Each light needs a wire that goes from the controller out to the light. I did a random layout of lights on the tree, and put them on 5 different ropes so they could easily be pulled up the tree on a pulled.

Here are the 15 lights and all the extension cords required to hook them up. In this case, I used 24 15′ extension cords because it was cheaper and easier than building the cables up from scratch.

That’s all for now.

Holiday light project 2008…

November 25, 2008 at 12:19 am

I’ve been searching for a new project to do for this season’s holiday lights. I typically have four or five ideas floating around my head, and this year is no different.

Lots of choices, so I’ve had to come up with a “rule” about new projects. The rule is that the project has to be in the neighborhood of effort-neutral. It already takes too long to put up (and worse, take down) the displays we already have, and I don’t want to add anything that makes that worse. Oh, and they can’t take too much power, because I’m already on a power budget.

Unless, it’s, like, especially cool.

I had an idea that met all my criteria. It was small – small enough to be battery powered, if I did my power calculations properly, and was going to be pretty cool.

It was, unfortunately, going to be a fair pain-in-the-butt to build – the fabrication was a bit complex, and the plan was to build a number of identical pieces. Oh, and it required me to choose the perfect LEDs from the 15 thousand that Mouser carries.

So, I hadn’t made much progress.

Then, one day I was waiting for some paint to be tinted at my local home store, and I came across these.

They’re holiday lights. Jumbo-sized holiday lights.  The bulb part is made of colored plastic, and measures about 7″ high. At the bottom there is a large fake lamp socket. Inside of all of it is a genuine C7 bulb of the appropriate color.

I bought 3 sets, 15 in all.

To be different, I wanted to build these as self-contained devices, with a separate microcontroller in each of the light bases. The microcontrollers I’m using cost about $1 each, so there isn’t too much cost there, but the big challenge is a power supply. Generally, I build a linear power supply, which is simple and performs well, but you need an expensive and bulky transformer.

There is a way around that, with the reasonably named “transformerless power supply”. Realistically, a better name would be the “high-voltage shock-o-matic”, because it involves hooking things directly to the AC line, can only supply a small amount of current, is inefficient, and is hard to troubleshoot. Oh, and if one component fails you get 150 volts instead of the 5 volts you were expecting.

I decided to build one of these, so I ordered up some parts, wired it up, plugged it in, and immediately lost the magic smoke from one of the resistors. Turns out I miscalculated, and I needed a much-more-expensive power resister.

Thinking about it some more, I decided that since I still needed power to each bulb – and therefore a wire to each bulb – it was simpler to just build a simple system with one microcontroller.

Ring of Fire – Summary

December 12, 2007 at 3:22 pm

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.

 

Santa Animation

December 11, 2007 at 11:31 pm

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

Santa Animation
Santa Animation

Ring of Fire – Video

December 11, 2007 at 11:24 pm

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.

Ring of Fire ornament
Ring of Fire ornament

Tree of Lights Video

December 11, 2007 at 11:21 pm

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

 

Tree of Lights
Tree of Lights

Ring of Fire – Up in a tree

December 9, 2007 at 10:12 pm

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:

  1. I hadn’t set the avr to use the internal clock correctly. This meant that it used the clock on the STK500 board, which I changed now and then, so the animation timing made little sense. This also mean that the chip didn’t run when plugged into the board.
  2. Reset needs to be pulled low for the avr to run until reset is disabled. This means that until you are ready to burn the final version, you need to pull it low in the final circuit or you can’t test it. This also means that that LED is always on. When you are finally ready, you set a fuse, and reset is disabled, so you can’t program it using the in-circuit programming approach, so it’s a lot harder to do.

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.

 

Ring of Fire – Ring and Firmware

December 4, 2007 at 11:27 am

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:

  1. Using the wheel as a form was workable
  2. The piece of conduit I had wasn’t long enough
  3. It was sort of bunged up for my first attempt

A quick trip to Lowes and another 30 minutes with the heat gun, and I had a nice hoop (size 700c) completed.

Firmware

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:

  • A nice 20MHz dual-trace Tektronix oscilloscope that I bought on the internets a few years ago.
  • A benchtop power supply (+5V, +12V, -12V, and 0-20V)
  • A Fluke multimeter
  • A Weller temperature-controlled soldering station
  • My 8 fingers and 2 thumbs

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.

<aside>

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.

</aside>

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:

TCCRO0A=0x09

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

Ring of Fire – Simulator

November 28, 2007 at 4:20 pm

To make some progress before my parts arrive (they showed up yesterday), and to have a good way to test my animations, I decided to build a simulator.

The simulator is build in windows forms, and is intended to prototype both the approach I’m going to take in the real software. I’m also hoping I can steal code, as the real software is going to be built in C this time, rather than directly in assembler.

To build the simulator, I had to decide how I was going to encode the animations, and how the main loop would work.

Because of time constraints, my plan was to build this as a sequencing system rather than something involving dimming. So, I coded up a very simple scheme of encoding the output in 3 bytes:

Count byte            first 8 lights            second 8 lights

Where the light bytes tell you what lights are on, and the count byte tells you how long to stay in that state.

I then tried to write a “lights go around in a circle animation”. The table looks roughly like this:

0x08, 0x80, 0x00
0x08, 0x40, 0x00
0x08, 0x20, 0x00

0x08, 0x00, 0x01

So that’s 16 lines of entries, taking up 48 bytes for a very simple animation, with me doing a lot of bitwise math in my head.

I then decided to do a more complex animation – there’s one light on at the bottom, the other lights circle around, and give a whack to the fixed one, which starts moving. So, in essence, a fixed spot moves backwards as the main animation goes forwards.

A full cycle of that involves 16 full circle cycles, or 768 bytes. Each of which had to be hand-figured out, basically by overlaying a fixed mask on top of the moving circle animation. I got through two cycles through a lot of debugging and testing, and decided I’d had enough. It was like programming a system without any looping constructs.

So, I decided to abandon the table-based approach to take a programmatic approach. Well, strictly-speaking, it’s a hybrid approach, where the animation is controlled programatically, but the low-level stuff is handled on an interrupt.

I also decided to incorporate dimming, since I really wanted to. So, here’s the design.

Interrupt Handler

The interrupt handler executes N times for each cycle (arbitrarily set to around 1/100th of a second to avoid flickering), where N is the number of dim levels I want to support. Consider N to be 64 for sake of argument.

PWM Cycle

The lowest level operation is to implement the PWM loop. Each time the interrupt fires, a byte counter is incremented, and compared to the dim level array elements (one per led), and the output bit is cleared if the counter is greater than the dim level for that light.

So, we have this array of lights all turned on, each with a number saying how bright it is, and as the PWM cycle continues, lights get turned off as their dim level is reached. Those with a low dim level are turned off early, those with a high level are turned off later.

The current levels are stored in a

byte current[16];

When a PWM cycle is finished, we reset all the outputs to high and the counter to zero, and then move to the animation cycle to see what to do next…

Animation Cycle

The animation cycle implements changes to the current array values over time. This is done through a delta vector and a count. Basically, we have:

byte delta[16];
byte deltaCount;

and every time we go through the animation cycle (ie each time a PWM cycle finishes), we add the elements of delta to current, and decrement the deltaCount.

So, if current[0] was 63 (ie full on), and we want to dim it to zero and turn current[1] full one, we would set up the following:

delta[0] = 255;
delta[1] = 1;
deltaCount = 63;

The first time through the cycle, current[0] = 63 + 255 => 62, and current[0] = 0 + 1 => 1. We’re just adding 1 to current[1] 63 times, and subtracting 1 (by adding 255 to it) from current[0] 63 times.

If we didn’t want dimming, we could also encode this as:

delta[0] = 193;    // 256 – 63
delta[1] = 63;
deltaCount = 1;

That would flip from one light to the next in a single cycle.

Note that we can achieve a hold by clearing the delta array and setting deltaCount to whatever delay we want, which leaves current[] unchanged for that period.

After the animation cycle has completed, we need to get the delta[] and count values for the next cycle. We do this by copying from deltaNext[] to delta[] and from deltaCountNext to deltaCount, and then setting deltaCount to zero. That gives us the delta set, and we continue as before.

That’s all for the interrupt routine, but it rather begs the question – where did the values in deltaNext[] and deltaCountNext get set?

Main animation loop

In previous incarnations, the main animation was just handled in the same section of code as everything else – when the animation cycle ended, you’d figure out what you needed next (well, actually, you did it right before you needed it).

This has two whopping disadvantages.

The first is that you have to do it in the spare time between cycles. That’s not bad if you are doing simple animation (ie not dimming) or you’re doing dimming in hardware (which I’m not), but in this case there may not be enough time to do the main animation loop in the time left for an interrupt (at 64 dimming levels, about 156 microseconds for everything, including the interrupt routine).

The second is that you have to write the animation as a state machine – for any given set of counters, you need to know what the next delta[] should be. That’s not going to be much fun for more complex animations.

I therefore decided to let the main animation loop run in the main execution thread (well, there is only one thread, which the interupt preempts as needed). It therefore has the full animation cycle to come up with the next set of values (though, if the count=1, that’s the same as the PWM cycle), or 10 mS, and there should be enough time leftover to do the work I need to.

The main loop will use a blocking function to tell it when it needs to proceed. It’s:

void SpinWait()
{
while (deltaCountNext != 0)
{
}
}

So, we’ll just hang in that tight loop. An interrupt will come along, do what it needs to do, and if it’s at the appropriate point, deltaCountNext will be set to zero and when the interrupt returns, we can go on to generate the next values.

That allows the animation to be coded as something like:

SpinWait()
deltaNext[0] = 255;
deltaNext[1] = 1;
deltaCountNext = 63;

SpinWait()
deltaNext[1] = 255;
deltaNext[2] = 1;
deltaCountNext = 63;

which is a whole lot easier to understand, and you can even use this thing called a “loop” so that it’s easy to write. The simplification is roughtly analogous to how it is easier to write an enumerator using yield than the old way.

Back to the Simulator

The simulator implements this by having a timer fire off every 10 mS, and it calls into the interrupt code (which does everything except the PWM loop). The main loop runs in a separate thread, and everything is peachy.

That’s all for now. I think my next task is to write a few more simulations to make sure the code does anything, and then move the code to the microcontroller, hook up a scope, and see what I get.