OK so I have finally found some time to begin writing the story of my RGB LED cube, this project was always going to be the next step in the evolution of my LED Cube. I can only hope that it will be as popular as my original cube, for those of you that followed my original cube project you will probably notice a few similarities.
I built the RGB cube while I was living in the UK for 6 months, so I had access to a limited number of tools and most of the work was done on the dining room table to the dismay of my girlfriend (wife now). Working on this project I have learned a lot about animating in colour, software modulation for fading and c++ in general, so hopefully I can teach you readers a thing or two as well. If nothing else at least you will be able to use what I offer here to build one of the greatest light displays you have ever seen! (If I do say so myself :P)..
Before I Begin
Well this is a pretty long article, if you somehow got here and don't know what an RGB LED cube is here is a video, hopefully after watching you will read on to see how I made it.
So first things first, how much time should you set aside? Don't be surprised if it takes you a couple of weeks, I think I spent about 20 hours just soldering LEDs for this project. I also spent about 60-80 hours on the software, but I guess I will give that to you (well most of it). Next here is a parts list, most of the parts I have used I purchased from ebay, I find that it really is the cheapest place to go for relatively low quantity electronic components,I did still use farnell a lot because of their next day delivery.
So it turns out I had made a couple of mistakes when building the driver board, as pointed out by a friendly commenter. My cube worked so I wouldn't get too worried if you had used the old values, but you may get better results by changingthe current set resistors and the decoupling capacitors.
- If the links for any of the following items go down just check out the
- 512 x 10mm, common anode RGB LED - - 0 AUD
- 12 x STP16 LED driver - - AUD
- 8 x 2N5195 PNP transistors (next time I am using MOSFETS) - - AUD
- 1 x ChipKIT UNO32 - -
- 1 x 5V switched mode PSU - - AUD
- 1 x 5v-3.3v DC-DC converter - - AUD
- 12 x 0.1uF 16V ceramic capacitors - - AUD
- 8 x 100R resistor (Transistor base resistor) - - AUD
- 12 x 1K resistor (STP16 Current Set Resistor)
- 8 x 1.5K - 10K resistor (Transistor pull up) - - AUD
- 14 x IDC ribbon cable connector - - AUD
- 1 x Roll 22AWG tinned wire - - AUD
- 14 x pin headers (16x2)
- 16 way ribbon cable
- 12mm ply for the base and jig
- 20x12mm pine for the jig
- screws, solder, bluetack, etc, etc.
- TOTAL 0 AUD
The Cube Assembly
So as you can imagine the assembly of this cube is a little more complicated than my original cube, before I begun the larger 8x8x8 cube I decided to build a little proof of concept cube to test some methods of assembly. Now because I am using large 10mm LEDs I had to make sure I allowed enough space between each LED, unfortunately this means that I had to use wire to connect each LED rather than using the LED's legs.
For my proof of concept I used protoboard as the base rather than make a jig, I also decided to assemble the cube in layers like I did with the original cube. This was my first mistake, I will only show you one picture and hopefully you can see why this method would be an absolute nightmare when assembling an 8x8x8 cube. Actually I'll show you two, just to show you that I didn't give up, it actually turned out pretty nicely so I gave it to a friend
How Not To Make an LED Cube
Mini RGB Cube
Anyway now I had an idea on how I would not do it, so I sat down with a glass of red wine as inspiration and got thinking. After a few designs in my head I decided that rather than assemble the cube in layers it would be more simple to assemble the cube in panels. So you understand what I mean here is a picture of both the finished product and the proof of concept highlighting the method of assembly. The major advantage of panels over layers (I think) is the fact that the jig I designed is so easy to make, my jig consists of one flat board (I used 12mm ply) and 8 lengths of 20x12mm pine beading.
Panels Versus Layers
The Bends and The Jig
I am very happy with the cleverness of my jig, is was easy to build and I was able to get 8 identical panels of LEDs. The first thing you need to do is bend all of your LEDs, I used a 6" steel ruler for this as it helped get the nice right angles that I wanted, then use some of the 12x20 pine strip for the second bend so that you bend it at the right length. Next trim the three cathodes so you have a couple of mm left to solder, I used finger nail clippers but I would recommend wire cutters if you have them.
Do A Jig
Step 2: Make The Columns
To make a panel you first make eight columns by bluetacking eight LEDs in position as shown in the photo below. Line up each LED to the edge of the board with something flat, then use some pliers to make three straight lengths of wire from your roll. With these three lengths solder the cathodes of the eight LEDs together to complete your column.
Step 2: Make The Panels
When you have 8 columns you are ready to create a panel, turn the columns over and line the top LED up with the edge of the board, tack them in place with bluetack again. You can now trim all 64 LED anodes ready for soldering, straighten another eight pieces of wire and solder the columns together. In this photo the blobs of bluetack give the illusion that the LEDs are not evenly spaced, don't worry they are near perfect.
Step 3: Put It All Together
With your eight panels of 64 LEDs you are now ready to complete the cube, unfortunately this part gets a bit messy. Next time I will rethink this part of the assembly, for now it is all I have to show you but feel free to attempt something different. So I edited my jig slightly and used it to hang the panels from the table ready for soldering. In the picture I have all the panels hanging quite roughly spaced, I actually worked on each panel one at a time soldering as I went. Now here you will see that I ended up with a similar problem to my proof of concept assembly (wires dangling everywhere) this step could definitelly use some improvement but it wasn't all that bad really.
Step 4: Put Down The Soldering Iron
By now you are probably covered in burns and never want to look at a soldering iron again, it's ok just put it down for a while and have a rest. I actually felt sorry for the soldering iron, the one I managed to borrow was older than I am, consequently if you need a decent soldering iron look at a Weller. So your cube is assembled and it looks friken awesome and it is not even turned on yet, I just sat and admired mine while I waited for a new soldering iron tip in the mail.
The Control Board
So up until now I don't think there has been all that much difference between my cube and some others I have seen on the web, but here the design starts to wander off on a different path. Most RGB cubes I have seen rely on driver boards based about chips that can perform PWM for you like the TLC5940. These chips seem great but im my opinion are just too damn complicated to run, so I decided to stick with the STP16 chips that I knew from my previous led cube project and I would figure out the PWM in software.
I don't have any eagle files unfortunatelly for this PCB, I actually tried out the RS design spark software and then actually lost the PCB files. You can download the gerber files from the downloads section though. I also didn't put the schematic in this article because it is so damn big, you can download a . One mistake to note in the PDF is that the Base and Collectors of the transistors are reversed, hence the mix up with the PCBs later on.
There are a few differences between this board and the driver for my previous cube, firstly rather than join the 12 chips in one long cascade I created three shorter cascades for the red, green and blue diodes in each LED. The idea here is that I can clock in the red, green and blue data at the same time, reducing the time to load the data into the drivers, hopefully the pictures below give you an idea of what I mean. You will also notice that this time I didn't just pull output enable (OE) to ground, I now control it with a digital IO, this allows me to switch off the drivers when I load in the data which reduces some of the flicker I was getting.
The transistors are also now controlled directly from the digital IO's, this speeds up the refresh process even more. My design focuses on efficiency and speed, though it does mean you will use a few more digital IOs on the chipKIT. You will need 14 spare IOs for the cube, I figure you may as well use them.
I decided to get the boards manufactured for me this time, and I am glad that I did because they turned out beautifully. Initially I ordered a board from in America, these guys offer a low cost prototype manufacture but expect to wait about four weeks before you get your boards. I didn't realise when I ordered the boards that they would take so long so I made a second order to a UK company , these guys are amazing! they have some insane offer for new customers, 3 boards for 10 quid each with one week turn around, I would definitely recommend checking them out. Somehow the transistors I purchased had a different package to the ones in designSpark so I had to do some nifty bending to get them in place, I think it adds character.
RGB LED Cube Driver Board
Unlike my previous cube I wanted this one to be a completely self contained object, the idea was plug it directly into the wall and it will start producing lovely animations, no PC or external PSU required. So I decided to buy myself a nice high current PSU I could fit inside the box, now because of the fact that the chipKIT only sports 3.3V IOs, I had to run the cube at 3.3V as I am driving the layers with PNP transistors. Not a problem, except I also wanted to be able to connect to the chipKIT while running the cube using the usb-serial converter, this requires that the chipkit is powered by 5V through the onboard regulator.
Now lets look at power requirements, as the cube is multiplexed only one layer will ever be on at a certain moment, that is 64 RGB LEDs or 192 diodes. Each diode is going to draw 3.3/100 = 33mA (I = V/R), so if all of the diodes are on at once that is a load of 6.3A! I decided then that I would just avoid any animations that create layers of white (they don't look any good anyway). I ended up sourcing a 25W switch mode power supply for the 5V rail and a 7A 5V-3.3V DC-DC converter for the 3.3V rail, I used double sided tape to attach the DC-DC converter to the side of the switch mode PSU and this is what it looks like.
So the 5V PSU supplies the chipKIT and the DC-DC converter, and the 3.3V PSU supplies the led driver board, don't forget to make sure all of the boards have a common ground and that the power select jumper on the chipKIT is set to reg.
PSU In The Box
Wire It Up
The box is very similar to the box I built for my previous cube, I used a sheet of ply with 64 holes drilled in it for the base and fed the cathode columns through the holes ready to be wired up. To connect the columns to the driver board I used lots and lots of ribbon cable, I wont go into all of the details here, I attached idc sockets to one end of the ribbon cables and then soldered the other ends to the cathode column wires (actually that is pretty much all of the details). I am definitely going to try and rethink this part for next time as it really is a mess, luckily you can not see it, apart from in this photo.
One thing I get a lot of emails about is where all of these wires go, I have painted some pictures to hopefully help you out.
The Wiry Insides
Animations and Code
I'm not sure how this happened, I have not even stared writing the tricky stuff and this article is already huge. Even now that I have begun writing it I still am not really sure how I am going to manage this section, the code and animations are probably the more complicated concepts in this project. They are also probably the concepts in the highest demand, so I will try and do a good job.
During the research phase of this project I found that there was almost no documentation on how other RGB cubes were animated, most I have seen use the TLC5940 PWM drivers and make reference to some code that must be floating about the Internet. For some reason I am always compelled to do everything my own way even if it is wrong, so here is how I did it.
The chipKIT UNO
The cube is controlled by a chipKIT UNO, a 32bit powerhouse which has quickly become my favorite development board. The board does it all, It multiplexes the cube, It uses Bit Angle Modulation to fade the colours and it generates the animations on the fly. All of the latest code (currently up to MK4) can be found on the downloads page of my site.
RGB Cube Driver Outputs
Multiplexing and Fading
OK I guess I may as well start at the bottom, quite a lot happens when displaying just a single frame on the cube. Firstly the cube is multiplexed so only one layer is ever on at a moment in time, then each layer is modulated using 8 bit BitAngle Modulation (BAM). As you can imagine this requires a fairly fast clock, but before I start talking about the clock rate I will try and help you visualise what is happening with some gifs I made.
Multiplexing is simple enough, all I do is perform all modulations operations one layer at a time, obviously it happens a lot faster on the cube than in the gif.
So to be able to generate a decent range of colours (16.8 million colours) for my effects I use Bit Angle Modulation to fade each diode in each LED. This is a little harder to explain, every time a layer is "on" it is actually just given 8 opportunities to be on, each coloured diode has an associated 8 bit brightness level (or byte). Each layer operation is spit up into 256 interrupts, every 2^nth interrupt the nth brightness bit is loaded into theLED and held until the 2^(n+1)th interrupt when it is replaced. Clear as mud right? hopefully the gif helps, if not well you can trust me it works. might help you understand BAM, if you read far enough it looks like someone has had some pretty cool ideas on something he coined BAMMAB
Bit Angle Modulation
So that is the theory of how I get the animations onto the cube, now I will try and explain some of the code that performs this magic.
So all of the modulation and multiplexing is achieved in my interrupt service routine located in the PDE file, it might seem like I am wasting a lot of time inside my ISR (well I guess I am), but it does what I want so I don't plan on changing it. One thing you may notice about my code is that despite using the chipKIT and the mpide software I did not use any of the Arduino libraries, it is all written from scratch because I needed to squeeze as much out of the chip as possible. I used c++ mostly but had to compile the interrupt service routine in c, that is what all the extern "C" business is about
In the latest MK4 code I no longer use the layer function I did previously, also instead of 256 interrupts with a bit counter to emulate the correct delays I actually just have 8 interrupts and I increase the delay between each one to perform the BAM.
Create The Colour Wheel
To generate all of the coloured animations I needed a clever way to create the smooth, vibrant colour effect. I was not happy with my first few attempts, after looking at a colour wheel I realised that my code was picking colours near the centre of the colour wheel which was causing them to appear washed out.] What I ended up doing is creating a linear array of colours that fade between the three primary colours using sine functions (blue->red->green->blue).
To give you an idea how it looks on a colour wheel I wrote some MATLAB code to demonstrate how my colour array moves around the colour wheel. Creating this MATLAB code and gif probably took longer than the actual colour wheel code for the cube, I hope it wasn't a waste of time. For anyone interested in the MATLAB code I wrote to plot the colours in the gif below you can .
Fill The Colour Array
So you have seen it on the colour wheel, now this is how I calculate it. I have changed this code a lot in MK4, it is much shorter, but a little harder to read. Not to worry though you will find it does esentailly the same thing.
Just in case you can not decipher the mess, I will go through one of the more "busy" lines of code so you can see how I use the oscillating sine functions to my advantage. Here I explain line 33 of the above code, blue is a function of phase where maxBitColour = 255 and colourWheelLength = 255 (this works well for my cube).
Colour Wheel Equations
How To Use This Array
Now that there is an array in memory filled with a nice smooth colour transition I had to think how I would use it, most of my animations select colours from the array based on a looped variable and the location on the cube. Unfortunately this means I can't always know what position in the array I am accessing, so that I never try to access a location out of the bounds of the array I wrote a simple function to get colour data from the array safely.
In the latest MK4 code I'm no longer using a 32bit integer and bitshifting out the 3 8 bit colours. I have just created a COLOUR struct type of 3 x 8 bit integers. So if you have a COLOUR col, you can access the individual colours with col.r, col.g and col.b... easy..
Write Your Own Animations
Well there is quite a lot of code bouncing around to run my RGB cube and I'm sure a few of you would like to have a go at writing your own animations. I have structured the code to be fairly expandable and adaptable, to write your own animations all you have to do is create a new class that inherits from my animation class. "What is this black magic you call inherits" you say? Don't worry it is easy, and this way you can use a whole lot of useful functions and variables I have writen for you to make animating easier.
Step 1: Animation Header File
Firstly I will talk about defining the header file for your animation, c++ uses the header files kind of like a textbook's index for your code (that is how I understand it anyway). I have highlighted the line in the header below that does the inheriting business (see easy), you do have to write the constructor and the animate function like I have and you can also write any of your own functions if you need them.
Step 2: Animation Cpp File
Secondly you must write the cpp file for your animation, here you will write what you would actually like the animation to do. The animations in my latest MK4 code are actually a bit more complicated than before, the duration and speed of animations are defined in the Setup.h file. There is also the oportunity to hand some information from one animation to the next using the BUCK struct type, this lets you start the next animation with the same colour as the last for example.
All the animations also have a fade in and fade out section to create some cool effects. Like the spiral animation that speeds up and shrinks down and then explodes, or the arrows that appear one at a time.
There is also no temp array any more in the MK4 code, all work is done on the one working array. This speeds things up significantly and reduces the code size so the modification to the heap size is no longer required. The cube array pointed at by ArrayP is just one long array of 512 elements, so to access it using cartesian co-ordinates (x,y,z) I have made a helper macro ar(x,y,z) that you can see I have used in the code below to set the colour of the cube.
Step 3: The Cube.h File
OK now you have written your amazing new animation you have to add it to the Cube class so that it will actually play on the cube
Include the header to the Cube.h file, and add a pointer to your animation in the classes private variables.
Step 4: Modify Setup.h File
Now you will need to add your animation to the setup file and give it a length and frame rate. The position of your animation in the animationOrder array will set the order your animation plays, hence the name.
Step 5: Modify Cube.cpp
Now just add you animation to the Cube.cpp switch statement and you are done!
And you are done! No doubt you will make plenty of mistakes to start off with, I know I did, if you have too much trouble feel free to email me for any advice, otherwise enjoy.
Step 4: Increase The Heap Size
This is not required for the MK4 code, if you are upgrading to the new code you will have to re-set it to 0x800
I quickly started to run out of RAM on the chipKIT with the 8x8x8 cube, so I had to first learn and then implement some Dynamic Memory Allocation (DMA). I also had to increase the default heap size on the chipKIT, now I can't do this step for you so here is what you need to do.
Firstly find the file "chipKIT-UNO32-application-32MX320F128L.ld" in your mpide install directory, it should be buried in the "\hardware\pic32\cores\pic32" folder. Then open the file in notepad and replace the line "PROVIDE(_min_heap_size = 0x800)" with "PROVIDE(_min_heap_size = 0x2000)", that's it. Now you should be able to happily run my code, if you miss this step you won't get any errors, the cube just wont work (it took me a long time to figure out this was why my cube was not working).
Yeh fair enough, if you started to read my attempts at explaining my code but decided you just don't care how it works you can download . Just hover over the RGB cube heading and click the link for the MK4 code.
Please reference me and my site if you use it in your own projects, it would make me a happy little vegemite.
So if you actually got to the end of the video (it's long I know), you would have seen the video input animations. I am still tossing up how much I want to give away there, so for now I will just give you some hints. I have written a linux application using the qt creator which can extract pixel data out of video files using the openCV libraries, honestly it is actually really simple compared to some of the rest of my code, everything you need can be found in the openCV documentation.
After the code gets the video's pixel data it is just a matter of scaling it to 8x8, sending it to the chipKIT and then performing some transformations to add the 3D effects to the video, easy as pi
The Finished Product!
I think I am actually done.. finally.. I hope you have all enjoyed reading this article a lot more than I enjoyed writing it :P, I can't wait to see what sort of cubes and animations some of you might create. If there are any gaping holes in the writeup chuck me an email and I will see what I can do, well I can't think of anything else at the moment so why not watch the video again, thanks for reading..
Mind = Blown
Updated Colour Wheel (March 2013)
This update is already included in the latest MK4 code
While messing about building a new cube I recently discovered that with the latest version of MPIDE the colours from my colour wheel were very washed out and shitty looking. Turns out the sin and cos function included from math.h were not spitting out the right answers. Rather than figure out the problem I decided that I would write some compiler independant functions based on sin and cos approximations. All you need to do is add two functions to the Cube.cpp class.
where DPI = 4/PI and DPI2 = 4/(PI^2) according to a clever approximation I found on the internet . Just add the following to the Cube.h file.
Finally just replace the instances of sin and cos in the fillColourWheel code with mySin and myCos, and there you haveit you should have a nice vibrant cube again. Oh and you should replace the sin and cos functions in the Spiral and Wave animations as well :)
Possible code Issues (April 2013)
I am not sure why, but for some reason my RGB LED cube code will not compile correctly in the latest MPIDE, if you are having trouble just download the 0023-20111221 version of MPIDE and everything should work just fine. I am attempting to figure this out with a shiny new cube that I have built.
New Animations! (August 2013)
A whole bunch of new animations for you to enjoy, the software has changed a lot to get to this point. They are not ready for download just yet, I am not quite sure what I am going to do with them at the moment.
New Animations are ready to download! (September 2013)
So all of those animations in the video above are now ready to download from the download page. I was a bit hesitant to give them away at first because I had spent so much time on all of them, but honestly I would have never got around to actually making any money off them (it would probably ruin all the fun anyway). All I ask is if you do end up using these somewhere on the internet please include a link to my website.
So hopefully the MK4 code (yes I have written two other versions between the original and this version) will just load onto your ChipKIT and run without any problems. My coding skills are slowly evolving so dispite there being 3 times as many animations, they should actually take up less room and no longer require modifying the heap size. There are way too many changes to list them all, what really matters is that the animations are pretty damn cool.
I am guessing that some people might want to change the order, speed or runtime of different animations, so I wrote a nice little setup file which will alow you to change these things really easily. So if you want to fiddle a bit just open up the Setup.h file.
In the file you will see an array of ANIMATION structures, these structures have a name, a runtime in seconds and a frame rate in frames/second. If you change the order of the structures in the array you will change the order the animations play, if you increase the time that animation will play for longer, if you increase the frame rate that animation will speed up... Pretty easy really.
Well enjoy your new animations!
Finishing touches (October 2013)Inspired by a very helpful commenter Xenon, who made a for his cube. I decided I had better finish my cube off with a nice stained timber base.
Page Update (March 2014)
I have made a few updates today, the MK4 code from the downloads page is hopefully now fixed and ready to go.
I have also updated this page so now all of the code referenced in the "Write Your Own Animation" section is relevant to the MK4 code with all my new animations.
Also a big thank you to all of the people helping out in the comments section, it is awesome seeing people chip in with their own improvements and advice!