algorithm Arduino hardware software

Device Independent Control for LED Cubes

LED Cube 8x8x8

LED cubes are fascinating. The allure of blinking LEDs in various patterns is always attractive and mesmerizing. Like many Arduino fans there came a point when I decided I would try my hand at one (or two, as it turned out).

Whilst they look complex, they are, in principle, relatively straightforward from an electronics and software perspective. Making the cube can be challenging, but by using jigs and patience, this becomes more of a chore than a challenge!

As part of this learning exercise, I wanted to move away from the ‘bit-twiddling’ code that seems to drive many cubes, to a device-independent software library that could be programmed in cartesian (XYZ) coordinates. This way the same code could be used to drive many different cubes with no change at the user code end of things.

After doing some research I concluded are 2 main types of LED cube architectures:

  • A scanning/refresh model, where the LEDs are refreshed by the Arduino at a rate fast enough to activate a persistence of vision effect. This puts the onus of multiplexing control in the Arduino software. An example of this type hardware is the ICStation Light Cube Kit, based on 74HC595 shift registers to control LED anodes and 4 I/O ports of Arduino control 4 common cathodes of LED. This type of hardware is the most common for LED cubes and relies on the microcontroller software opening a circuit (a path for current) for each LED in very quick succession.
  • A ‘set and forget’ model, where each LED is set by the Arduino and some other hardware components ensure that they remain turned on or off. One example is a DIY version from this Arduino forum post. This cube uses a MAX7219 LED controller to drive the 64 LEDs in the cube. Refreshing the LEDs is therefore handled by the 7219, with the Arduino periodically writing new settings through the interface registers.

The software must take into account these differences and allow both to work using the same basic software pattern.

Some additional analysis and experimentation resulted in a very small set of primitives that need to be implemented to handle the differences. The final library tested with these two 4x4x4 and the JolliCube 8x8x8 cube architectures can be found here.

Basically the hardware dependent code needs to do the following:

  1. Initialise the hardware. This will clearly be different for the different hardware types. In the library this is implemented in the begin() method.
  2. Turn a LED on/off. This is THE basic function for the cube and is implemented in the setVoxel() method. Every other drawing function – clear(), drawLine(), fillPlane() –  can be written using setVoxel(). The function also needs to be able to map between coordinate and a physical LED, often in a non-linear manner.
  3. Update the cube. Implemented in the update() method, this allows the internal buffers to be copied to the cube display, allowing for crisp animations and controlled updates, as all the changes accumulated since the previous update are shown at once.
  4. Animate the cube. This is the animate() method called in between updates to allow refreshing in multiplexed cubes. For ‘set and forget’ cubes, this method is ignored.

Using the extensibility inherent in C++ class inheritance makes it a breeze to create hardware specific functionality around a common core class.

So there it is. It is possible to create device independent code to run a cube. In principle, this library is also extensible to cubes of any size. Mission accomplished!

Update: See also this additional article

3 replies on “Device Independent Control for LED Cubes”

Impressive Work! Just checked out your github repo and flashed that onto my icstation cube, works really well with the demos. I am currently tinkering with the library to implement a snake pattern on the cube and the coordinates are just so much nice to use than the usual bit patterns 😉



[…] Full code for my icstation4x4x4 included below.  Note: This is not written to be particularly good code (I don’t use portable definitions for 16-bit values, and there is minimal error checking, etc – this is just my hacking about, not meant for real use anywhere – I might tidy I up one day – maybe).  If you want to do it all properly, I suggest you take a look at the rather fine library described here: […]


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s