Pages: [1]   Go Down
 Author Topic: 4 x 4 x 4 LED Cube with Shift Registers  (Read 2600 times) 0 Members and 1 Guest are viewing this topic.
Canberra Australia
Offline
God Member
Karma: 11
Posts: 514
Hardcore Arduino
 « on: April 08, 2013, 04:12:30 am » Bigger Smaller Reset

After having previously built a 3 x 3 x 3 LED cube and controlling it via  nine anode pins (columns) and three cathode pins (levels) - I hope that makes sense, I am now trying to design a 4 x 4 x 4 cube using two 74HC595 shift registers for the sixteen LED’s of the planes and either four transistors or a 595 / ULN2803 combination for the levels. Initially I have constructed a 4 x 4 matrix with the sixteen cathodes  in series with each other and all connected to ground and each of the sixteen SR outputs consecutively connected to the sixteen LED anodes. i.e. daisy chained.

I have been using shiftOut and trying different coding techniques to control the matrix. I have tried -
1.   one dimensional arrays with for loops
2.   two dimensional arrays
3.   bit shifting right and left through bytes
4.   declaring functions that access two dimensional arrays

I have tried having both shift registers clock, latch and data lines connected in parallel but found it too limiting as the two halves of the matrix obviously displayed the same pattern so therefore I am having them daisy chained.

I suppose I am just asking for suggestions as to how other people have approached coding when using SR’s with small cubes like this. Here is a sample of the types of coding I have been trying so far. Not very exciting I know but I’m all out of ideas. With hindsight, maybe this is not a practical way to use SR’s to control a cube, and I haven’t even thought too much about level control yet, vis-à-vis coding. Any suggestions would be greatly appreciated, Pedro.

Code:
// EXAMPLE 1

int dataPin = 8;    // connect to pin 14 of the SR
int clockPin = 12;  // connect to pin 11 of the SR
int latchPin = 11;  // connect to pin 12 of the SR
int digit[] = {B10000000,B01000000,B00100000,B00010000,B00001000,B00000100,B00000010,B00000001,};

void setup()
{
pinMode(dataPin, OUTPUT);
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
}

void loop()
{
for (int x = 0; x < 7; x++)
{
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, LSBFIRST, digit [x]);
digitalWrite(latchPin, HIGH);
delay(1000);

}
}

////////////////////////////////////////////////////////////////

// EXAMPLE 2

int pinMatrix[4][4] = {{B10000000,B01000000,B00100000,B00010000},
{B00001000,B01000100,B00100010,B00010001},
{B10000001,B01000010,B00100100,B00011000},
{B11000000,B01100110,B10011001,B00011000}};
void loop()
{
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, LSBFIRST,pinMatrix[3][2] );
digitalWrite(latchPin, HIGH);
delay(1000);

/////////////////////////////////////////////////////////////////

// EXAMPLE 3

int pinMatrix[4][4] = {{B10000000,B01000000,B00100000,B00010000},
{B00001000,B01000100,B00100010,B00010001},
{B10000001,B01000010,B00100100,B00011000},
{B11111001,B10011111,B11111111,B00000000}};

void loop()
{
inner();
delay(100);
outer();
delay(100);

}
void inner()
{
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, LSBFIRST,pinMatrix[3][2] );
digitalWrite(latchPin, HIGH);
delay(100);
}

void outer()
{
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, LSBFIRST,pinMatrix[3][3] );
digitalWrite(latchPin, HIGH);
delay(100);
}

/////////////////////////////////////////////////////////////////

// EXAMPLE 4

int digit = B10000000;

void loop()
{
for (int x = 0; x < 7; x++)
{
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, LSBFIRST, digit >> x);
digitalWrite(latchPin, HIGH);
delay(1000);

}
}
 4X4_MA~1.png (19.32 KB, 1495x1060 - viewed 180 times.) Logged

Eugene, Oregon
Offline
Sr. Member
Karma: 9
Posts: 388
 « Reply #1 on: April 08, 2013, 10:48:53 am » Bigger Smaller Reset

Thats prettymuch how I did mine. After I converted mine to use shift registers (it was originally directly connected, and only used one resistor per plane. It was very few parts, but it used all the io pins.

Converting it to shift registers mean that I went from lighting 1 led at a time, to lighting 16 LEDs at a time. which means you really need to add 4 transistors (one for each plane) to handle the current from 16 LEDs.

I think that the original program that I used was modified from a 3x3x3 code to 4x4x4 before I got it. When i upgraded the cube to use shift registers, I modified that program to use stuff from shift out.

Ive since modified that program to work on my new cube (transistor cube), but its still a bit buggy.

I've attached the program, you are welcome to do whatever you like with it. I think this version is setup for common cathode, you may need to modify a few things for it to work with your cube.

Offline
Jr. Member
Karma: 1
Posts: 60
 « Reply #2 on: April 08, 2013, 12:23:29 pm » Bigger Smaller Reset

Well, originally I was using a couple arrays for my animations as well. However I quikcly ran out of memory, so I tried the progmem function. It went a little better, but after a couple of more arrays the cube became glitchy and buggy as well. So my conclusion, you can't use any large number of arrays in the code and possibly 1 large array like hippynerd has the same problems. This is the code im using atm, it has a timer which take care of the multiplexing at a very high frequency. If you don't understand it you can always pm me.

NOTE: This code is used for a 5x5x5 LED cube, im using 6 shift register. 5 LEDs on each shift register, with a total number of 5 SR's. The 6th SR is taking care of the levels via npn transistors.

NOTE2: Once there is data in the led0 array, it will stay in there unless you clear it with zeros.

Code:
#include <SPI.h>
#define latchPin 2
#define clearPin 3
#define dataPin 11
#define clockPin 13

int shift_out;
byte cubeLevelBit[5];
byte led0[25];
int level=0;
int cubeLevel=0;
void setup(){
SPI.setBitOrder(MSBFIRST);
SPI.setDataMode(SPI_MODE0);
SPI.setClockDivider(SPI_CLOCK_DIV2);
noInterrupts();
TCCR1B = 10;
TIMSK1 = 2;
OCR1A= 30;
pinMode(latchPin, OUTPUT);
pinMode(dataPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(clearPin, OUTPUT);
cubeLevelBit[0]=1; //level 1/5
cubeLevelBit[1]=2; //level 2/5
cubeLevelBit[2]=4; //level 3/5
cubeLevelBit[3]=8; //level 4/5
cubeLevelBit[4]=16;//level 5/5
SPI.begin();
interrupts();
}

void loop(){
//led(which level the led is located, which row the led is located, which column the led is located);
led(4,1,2);
}

void led(int level, int row, int column){
if(level<0)
level=0;
if(level>4)
level=4;
if(row<0)
row=0;
if(row>4)
row=4;
if(column<0)
column=0;
if(column>4)
column=4;
int Byte = (((level*25)+(row*5)+column)/5);
int ledByte=(level*25)+(row*5)+column;
bitWrite(led0[Byte], ledByte-(5*Byte), 1);
}
ISR(TIMER1_COMPA_vect){ // MULTIPLEXER
PORTD |= 1<<clearPin;
SPI.transfer(cubeLevelBit[cubeLevel]); // i got
for(shift_out=level; shift_out<level+5; shift_out++)
SPI.transfer(led0[shift_out]);
PORTD |= 1<<latchPin; //direct pin acces, its faster then digitalWrite
PORTD &= 0<<latchPin;
PORTD &= 0<<clearPin;
cubeLevel++;
level = level+5;
if(cubeLevel==5)
cubeLevel=0;
if(level==25)
level=0;
}
 « Last Edit: April 08, 2013, 12:26:30 pm by WonderTiger » Logged

Canberra Australia
Offline
God Member
Karma: 11
Posts: 514
Hardcore Arduino
 « Reply #3 on: April 08, 2013, 03:02:15 pm » Bigger Smaller Reset

Thank you for replying Hippynerd and WonderTiger. I will have a look through both your codes and see what I can pick up from them.
Interesting to see your use of direct port manipulation WonderTiger. Thanks again to both of you.
 Logged

Offline
Full Member
Karma: 1
Posts: 135
 « Reply #4 on: April 08, 2013, 08:41:09 pm » Bigger Smaller Reset

If you are not looking to change brightness of each LED individually, you can use MAX7219, but this will limit your design in the future if you decide to do that.
 Logged

Search for "mjkzz" on eBay :-)

Canberra Australia
Offline
God Member
Karma: 11
Posts: 514
Hardcore Arduino
 « Reply #5 on: April 08, 2013, 08:52:40 pm » Bigger Smaller Reset

Thanks mkjzz,
yes I have played around with Max7219 and 8 x 8 matrices, but I would have a good long hard think about how to use them for a cube, but well worth thinking about, thanks for your suggestion
Pedro.
 « Last Edit: April 08, 2013, 08:58:51 pm by Pedro147 » Logged

Global Moderator
Boston area, metrowest
Offline
Brattain Member
Karma: 525
Posts: 26569
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
 « Reply #6 on: April 08, 2013, 11:21:28 pm » Bigger Smaller Reset

MAX7219 would be a neat trick for 4x4x4 cube. Perhaps wire 1/2 of each plane as a digit.
 Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Offline
Jr. Member
Karma: 1
Posts: 60
 « Reply #7 on: April 09, 2013, 02:07:55 am » Bigger Smaller Reset

Well you can also adjust the brightness via my given code. The code I gave you was a bit easier (because its easier to understand without the brightness control)then Im using, because I can also change the brightness of the leds(in the first 5 seconds I use brightness control to let my cube flash): https://www.youtube.com/watch?v=_mEOX-k7gy4&feature=youtube_gdata_player
 Logged

Valencia, Spain
Offline
Karma: 144
Posts: 5378
 « Reply #8 on: April 09, 2013, 04:08:53 am » Bigger Smaller Reset

MAX7219 would be a neat trick for 4x4x4 cube. Perhaps wire 1/2 of each plane as a digit.

In theory it could drive all the LEDs in the cube, the wiring would be tricky though.

 Logged

No, I don't answer questions sent in private messages (but I do accept thank-you notes...)

Canberra Australia
Offline
God Member
Karma: 11
Posts: 514
Hardcore Arduino
 « Reply #9 on: April 09, 2013, 07:41:25 am » Bigger Smaller Reset

I have been having a goggle, and I found this 4 x 4 x 4 LED cube using a picaxe microcontroller. I'm not sure if this could be adopted to Arduino but it looks interesting. Anybody up for a conversion

 Logged

Offline
Full Member
Karma: 1
Posts: 135
 « Reply #10 on: April 09, 2013, 09:56:44 am » Bigger Smaller Reset

I have been having a goggle, and I found this 4 x 4 x 4 LED cube using a picaxe microcontroller. I'm not sure if this could be adopted to Arduino but it looks interesting. Anybody up for a conversion

That is cool!

If we think of 4x4x4 as 64 LEDs and think in rows and columns, build a layer of abstraction in software that turns rows and columns into x, y, z, we might have something going :-)

Then, from 4x4x4 as building block, we can build a much more complicated cubes, or something like 4x4x8, etc.
 Logged

Search for "mjkzz" on eBay :-)

Eugene, Oregon
Offline
Sr. Member
Karma: 9
Posts: 388
 « Reply #11 on: April 09, 2013, 10:08:34 am » Bigger Smaller Reset

I couldnt download the schematic to see how that cube is built, but from the description, it sounds like how most cubes are made in planar fashion, but each plane is split in half (8 groups of 8 LEDs).

Its not as hard to build as you might think. My transistor cube breaks up plane into 4 lines, if you did the same thing, only connected 2 lines together on each side, you have the same thing as he is describing (2 lines of 4 LEDs is 1/2 plane).

In the picture below you can see 16 LEDs that are made up of 4 lines of 4 LEDs. 4 of these make one 4x4x4 cube. Im using RGB LEDs, but you could do the same thing with single color LEDs.

If you connect 2 of these lines together, you make 1/2 plane. You could connect them horizontally, or vertically, either way should work.
 Logged

Offline
Full Member
Karma: 1
Posts: 135
 « Reply #12 on: April 09, 2013, 10:25:02 am » Bigger Smaller Reset

Come to think of it, if MAX7219 is used, each plane needs 10 wires, 8 for anodes, 2 for common cathodes. For next plane, the 8 anodes wire can be wired together, only the 2 common cathode wires need to be separate.

So maybe wiring isn't that bad at all . . . no resistors, 7 more of it, we got a 8x8x8 cube with 8 MAX7219s
 Logged

Search for "mjkzz" on eBay :-)

Global Moderator
Boston area, metrowest
Offline
Brattain Member
Karma: 525
Posts: 26569
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
 « Reply #13 on: April 09, 2013, 12:41:56 pm » Bigger Smaller Reset

Exactly. Just need each 4x4x4 seperated electrically from the others.
 Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

 Pages: [1]   Go Up