Go Down

Topic: 8x8x8 LED cube using Ardunio Mega 2560 and Shift registers (Read 5411 times) previous topic - next topic

usmcPhysicist

Well I have started building my second LED cube and graduated to a stand alone 8x8x8 cube using this as a model:

http://www.instructables.com/id/Self-Contained-7x7x7-LED-Cube/?ALLSTEPS

Because I am an idiot I almost finished building my 8x8x8 cube and circuit and to my dismay I realized I needed 80 outputs
8 x 8 = 64 columns
         + 8 layers
         + 8 push buttons

when my 2560 only provides me 70 outputs. I would be flexible enough to not include the buttons but that still puts me over the limit (probably why the Instructable writer made a 7x7x7). This led me with three options: either reduce the size of the cube (last resort), buy a different controller (that's like admitting defeat), or use a shift register (I just got a TCA9555 "free sample" from Texas Instruments). So, that being said i have looked through every forum and website I could find and I haven't found a way to implement a code like the one in the Instructable:

http://www.instructables.com/files/orig/FOP/HKPE/HFD15TIP/FOPHKPEHFD15TIP.zip

with a "normal" binary code (or a for loop that does the basic same thing) that is all I have found for a shift register: http://forum.arduino.cc/index.php?topic=159141.0

My question is this: is there a way to integrate a shift register easily into the Instructable code (once I make it viable for an 8x8x8 cube), should I turn the entire code into binary, or just do a combination of the two?

Keep in mine I only have limited programming experience so I will be fighting through every line of code (which will be good for me, but only to a certain extent).

Thanks in advance.

CrossRoads

I would switch to hardware that is more appropriate for driving LEDs.
TPIC6B595 shift registers for sinking current from the 64 columns, and P-channel MOSFETs or PNP transistors for sourcing current to the layers.
This board, with external resistors and transistors, would work wonderfully for that, with up to 96 IO provided via SPI to up to 12 shift registers, and if you kept the 328, then another 16 IO for buttons, serial etc.
http://www.crossroadsfencing.com/BobuinoRev17/
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.

usmcPhysicist

Well if I were to fix all my problems by buying this, my question was still unanswered. Since this would still be using shift registers how would I have to write my code, in binary like I have seen with other shift register examples, or would it be in the "typical" way that I have seen with other projects (looks a lot more like java which is what I am familiar with)?

CrossRoads

I would write it in C/C++ using the IDE. I don't know what you mean by binary, or Java-like.
I would make an array of 64 bytes. Each 8 bytes would represent 1 layer.
Every 1 or 2mS use SPI to shift out 8 byte into shift registers 1-8, and in shift register 0 put B11111110, then B11111101, B11111011, with 0 enabling the P-channel device to turn a layer on. The shift registers on that board are daisychained, so it would straightforward to have a loop within a loop to cycle thru all the layers.
Code: [Select]

currentTime = millis();  // capture the time
if ( (currentTime - previousTime)>=duration){ // time to update the display?
previousTime = previousTime + duration; // yes, save the time for the next pass

x=x+1; //  select next layer
if (x==8){x=0;} // reset to 0 after after going thru them all
// turn off previous layer by sending all 1s to shift register 0
digitalWrite (SSpin, LOW);  // can make these faster with direct port manipulation, altho impacts portability
SPI.transfer(0xff);
digitalWrite (SSpin, HIGH);

// send out the layer data
digitalWrite (SSpin, LOW);
for (y=0; y<8; y+y+1){ // arrray data
SPI.transfer(dataArray[ (x*8)+y]); // array data - 0-7, next pass send 8-15, then 9-23, 24-31, 32-39, 40-47, 48-55, 56-63
}
SPI.transfer(layerArray[x]); // layer turn on, layerArray[] = B11111110, B11111101,  B11111011, etc.
digitalWrite(SSpin, HIGH); // outputs change
} //end time check
// do other stuff while time passes, like read serial data & update dataArray, etc.

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.

usmcPhysicist

Code in the format of B11111011 is the "binary like" code of which I was talking about. As opposed to something that resembles Java or C++ like this:

Code: [Select]
/**
*    CornerToCorner.h
*   
*    Extention of Routine to light up the cube starting at a corner.
*   
*    Program written by Lopuz3
*    Spring 2013
**/

#ifndef CornerToCorner_h
#define CornerToCorner_h

#define STEP_TIME 75000

#include "Arduino.h"
#include "Routine.h"

class CornerToCorner : public Routine
{
public:
CornerToCorner();
void update(unsigned long dt);
private:
unsigned long timeSinceLastStep;
int step;
boolean growing;
boolean xHigh, yHigh, zHigh;
};

#endif

/**
*    CornerToCorner.cpp
*   
*    Extention of Routine to light up the cube starting at a corner.
*   
*    Program written by Lopuz3
*    Spring 2013
**/

#include "Arduino.h"
#include "CornerToCorner.h"

CornerToCorner::CornerToCorner()
{
timeSinceLastStep = 0;
step = 0;
growing = true;
xHigh = random(2);
yHigh = random(2);
zHigh = random(2);
}

void CornerToCorner::update(unsigned long dt)
{
timeSinceLastStep += dt;
if (timeSinceLastStep > STEP_TIME)
{
if(growing)
{
for(byte x = 0 ; x < CUBE_SIZE ; x++)
{
for(byte y = 0 ; y < CUBE_SIZE ; y++)
{
for(byte z = 0 ; z < CUBE_SIZE ; z++)
{
int xDist = x;
if(xHigh)
{
xDist = CUBE_SIZE -x -1;
}
int yDist = y;
if(yHigh)
{
yDist = CUBE_SIZE -y -1;
}
int zDist = z;
if(zHigh)
{
zDist = CUBE_SIZE -z -1;
}
cubeModel[x][y][z] = (xDist + yDist + zDist <= step);
}
}
}
step++;
if(step > (CUBE_SIZE-1)*3)
{
step = 0;
growing = false;
}
}
else
{
for(byte x = 0 ; x < CUBE_SIZE ; x++)
{
for(byte y = 0 ; y < CUBE_SIZE ; y++)
{
for(byte z = 0 ; z < CUBE_SIZE ; z++)
{
int xDist = x;
if(xHigh)
{
xDist = CUBE_SIZE -x -1;
}
int yDist = y;
if(yHigh)
{
yDist = CUBE_SIZE -y -1;
}
int zDist = z;
if(zHigh)
{
zDist = CUBE_SIZE -z -1;
}
cubeModel[x][y][z] = !(xDist + yDist + zDist <= step);
}
}
}
step++;
if(step > (CUBE_SIZE-1)*3)
{
step = 0;
growing = true;
xHigh = random(2);
yHigh = random(2);
zHigh = random(2);
}
}
timeSinceLastStep -= STEP_TIME;
}
}
[/size]

But it looks like I should be able to incorporate the "names", or locations, of each column used on the shift register much like I could any of the other columns used on the Arduino board itself. Is that correct?

CrossRoads

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.

usmcPhysicist


Sure. Its all in how you define things.


Thank you very much. I'll post back to let everyone know how it turned out and post my code/ circuit drawings

Go Up