Go Down

Topic: 4 x 4 x 4 LED Cube with Shift Registers (Read 3341 times) previous topic - next topic

Pedro147

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: [Select]
// 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);
       
      }
  }

http://www.pedroduino.com

Hippynerd

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.
https://sites.google.com/site/rgbledcubes

WonderTiger

#2
Apr 08, 2013, 07:23 pm Last Edit: Apr 08, 2013, 07:26 pm by WonderTiger Reason: 1
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: [Select]
#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;
}

Pedro147

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.
http://www.pedroduino.com

mjkzz

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.
Search for "mjkzz" on eBay :-)

Pedro147

#5
Apr 09, 2013, 03:52 am Last Edit: Apr 09, 2013, 03:58 am by Pedro147 Reason: 1
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.
http://www.pedroduino.com

CrossRoads

MAX7219 would be a neat trick for 4x4x4 cube. Perhaps wire 1/2 of each plane as a digit.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

WonderTiger

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

fungus


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.

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

Pedro147

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  8)

http://www.picaxeforum.co.uk/showthread.php?22115-4x4x4-LED-Cube-using-08M2-and-MAX7219&highlight=led+cube
http://www.pedroduino.com

mjkzz


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  8)

http://www.picaxeforum.co.uk/showthread.php?22115-4x4x4-LED-Cube-using-08M2-and-MAX7219&highlight=led+cube


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.
Search for "mjkzz" on eBay :-)

Hippynerd

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.
https://sites.google.com/site/rgbledcubes

mjkzz

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
Search for "mjkzz" on eBay :-)

CrossRoads

Exactly. Just need each 4x4x4 seperated electrically from the others.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

Go Up