8x8x8 multiplexed LED cube with an Arduino Mega 2560

Thank you for this information! :slight_smile:

I have found another article somewhere (Arduino Playground - MAX72XXHardware) which seems to confirm what you just mentioned:

  • Parallel the CLK and CS(Load) for all the MAX7219 chips (I guess we also call these two SLK and SS)
  • Take the DOUT from one chip to the DLN of the next chip

And using just 3 wires to communicate with the whole thing? Wow, that's impressive!

There's one thing I'm not sure I understand in your explanation about how to program the whole batch of chips. You say that if I send packages of 16 bits multiple times, the bits are pushed from the nearest chip to the next one every time a new package is sent while SS is kept low. This is clear and wonderful. But you also wrote "Then you latch and that row gets committed". What does it mean to latch?
Sorry if I ask such beginner questions, but as I wrote, my knowledge in this area is merely starting to develop and I'm having a hard time understanding some of the basics...

As for how to divide the cube into layers, I guess you are right, it doesn't really matter that much, the software can handle it either way.

I don't really where to buy the MAX7219 chips from. As I wrote earlier, I found them on eBay, where you can buy 10 pieces for 5$. That would be nice, but I've read that they are not original and that must be true because Maxim is selling them for a lot more. I've also checked them in a local electronics parts store and here I could buy original ones, 10 pieces for 40$... I wonder if it's worth buying the original ones...

Thank you!

I've juts realized that the fact that driving the LEDs with MAX7219 chips in such a simple and elegant fashion has a price to be paid during construction of the LED cube. If I drive each horizontal plane of 8x8 LEDs with one MAX7219, I'll need to have 16 wires go to each horizontal plane, I no longer have the advantage of connecting the vertical legs of each column together and sending signals through that... It's going to get ugly... :frowning:

Un4Seen:
But you also wrote "Then you latch and that row gets committed". What does it mean to latch?

When you bring CS (chip select) high the data is latched. That is, it is transferred from internal holding registers to the actual chip outputs, connected to the LEDs. Until it is latched you don't see it, so you don't notice the data being pushed from one chip to the next one, it is all internal.

Un4Seen:
If I drive each horizontal plane of 8x8 LEDs with one MAX7219, I'll need to have 16 wires go to each horizontal plane, I no longer have the advantage of connecting the vertical legs of each column together and sending signals through that... It's going to get ugly... :frowning:

I don't see how you can individually control 64 LEDs with less than 16 wires unless you use Charliplexing maybe, but that could be a bit difficult for 512 LEDs. Plus you need the 512 resistors then.

On this diagram for the 8x8 LED:

On the right, notice how 8 anodes are connected together and 8 cathodes? It will be tedious wiring 512 LEDs whatever way you look at it, but only 16 wires isn't too bad.

So why not stick with your original plan:
64 cathode drivers, and 8 anode drivers.
Can be done with 9 TPIC6B595 shift registers and 8 PNP or p-channel MOSFETs.
8 of the 6B595's will drive the cathodes.
Each bit of the 9th 6B595 will be used to pull the Base/Gate of the Anode transistor low to turn the part on, pullup resistor pulls it high to turn it off.
83 cents each at avnet.com
Have to play with the timing, see if 9 SPI transfers will do it, or if need to turn the anode off, drive the cathodes, and then turn the next anode on to prevent ghosting. 9 SPI tranfers or 11, quick either way.
Lots of time available while watching millis() go by to update the 64 bytes that hold the array information.

This board I sell will hold all the shift registers, you can not populate the '328 part of it and feed in your SPI controls signals from your Mega if you wanted to.
They're all daisy chained, so you couldn't easily split the transistor driver from the other drives.

I used 2 of them, 10 shift registers each card, just passing power and the control signals along to the 2nd card, to drive this 5x20 display with no multiplexing:

Thank you again for your replies!

Nick Gammon, in a theoretical sense you are right that 16 wires to drive 64 LEDs is pretty good. However, the LED cube is all about being able to see through it, about being elegant, about not seeing wires... I was thinking that I could cheat out half of the wires by dividing the cube not into horizontal, but vertical planes. Each MAX7219 would drive a vertical plane. This way 8 legs (all anodes or all cathodes) would go directly into the PCB beneath the cube, so only an additional 8 wires would have to crawl up along the edges of the plane. Dividing it equally, I could manage with 4+4 wires. Maybe I can buy some very thin wires and it would look nice. I wonder how thin is not too thin. I'm thinking that the resistance of the wires might matter...

CrossRoads, your idea is also tempting because I could create a cleaner (wire-free) and more robust cube. It also has the advantage that the cube would be made only by soldering LED legs together, as opposed to the MAX7219-based solution where I would have to find a way to make the cube more rigid by adding some non-conducting sticks between the planes, to hold them together. That would probably mean glueing.
What did you mean by "Lots of time available while watching millis() go by to update the 64 bytes that hold the array information." Were you suggesting that in the MAX7219-based approach needs a lot of time to fill up the registers?

You also wrote this:
"64 cathode drivers, and 8 anode drivers.
Can be done with 9 TPIC6B595 shift registers and 8 PNP or p-channel MOSFETs.
8 of the 6B595's will drive the cathodes.
Each bit of the 9th 6B595 will be used to pull the Base/Gate of the Anode transistor low to turn the part on, pullup resistor pulls it high to turn it off."
Is there a place I could find an exact wiring diagram for this? What about an example on how to program it?

As I wrote, I really am an amateur with high aspirations (the 8x8x8 LED cube). I'm struggling really hard to understand the answers you guys give me :slight_smile: Because of this the MAX7219-based solution is more appealing to me. The chip takes care of LED currents, of multiplexing the LEDs. Also less components, less room for error. The only two problems with it are the price and the wires that would make the cube look less aesthetic... Because of this I'd like to try to understand the other solution too, with TPIC6B595 shift registers, but I need some diagrams and some programming example to see if I can work with it.

I really do appreciate your answers. Thank you!
Andras

How's this for a start?

It looks understandable enough :slight_smile: Thank you!
A few questions, though:

  1. The micro controller on the left would be an Arduino. How would that be connected to the TPIC6B595s? Which Arduino pin would be connected to which pin of the shift registers?
  2. For the 64 coulmns 8 pieces of TPIC6B595 are needed. In your diagram I see that pin 18 of each shift register goes to the next shift register. But to which pin of the next shift register?
  3. Which input pins of the TPIC6B595s would be used and how exactly (how would they be connected to the Arduino and how would the 8 column driving shift registers be connected to each other) (In a sense this extends question 2).
  4. For the 8 layers I would need 8 transistors. If I understand correctly, this is the part of the circuit which decouples the low currents used to get signals from the Arduino to the LEDs from the high currents that actually pass through the LEDs. You wrote above the diagram that each transistor must be able to handle 6420 mA (makes sense as it switches 64 LEDs in a layer). Is there some packaged chip like the ULN2809 for example which could handle the whole cube (I mean that it contains 8 transistors, each capable of handling 6420 mA)? If not what kind of transistor can do the job?
  5. These shift registers don't do multiplexing. Does this mean that the multiplexing will have to be done from software?
  6. How would you switch LEDs on/off with this hardware approach? How would you send data to the shift registers?

Thank you!
Andras

I'm wondering about what 5V power supply to get for powering the cube...
What would be the maximum current consumption of the two solutions when all the LEDs are turned on at full brightness (assuming we give each LED 20 mA of current)?

With the MAX7219 I saw something in the datasheet that it consumes 330 mA, but I wonder if that includes the current consumption of the 64 LEDs it drives or it consumes 330 mA by itself...

Any useful tips regarding the power supply?

Thanks,
Andras

1,2, 3: Yes, an Arduino. Connections would be via SPI as I previously described.
Specifically: D13/SCK to SRCK on all chips
D11/MOSI to SerDataIn on 1st chip, then SerOut goes to SerDataIn down the chain
D10/SS to RCK on all chips
SerClr/ to +5 on all chips
OE/ to Gnd on all chips. You could also experiment with connecting to a PWM output for dimming.
4. 64 * 20mA = 1.28A. I don't know of a PNP equivalent to ULN2803 that can do this.
I would suggest a P-channel MOSFET such as this

I also realize some resistors are missing. See corrected shematic below.
5. Yes, software does the multiplexing as I described earlier; one layer's transistor is turned on at a time while the cathodes are pulled low for on, and not for off.
Having each layer on for 4mS would yield about a 30Hz refresh rate. Better results may be seen if the transistor shift register is seperately written from the cathode shift register, have to experiment some & see.
6. I would keep the image of the cube in a 64 byte array, writing out 8 bytes at a time for a layer using SPI.

Cube would use 1.28A if a layer was turned full on at 20mA. 5V, 2A supply would be sufficient
http://www.dipmicro.com/store/DCA-0520

I suppose one could also use 4x TLC5940 or 4XWS2803 for the cathodes, and have PWM capability per channel. Have to send out more data tho, at least a full byte per column for 256 level brightness control. Vs just 8 bytes per layer & on/off only.

MAX7219, controls both the anodes & cathode, haven't thought of a way to multiplex that. Would think something like 8 transistors between MAX7219 and the anodes, or cathodes, of each layer to be able to isolate the control for that layer? Then have to control turning layers on/off in software and writing out data for each layer in software.

A lot clearer now. Thank you!
What is the role of those resistors that you have newly added and what would their value be?

Now that I think I'm very close to fully understanding both the TPIC6B595-based solution and the MAX7219-based solution I'm trying to evaluate the advantages and disadvantages of both:

  1. The TPIC6B595 solution would only require a 2A power supply because the total theoretical current consumption is only 1.28A. The MAX7219-based solution needs at least 8x330 mA (2.64 A), so I'd probably need at least a 3A power supply, which are harder to come by.
  2. The TPIC6B595 solution has cosiderably more components, it's easier to make a mistake and the software multiplexing must be bulletproof, otherwise it could accidentally turn on all layers, leading to a current consumption of 8x1.28 A. Software multiplexing would of course complicate the code in unnecessary ways, compared to the MAX7219 solution which only needs the bytes to be sent via SPI.
  3. The MAX7219 solution is expensive, the TPIC6B595 is magnitudes cheaper.
  4. The MAX7219 solution requires some additional wires to crawl up to all LED planes, making the construction a bit uglier, but I could come around that by putting the wires into two sets of 8 additional columns in the cube (with no LEDs, just wires). MAybe it would look acceptable. The TPIC6B595 solution solves this problem in a natural way by allowing the current to travel up the cathodes of the LEDs soldered together in 64 distinct columns.
  5. The MAX7219 solution would make it easier to solder the LEDs together because the 8 distinct levels (planes) would need no contact. I could just add some non-conducting sticks in the end among these 8 distinct planes to make the structure more robust. For the TPIC6B595 solution, on the other hand, it's needed to solder all the LEDs together (cathodes to cathodes in 64 unconnected columns and anodes to anodes in 8 unconnected planes). Makes the soldering trickier.

Are there any other pros/cons for these two solutions that I don't see?

Thank you!
Andras

I disagree with many of your assumptioms.

  1. MAX7219 multiplexes 64 digits. It has no more than 8 LEDs on at a time, thus not much more than 160mA if 20mA/LED is being used.
    Additionally, 5V/4A supply is easy to find - I use this one in several projects
    5V 4A Power Adapter OPENPEAK OP-20004
    For my 8x32 display using 4 of MAX7219 and a Duemilanove, a 9V, 1A supply was used, drawing under 1A of power as all 5V current went thru the onboard regulator.
  2. More components, yes, but easier to assemble LED cube as all columns are connected, and all Layers are connected, thus just 8 wires need to be hidden away. With non-multiplexed MAX7219, need isolated layers and 16 wires per layer.
  3. MAX7219 is $1.25/chip from taydaelectronics.com. TPIC6B595 is 83 cents from avnet.com, plus PNP or P-channel MOSFETS. Seems comparable when totalled.
  4. Agree with you on wiring. Don't know how you solve the cube stability while maintaining layer isolation.
  5. There are many examples of LEDs cubes. The soldering together is less tricky than you think, there is just a lot of it. Here is one of the best writeups I have seen.
    http://www.jameco.com/Jameco/workshop/JamecoBuilds/4x4x4ledcube.html

That bobduino thing looks pretty cool. I've also seen a similar thing that was just shift registers, I think it was 8 of them, I cant remember for sure.

I have been working on documentation for 3 different RGB LED cubes, they all controll 64 RGB LEDs, but they do it 3 different ways.

I still have a lot of work to go, I have one cube up, and details about how what wires to use, how to prep them, and why.

I really think the split is a bad idea, It will require some kind of non-conductive structure in between. I dont see any good way to do this, it will only make things harder, and I think the results will be less than desirable.

I have seen carbon fiber tubes and plastic stuff at the hobby store, if you really must try some kind of non-conductive alternative, you might find something there. What you will find there is something called music wire, its hardened steel wire, and is very very stiff. Its harder than hell to solder too, but it provides a really sturdy structure, that will flex a bit, instead of bending and kinking. You can get very thin wire, that is stronger than bailing wire, and much much thinner, and harder to see.

You should really learn about Serial communication, like I mentioned in my other post. Transmitting the data (64 bits per plane most likely) Since you do not have 64 pins available, there is no way to do that with parallel, so you will need serial, there is no doubt (unless you were willing to entertain charlieplexing...) Since you are forced into serial, you really wont need a mega, but it has more memory, so that will be useful, but you really only need a few pins to do serial data transfer. Since you have so many pins available, you may elect to use one pin per plane, and 3 pins to serialize your data through. Since you will be doing some form of serial, you have lots of options, shift registers, LED drivers, you could even do a ton of resistors and transistors. Drivers come with a lot of different features, I've tried get my head around what things are important, and its confusing.

If you go with a constant current driver, like the TLC 5940, you can do it with 4 chips (each chip is 16 bit, and does PWM), You will need to source current to each plane, as the TLC chips are sink only, no sourcing.

If you use shift registers, the nice thing about them is that they can sink or source, so you could source using a shift register, and sink with something else. The downside is that they dont control the current, so the will need resistors.

Multiplexing chips probably wont work for you.

I havnt finished my higher power cubes, but you will need to sink or source current to your planes, I've done a little reading and it seems there are 2 common ways to do that, darlingtons or mosfets. Mosfets are preferred as they seem to be more efficient, especially when not being used (and your mosfets would only be used 1/8 of the time).

The current website im working on is about RGB charlieplexing cube, but you will find some useful info about building cubes in there. I would strongly suggest building a couple small structures with just a few parts, and actually complete something so you understand all the steps before you try to design your own process.

The most realistic way I can see building this cube is 8x64 setup, and common anode(planes) is the most versatile way, since you could use shift registers or constant current drivers.

Thank you again for your help, guys!

I'm thinking and thinking an thinking about which approach to take, but it seems that the more I know, the more confused I get :slight_smile:

I must admit, the solution that appeals to me most at this time is to have 8 separate, unconnected layers, each driven by a MAX7219. It seems that the current consumption is not so bad after all and I'm hoping that the ones I can find on ebay (10 pcs for 5$) will do the job. I would not divide the LEDs into 8 layers the conventional way though. Instead of having the usual 8 horizontal layers, I'd have 8 vertical layers. This has several advantages:

  1. Having 8 layers driven each by a MAX7219 requires 8x16 wires. Half of these would be connected to the layers directly from the bottom of the cube (because the layers would be placed such way that half of the required wires would face the bottom). This means that only 64 wires would be visible. These could enter the cube from the back of it (the side which is away from the viewer). Could still be messy...
  2. By having these vertical plane layers, the weight of each layer would stand on the bottom 8 LEDs, so I would have to add just a few non-conducting sticks to strengthen the cube, maybe just at the top and around the middle, not everywhere. I'm not sure if this would look nice because the cube would be more transparent or it would look weird...

I guess the main reason why I'm trying to convince myself that the MAX7219-based solution is best is because it's the simplest from more than one perspective:
A. Less components to solder in the circuit.
B. Takes care of LED currents and even can be used to set brightness from software easily.
C. The software does not need to be aware of the multiplexing, the Max chips do it themselves.

Searching the Internet I have found that somebody has actually pulled it off with this Max7219-based solution applied to a 8x8x8 LED cube (http://hackedgadgets.com/2011/09/02/8x8x8-led-cube-powered-by-an-arduino/). Unfortunately, I must say that the result is not nice at all. I mean, I do respect his work, but let's face it, the usual LED cubes that we see are much more better looking. Those wooden sticks at the corners of the cube block the vision a lot and those wires at the back are just plain ugly. I'd hate to turn up with a result like that after who knows how many hours of work.

I've never thought it would be so hard to build a LED cube. There are solutions for every problem related to it, but none of the solutions is "perfect". You can only get some benefits by sacrificing others...
I'll try to think of solutions to go for the MAX7219-based solution and to get rid of the ugly wires and to solve the problem of non-conducting sticks between the layers. As much as I realize that most of the cube out there don't use this solution because of the disadvantages I have just enumerated, I don't dare to try the other solution. It just has too much room for error both in building the circuit and in the software part which gets more complicated by having to implement multiplexing. Also it's less foolproof. If the software messes up the multiplexing and lights up all the 512 LEDs, I don't know what's going to happen...

Like I said, the more I think of it, the scarier it gets... :slight_smile:

Back to the TPIC6B595... CrossRoads, you laid it out so nicely for me, I just hate to waste that information, so I'm back to it again :slight_smile: Looking at the diagram, the following additional questions have come up:

  1. Should all GNDs be connected together (The GND of the Arduino, the GDN of the TPIC6B595s, etc.)?
  2. What kind of resistors should be used?
  3. What kind of capacitors should be used?
  4. You recommended NDP6020P MOSFETS for the transistors. In their datasheet the leggs of the NDP6020P are marked G,D,S. Which of these leggs go where in the diagram?
  5. You wrote that if the software multiplexing turned each layer on for 4ms, it would lead to a refresh rate of 30 fps. Do you think that's good enough for the human eye?
  6. You wrote that dimming could be achieved by connecting to PWM pins on the Arduino. But connecting what to the PWM pins?

Sorry if I'm asking the obvious again...

"If the software messes up the multiplexing and lights up all the 512 LEDs, I don't know what's going to happen..."
Nothing. Any COTS switching power supply will just shutdown as it sees an overcurrent situation occurring, same as if you shorted the output.

Your latest questions:
Resistors = inexpensive resistors, 1/8W, carbon composition. Value will depend on the LED color & the current you want to put thru them.
If have a 5V source, and the anode transistor has 0.45V across it, and the cathode shif register has 0.25V across it, that leaves the remaining voltage across the LED and the resistor.
For and LED with Vf of 3.2V way, and using 20mA as the current, then:
(5V - .45 - .2v - 3.2)/.02 = 55 ohm. 56 ohm is a standard value.

For the transistors, the base/gate resistor from the shift register is probably not needed (no need to limit current into the shift register, that will be set by the pullup resistor), and the pullup resistor can be smallish, say 220 ohm.

Caps are just 16/25/50V 0.1uF caps. I use these a lot
http://www.dipmicro.com/store/C5K10-50

P-channel MOSFET -
Gate connects to the shift register
Source connects to +5
Drain connects to the LEDs
(odd naming, I know).

30Hz - Movies were only 24 Hz for the longest time, and TV was 30 Hz. Good enough?

PWM connected to OE/ on the shift registers could be used for dimming. I would connect to the cathode shift registers where there is less current flow.

You are making too much of the "multiplexing complexity" I think.

// some stuff you need anyway
# include<SPI.h>
unsigned long currentmillis();  // millis() and micros() are type unsigned long, 0x00000000 to 0xFFFFFFFF
unsigned long previousmillis();
unsigned long duration = 4;  // time in mS to display each digit
// declare other variables, and 2 arrays, one to hold the anode bit selection, one to hold the 64 bytes of the array

void setup(){
// do all the setup stuff, pinModes & stuff.
SPI.begin();
};

void loop(){
// start the multiplexing:
currentmillis = millis();  // capture the "time"
if ( (currentmillis - previousmillis)>=duration){  // 4 mS gone by yet?
previousmillis = previousmillis  + duration;  // set for next time check

x=x+1;  // break down anode for:next loop so it can run within the time check
if (x==8){
x=0;  // reset  after passing 7
}
// turn off existing anode (see note below)
digitalWrite(anodeSS, LOW);
SPI.transfer(0xFF);  // all 1s so no MOSFET is on
digitalWrite(anodeSS, HIGH);

// set up cathodes
digitalWrite (cathodeSS, LOW);
for (y=0; y<8; y=y+1){
SPI.transfer(dataArray[(x*8)+y]); // so 0-7, then 8-15, 16-23, etc., up to 55-63
}
// (perhaps ditch earlier anode write & pull later one back to here, so all shift registers are updated together with one SS pin?)

digitalWrite (cathodeSS, HIGH);

// now turn on one anode (see note above)
digitalWrite(anodeSS, LOW);
SPI.transfer(anodeArray[x]);  // Array holds B00000001,  B00000010,  B00000100, B00001000, B00010000, B00100000, B0100000, B10000000
digitalWrite(anodeSS, HIGH);  // with high = output pulled low

} // end time check

// do other stuff if desired while waiting for next time check, like receive serial data, update dataArray contents, etc
} // end void loop

This may need a little tweaking, but that's basically it.
I used seperate SS for the Anode vs the Cathodes, it may be that you can string them all together with one SS, have to play some and see which looks better.

Yes, all GNDs get connected.

CrossRoads, doesn't your circuit require 16 wires per 64 LEDs? So the number of wires in the cube is the same as using the MAX7219? Or have I misread it?

The only way I can think of reducing the required number of wires to less than 16 is to use Charliplexing:

However that is quite complex. Also you still need 9 wires to control 64 LEDs (only a small saving).

For n pins, you can have up to n(n-1) LEDs in the matrix. Any LED can be lit by applying 5 V and 0 V to its corresponding pins and setting all of the other pins connected to the matrix to input mode.

I think you are misreading the partial schematic.
Each common anode layer needs 1 wire.
The common cathodes need 64 wires, 1 per column, usually soldered to the PCB that makes the base of the cube.
72 wires total.
Vs 8 x 16 wires = 128, and connectivity not built into the array either. See the video that was posted in Reply #21.

Wish I had way more hours in a day to build one of these up.
I'd go for 9x9, have read having the center LED to pivot things around makes it look neater.
My 12-shift register board could drive it, be a bit of a software PITA spreading 81 bits + 9 anode control bits across 12 8-bit registers (96 bits).