When I saw the Aurora LED 9x18 Instructable, I was inspired.  However, it's built on the PIC microcontroller while I am most familiar with the AVR microcontrollers.  Plus, I already have the development and programming environments for AVRs, so I set about a redesign as a personal challenge.  I wanted to make something (almost) just as nice, that did not require as many components, was less expensive, and could be soldered by hand (albeit maybe taking a lot of time).  The result is this Instructable, the ChromoDisk.

The ChromoDisk is very similar to the Aurora LED.  It has the same 9 rings of 18 LEDs and every ring has to be the same color and brightness due to the multiplexing approach.  This device uses pulse-width modulation (PWM) instead of resistors to limit the power fed to the LEDs, so while it takes less assembly time and components, you need to be a little careful about how you write the software.  This is a good illustration of the tradeoff you need to make when you design with microcontrollers.  You need to strike a balance between what you do in hardware and what you do in software.  I am NOT saying that LED Artist's approach with all the resistors is bad, it's just a design choice and this is one alternative.  More about this later.

Let's start with the design parameters:

  • Easily available, low cost components

  • Low component count

  • Fits within a low-cost tier for PCB manufacture

  • Hand-solderable

  • Multiple power supply options

  • Easily programmable
The design you see here has been through 4 generations.  You can make a lot of mistakes in PCB design and layout, and I did.  Little things like forgetting to mirror components (battery pack) to the back of the board, not accounting for total current loads on chips (overheated micro), and switching transients (turning all the LEDs on at once) wreck a design.  I ran into all of these and more.  I think this final version gets it about right though.

The components I've chosen barely fit into the tight space.  I picked the largest SMT components that I could to facilitate manual handling and ease of soldering. In the end, because of the limited real estate, I was not able to allow both battery pack and DC power jack, so you need to choose which one you'll use.  Also, everything fits within a 100 mm square, a 4 inch disk, which is one of the pricing tiers typical of most PCB manufacturers.  Anything bigger bumps you to the next pricing tier.  Since area and cost goes up as the square of the radius, it's a good idea to limit the size.   Routing out the circular shape is normally included in the board price.

The AVR micros are fairly easy to program.  The code I've provided is entirely interrupt-driven and written in assembly language.  It might be a bit less readable than C or some other language, but it's about as efficient as you can get.  I don't claim to be the best programmer, but it seems to work pretty well and I was able to derive some new modes using code from other modes.  It's designed to be hacked!

Here is the list of parts for the ChromoDisk, with Mouser P/N, description, and quantity:

667-ERJ-3EKF1201V Thick Film Resistors-0603 1.2K ohms 1% 13
667-ERJ-3EKF6800V Thick Film Resistor-0603 680 ohms 1% 3
667-ERJ-3EKF1002V Thick Film Resistor-0603 10K ohms 1% Tol 1
81-GRM188R71H104KA93 Capacitor (MLCC)-0603 0.1uF 50volts X7R 10% 1
512-FDN338P MOSFET Small Signal SSOT-3 P-CH -20V 3
771-PMST2369115 Bipolar Small Signal NPN 15v 200mA 500MHz 12
556-ATTINY4313-SU Microcontroller AVR 4KB FL 256B SRAM 1.8-5.5V 1
612-TL3315NF250Q Tactile Switch LOPRO 250GF SMD 1
611-KSC741GLFS Tactile Switch 4.3mm IP67 3N Soft Actuator 1
798-DF1BZ-6DP-2.5DSA 2.5MM V DBL ROW HDR 1
  Common cathode RGB LEDS 162
  Custom PC Board 1
598-AVE227M16X16T-F Al Electrolytic Cap - 220uF 16V 85C Case 6.3 x 7.7 1
163-5030-E DC PWR JACK 2.0MM X 5.5MM SMT 0/1
12BH331P-GR Battery Holder 3 AA PC LEADS 1/0
  In-System Programmer for AVR microcontrollers 1

A couple of comments here.  First, you'll notice that you have to choose either the DC power jack or the solder-on battery pack (you can use one with wire leads if you like, but I designed it to use the version with pins).   There's a mounting hole in the center for whatever you want, but the battery pack will obscure it.  I used it to secure battery packs before I added the PC mount pack.  Second, I don't have a spec for the RGB LEDs.  It's entirely up to you which ones you choose.  Since I eliminated the current-limiting resistors on the LEDs by using PWM in software, you can adjust the brightness of the LEDs over a wide range by adjusting a couple of simple parameters at the top of the code. This allows you to accommodate LEDs with various current specs as long as they can take the surge current of the PWM approach.

The pinout for the LEDs is red / cathode / green / blue.  I have tried assembling boards with diffused and water-clear LEDs.  Diffused give more uniform color and brightness; clear give brighter light that floods farther and they have interesting effects with angle of view, but non-uniformity in LEDs can result in color hot-spots.  The PWM approach has some limitations there.

I've ordered the parts in large enough quantities that I can provide the kit of parts and the custom board (but not the ISP programmer).  Let me know if you're interested.  Given the time involved, I'm not going to make any money on it.  That wasn't  really the point.  It was intended to be a challenge and something fun for people to experiment with.

Step 1: The Build - Layer 1

There are five phases to the build:

- Solder on the small passive SMT components and transistors
- Solder on the larger SMT components
- Program the microcontroller
- Solder on the LEDs
- Solder on the power source

The idea here is to put on components that don't interfere with each other in layers.  The board is very crowded, so it's essential to do this to make the build as easy as possible.  Here's a picture of the board you're starting with.  Let's go!

Layer 1 - SMD Components ... Most of them

The passive components go on first because they are the smallest and easiest to lose if you tilt the board.  You need as much clear area as possible when you're soldering these.  You can use the “skillet” / oven method, or hand solder them.  I did it all by hand.  SparkFun has a good tutorial on hand-soldering SMT components, so I won't try to duplicate that here.  Solder on all of the resistors and the bipolar transistors first.  The MOSFETs are static-sensitive, so adding in the other components first will help protect them.  Don't put on the microcontroller, the large electrolytic cap, the 6-pin connector, the LEDs, the power connector / battery pack, or the capacitor on the back yet.  Solder on the MOSFETs last in this layer.

Step 2: Layer 2 €“ Large SMD Components

Now that you've got the small components in place, add in the two switches.  Put the large one on the pads labeled Mode, since it's the one you might use the most.  The shape of the switch makes it a little harder to solder in place.  I found the key to be soldering one contact in place, with the switch centered on the pads.  If you heat up the other pads, and use good flux, the solder will wick in underneath pretty readily.  The other switch goes on the Reset pads.  It has more exposed contacts, so it's easier to solder down.  Add in the large 220 uFd cap, the microcontroller, the small cap on the back opposite the microcontroller, and the 6-pin connector.  Note: the image here shows the LEDs installed.  If you're following along while building one of these, they aren't there yet!

Step 3: Layer 3 €“ Programming

At this point, you have everything on the board to program the microcontroller except the power connector.  You'll need to jumper your power source to the two holes for the battery pack.  Make sure you respect the polarity!  Depending upon the ISP you're using, you'll need to connect the power before or after you connect the programmer to the 6-pin connector.  Check the instructions for your programmer.  An initial program is provided here, in both source and code formats.  The microcontroller does not come pre-programmed, so you'll need to do that now.  The advantage of doing it here, rather than at the end, is that you can test as you go.  One of the modes in the code lights up each color in each ring.  This allows you to verify that your LEDs and other components are soldered in place correctlyas you progress through the build.  To do this, you can connect the power when needed.  I did this with the battery pack by inserting it in the holes without soldering it in place.  If you chose the DC power jack instead, it will be a bit more difficult.  You could solder that on, but it will make manipulating the board a little more difficult during the rest of the build process.  Here's what it looks like with the battery pack in place.

Step 4: Layer 4 – the LEDs

You would have thought that the surface-mount devices would be the hardest part of the build.  For me it was the LEDs.  The pins are close enough together that it's easy to get solder bridges.  Plus there's the sheer tedium of soldering 162 LEDs with 4 pins each.  One method that works for me is to insert all of the LEDs and verify that they are oriented properly.  You can get an inkling if you connect up the power and go to the test mode.  Not all of the pins will make contact without soldering, but if you press an LED to one side or the other, it will make contact on all of the pins and you can get it to light up as a quick test.  If any of the LEDs are inserted the wrong way, strange things can happen with all the others, because they are all connected into a big matrix.  Solder bridges do the same thing, so be prepared with a magnifying glass.  And use a quality solder and plenty of flux!

Here's my approach to the order of soldering.  Once you've got all of the LEDs in place, solder one pin on each LED in the outer-most ring in place on the bottom side of the board.  Make sure that as you solder, the LED is fully inserted so they are all flush with the top side of the board.  You can also use the shoulders on the leads to space the LEDs up off the board, but this is a little more difficult to get consistent height.  The choice is yours.  Thicker overall board with the LEDs up off the board, or slightly thinner and more compact with them all flush.

Next, go around that outer-most ring and clip the leads, leaving a little nub for soldering the other leads later.  Then proceed to each of the rings, soldering one lead on each LED and clipping leads.  Once you've got all of the LEDs tacked in place, go around and solder all of the remaining leads.  This goes a lot faster.  Make sure you don't miss any, or you'll be trying to figure out why some of your LEDs are acting funny.

At this point, you need to test all of the LEDs and make sure they are working, because if you're using the battery pack it will cover up some of the leads!  The DC power jack is not as problematic, since it does not obscure the pins.  It's sometimes very difficult to find bridges, and I don't have any wise words or troubleshooting steps for you.  However, I have found that the board is thin enough that you can shine a light through from the top and inspect the bottom side to find some bridges.  If you don't see a complete ring of light around each LED on the bottom side, there's likely a bridge there.

Use the one-color-per-ring mode as a final test though, to make sure every color and every LED is working.  Here's what it should look like:

Step 5: Layer 5 – the Power Source

Now you can add the power supply of your choice and you should have a working device!  I hope you think the result was worth the effort.

Step 6: What Next?

I showed a completed disk to some friends just before Christmas, holding it at the top of their tree.  They asked if I could make one that looks like a star, so I went home and stuffed a board with just the LEDs to form a 6-pointed star (the number of LEDs in a ring lends itself to this layout best).  They loved the result!  So feel free to try different arrangements of LEDs – you do not have to populate the whole board.  However, remember that if you are using the battery pack, empty LED spots that you might want to fill later will be covered up!


If you have any questions, please post them to the Instructable.  Please also feel free to hack and try different things.  I've provided source code, programming file, schematic, board layout, and Gerber files.  This is an open source device and you are free to use any of the files, with attribution.  I hope you enjoy it!

Step 7: A Walk Through the Code

One of the points of designing this device was to make it "hackable."  I've provided the source code so that you can both learn how these things are programmed, and also to modify it as you like.  If you're like me, you find it difficult to read someone else's code, regardless of the language.  Assembly language is perhaps a bit more difficult, but it's fast and you have complete control.

The code is structured at a high level into parameters, code, and data.  the parameters section is meant to bring all of the key contacts that affect how the color modes work to the top where you can easily modify them without diving into the code.  The first part of the parameter section adapts the code to the hardware and, although you're welcome to design your own board as I did, I'm going to assume that you want to use it for this board and either change one of the modes that's already there, or write your own.  So skip down to:

.equ initialMode = 4
.equ maxModes = 6

The first EQU sets the mode the ChromoDisk jumps into when first powered on or when you press the Reset button.  Mode 4 is the rippling color mode.  The next EQU is just the number of modes implemented in the code.  Remember to change this if you add a mode of your own design.

The rest of the EQUs are specific to each mode.  At first I wanted to write a generic program that allowed me to generate new modes just by changing a few parameters.  I didn't figure out a way to do that, so each mode has its own special code section you'll see later.  I've provided comments that i hope are pretty easy to understand, once you know how the mode works.

You'll see that there are arithmetic equations in some of the EQUs.  There are two things to remember here and throughout the code: the microcontroller is an integer machine, and it knows two basic ways to work with numbers.  If you write an equation that results in a number with a fraction, it's going to be truncated.  Don't expect 2/3 to give you 0.666667.  It will give you 0.  This may seem obvious, but at some point you're going to forget and wonder why some piece of code is not working right.  With respect to number systems: you can interpret an 8-bit number as an absolute number (0-255) or as a signed integer (0 - 127, and -128 to -1).  I know this well, and yet I still sometimes get tripped up on it.  An even more subtle issue is that the processor will treat an integer as absolute or signed depending upon which instruction you use.  Branching is a great example.  You would expect that if you read the timer and get 132, that if you compared 120 with 132 and branch if it's lower, BRLT (Branch if less than), it would take the branch.  Not so fast.  BRLT assumes the numbers are signed, so 132 is actually -125.  For unsigned numbers, as in this case, you need to use BRLO (Branch if lower).  Keep this in mind as you read through the code.

The executable section starts with the .cseg statement.  The code contains, in order:
- the interrupt vectors that point to the interrupt service routines (ISRs)
- the initialization code, executed after a reset
- the main code
- the initialization code for each mode
- the ISRs
- the data area, which starts with .dseg

I don't want to make this too long, so I'll try to summarize.  The program is completely interrupt-driven, so everything happens in the interrupt service routines.  The main code just puts the processor to sleep.  It wakes either when the Mode button is pressed, or when a timer times out.  Timer 0 is used to debounce the Mode switch.  Timer 1 is used to make the colors change using a single PWM control line and the color on/off outputs.

The Mode switch illustrates the hardware / software trade-off mentioned earlier.  Switch contacts bounce when you press them, so you need to be able to handle a series of short pulses, rather than just a high or low input.  I ended up doing this in software because I could not find an easy way to do it with the space and hardware that I had.  Basically, the mode switch resets Timer 0.  If timer 0 times out before it gets reset, the code assumes the contacts have stopped bouncing and the code can take action.  This is a bit of a hack and you have to carefully pick the timeout value.  You'll see that the device sometimes skips a mode, so the timer setting isn't perfect.  It's a trade-off between response time to pressing the button and how often it skips a mode.

If you want to see how each mode is implemented, look at the Timer 1 ISR.  There's a variable in memory that keeps track of which mode it's in.  The ISR looks at that number and jumps to the right part of the code, kind of like a CASE or SWITCH statement.  Each mode needs to keep track of it's own state, stored in RAM, such as which color it's on.  Most modes turn on the red, then the green, then the blue, and back to red.  In general, they cannot all be turned on at the same time because there's only one PWM output controlling everything and he width depends upon the brightness of the color that's on.

So that's a quick overview, without writing a book.  I'l try to answer more detailed questions if you post them.   Have fun!

Step 8: Documentation

Here is the design documentation.  I've included the schematic as a high-res image and the complete set of Gerber files in a ZIP package.

Holly cow!!! I can't&nbsp;believe&nbsp;you made a copy! (is it ok to say that?)<br> <br> Kudos for doing it your way and doing it with a 8 bit controller. I decided at the early stage of the development that 8 bit PIC wasn't going to cut it, and&nbsp;learned the 16 bit assembler.<br> <br> I'm very curious to see the schematics, though...<br> <br> Aki
Hi Aki, <br>To be honest, I had mixed feelings about posting this Instructable, since it is a rework of your great idea. In the end I thought it would be useful to give an alternate design approach to help people understand some of the issues involved, and it makes the design accessible to those who use AVR rather than PIC. I'm always up for a personal challenge, and surprised myself that I pulled it off ... and in only 4 design cycles, LOL! So I take your comment as a compliment and hope your other designs are going well! <br>Sorry for not posting the design docs (yet). I had intended to attach them and just plain forgot. I'm moving to a new laptop and need to re-install some apps (like Eagle), so look for the Eagle and Gerber files in a few days. <br>Best regards, <br>Roger
Looking forward to it. <br>
Done! I've added another step at the end with a high-res schematic and the Gerber files for the board. Not sure the Eagle files would be of much use to most people because they are larger than the free version can manipulate. If there's anything else you'd like to see, please let me know.
Another member sent me an email and noted that the schematic didn't really come out &quot;high-res&quot;. Sorry about that. I've posted the schematic in Eagle format if anyone is interested. I think it's too big to manipulate in the &quot;free&quot; version of Eagle, but let me know if you have trouble viewing it.
Cool. I see that the circuit is essentially the same except the lack of current limiting resistors for the LEDs. Bold move, that one... (be careful doing this though, there are more reasons to use resistors than just limiting the curent - balancing the current between the LEDs connected in pararel is an important one. There are other issues such as stressing the MOSFET/transistor. It's working and all is good with this one I guess.)<br><br>If this AVR has 3 PWM generators, you could omit 3 transistors connected to the MOSFET - like Aurora 9x18 mk2 and 18x18's circuit. This also saves an IO pin.<br><br>Thanks,<br>Aki
I wanted to see if using PWM and pulsing them to max brightness would balance the output enough. It seems to work with diffused LEDs, but I found that the water clear ones sometimes had hot spots, especially in the green pixel. Usually only happened with 3 -4 of them though. With the water clear LEDs, the lensing effect where you see a slightly different color cast across the board was more prevalent and interesting. <br>The ATTiny only has two timers, so I was not able to eliminate your FET drivers. I did change the resistors on the driver circuits though to reduce the current draw on the AVR outputs. It was funny on version one of the board where I didn't have the resistors on the bases of the bipolar drivers of the LED cathodes: the ATTiny heated up pretty well! The bases essentially act as short circuits.
You sirs - Both Awesome!
Thanks for this. No harm done (the original instructable is referenced) and as a fellow AVR user i can only say that this is a great help. Plus porting from one AVR to another (e.g. attiny to atmega8) is fairly easy. <br> <br>Any reason you chose assembly over C? The code outputted by GCC is usually just as good as asm (and can sometimes be more efficient than writing it yourself, because GCC can optimise register usage, etc.) and often it's not worth the hassle. Still, thanks for putting the source out there, all too often it's missing from the projects!
Hello. <br>Can You share the schematics and/or pcb files ? <br>( Ithink, You use altium/protel ? ) <br>Or a better schematic (pdf or so ). <br>THX <br>Frank-de <br>
ela aaaaaaaaaaaaaa aaaaaaaaaa
Any issues with power dissipation? My back-of-napkin calculation for all emitters on 100% (162 LED's * 3 emitters/LED * 3V * 0.02A) is about 30 watts. I imagine, then, that it's extremely bright.
Remember that they are PWMed so they're not all on all the time. Figure a duty cycle of 50% maximum, and if you do animations and colors other than white it will be much less. So maybe 10-25%? That wpuld easily give you about 4 hours run time with good AA rechargeables and a 1A 5vdc wall wart drives it with no problem. Interestingly, the reason for the 220uF cap is because of the current spikes. I was getting processor resets without it.
Can you give a price breakdown for the board and components so we can have an idea of what you paid? <br>Very nice.
There are too many variables to give you one cost number for this. They include quantity of boards you want to build, quality of LEDs you choose, where you want to source them from, the PCB house you use, etc. I can tell you that the LEDs are likely going to account for the bulk of the cost, regardless of where you get them. In huge quantities, you could likely get the total parts cost down under $30. In single quantities, you're looking at something over $100. Remember also that there are several hours of build time involved. Check out the kits available for the Aurora 18x9 offered by LEDArtist for one example. The parts for this version are slightly less, if only because it eliminates the resistor-per-LED for current limiting. <br> <br>If you want to price out the pieces, the board fits in a 100mm x 100mm board size. It's two-sided, with solder mask and silkscreen both sides, so your preferred PCB house should have standard pricing. <br> <br>Does that help?
Could you code the fully-populated board to display the star shape? <br> <br>That way you could use the ChromoDisk all year round...
Therein lies one od the compromises in tbis design. The LEDs are not individually addressable. All of the LEDs in each ring must be the same color and brightness.
Ah, I see.

About This Instructable




More by Surferdude:Hermes' Caduceus The ChromoDisk Trash Landing 
Add instructable to: