Doug's Workshop

8 x 8 x 8 RGB Qube Software

Supplementary Instructions

This is where I am storing miscellaneous instuctions and helpful hints:

1. I just learned something that may be helpful to anyone programming a cube with the ChipKit UNO32.

Programming cubes usually involves tables. And to keep them from using up precious RAM space, we Arduino programmers use PROGMEM. The IDE for ChipKit allows you to use PROGMEM to store data in program memory - just like Arduino. But then when you go to use that data, ChipKit pulls it into RAM. Sometimes, as in the case with my font table, the table can be huge. Arduino doesn't pull anything stored in program memory into RAM.

So it seems ChipKit has a problem. But not really. When you define data as const (constant) in Chipkit, it is automatically put in program memory. And it stays there - it's never pulled into RAM. With Arduino, data is always stored in RAM, so even const data is stored in RAM - const just tells the compiler to generate an error if you try to change it. Hence the need for PROGMEM.

So bottom line, for ChipKit, to keep stuff from ever using RAM, just define data as "const"! And we never have to worry about PROGMEM ever again. So Versions 3.7 and 4.4 (and all subsequent versions) have been updated to remove all references to PROGMEM and replace them with const data, and replace the "pgm_read_byte_near(& " expressions used with PROGMEM with direct references to that data.


2. If you are try putting a lot of content on the chipKit UNO32, chances are you will run out of RAM (16K bytes available) before you run out of Flash memory (128K bytes) for program storage. If you do run out of RAM, it may or may not be caught by the compiler. If not, you will just start getting very unpretictable results.

The secret to never running out of RAM is to manage it properly. The C+ language does a great job of disposing of variables when no longer needed, and it does this pretty much automatically. Cube software uses lots of big tables, and as soon as you have a bunch of them in play at the same time, you run the risk of using up all the RAM. For example, the table that stores the current content of the cube takes up 1536 bytes of RAM. It is used by everything, so it must be a global variable and never gets disposed of or available to reuse. But most of your other tables that are relevant to a single animation can be set up locally. Just create them inside a subroutine, and they will be automatically be disposed of when that subroutine is exited, freeing up that RAM space for reuse.

I haven't always been diligent about proper disposing of variables in my own software, but I have gotten better at it as I have programmed more. With reasonable attention paid to keeping your variables local and disposable, you should never run out of RAM! A good example of minimizing RAM usage is the CubeInCube animation in Version 7. In this example we have a bunch of different sprite objects running, but we never allow them to exist simultaniously. They are each in their own subroutine.


3. In Version 6, we introduced the sprite object class with a max sprite size of 4x4x4. These sprite objects use a 4x4x4 matrix called description to define the color of each LED in the sprite. In addition, each sprite uses another 4x4x4 buffer matrix for rotating it. So each sprite object uses a total of 128 bytes of RAM. That's independent of the actual sprite size, as C++ doesn't allow the size of a variable to be defined by another variable.

Now in Version 7, we increased the max size to 6x6x6, so now each sprite object uses 432 bytes of RAM. This has the effect of limiting the number of sprites that can exist at the same time to about 8, simply because of all the other demands for RAM in our cube programming. I am bringing this up because, while the compiler sometimes detects and generates an error when you try to use more RAM than is available, it does not catch it in this particular case. Program execution simply fails with no explaination! So, be forwarned - don't try to have more than 8 sprites existing at one time in Version 7.


4. The last three items were about memory management. This is a totally different subject. Let's talk about creating your own animations in general. How do you go about it?

You need to start out with a vision of something you would like to see in your cube. The better you can define it, the easier your coding will go. So don't be in a rush to start writing code. Think about the animation conceptually for a while. How is it going to start? How is it going to end? What is the cool thing that is going to make this animation eye-catching and stunning?

Writing the actual code may be very difficult, but it definitely gets easier with practice. Knowing all the tools that are available in my templates makes it much easier. If I have carefully considered what I want to do, I can write the code and have a starting point to look at in a half hour or less.

Where the real work comes is fine tuning your animation after you have something working. This can not only take several hours, but may take place over several days. I typically experiment with the timing a lot. It is not just how fast do I want my animation to run. The human eye can perceive about 25 images per second. But if too much is changing from one image to the next, our brain can't process it all, and it uses all kinds of tricks to deal with the flood of information. So to get the finished result you are looking for, you may have to play around with the timing through many iterations. I typically work on a new animation until I like it, then wait awhile. I might come back after a couple of days and look at it again. Then I usually end up making more changes!

You won't see it on this website until I'm convinced it's as good as its going to get. And that doesn't always happen. Frequently, I end up tossing a new animation in the trash, because no matter how much I fiddle with it, it just doesn't make the grade!