Go Down

Topic: LED cube,shift registers and fun. (Read 20395 times) previous topic - next topic

Hippynerd

#15
Sep 30, 2012, 09:27 pm Last Edit: Sep 30, 2012, 09:40 pm by Hippynerd Reason: 1

Yes Hippynerd,

that's a neat bit of code that I also used after I found it somewhere online. Looks like your doing a good job modifying it to allow for shift registers (I'm certainly not that clever yet  :smiley-sad-blue: ) Keep up the good work and still waiting for that video clip

Pedro.


https://www.youtube.com/watch?v=53SB525n2QY
Heres the video!
https://sites.google.com/site/rgbledcubes

Hippynerd

Bonus video, finding buried treasure for the microcontroller junkie.

The display board looks like it does serial transfer for IR data/button data, and for display data. I've taken some buttons off for my next experiments.

The laser diode and caddy could be fun, I have  to figure out how and what all the wires do. 

The I think the power supply does 24/12/5v. The display board/front panel wants 24v

The motors might be useful for POV projects. I might also be able to use the laser diode caddy for POV projects

https://www.youtube.com/watch?v=KAY-7dzLJH8
https://sites.google.com/site/rgbledcubes

Pedro147

Thanks for the upload, I always like to see a bit of cube action  8)  and good work on recycling the guts of that trashed DVD player... always love a few free parts,

Pedro.
http://www.pedroduino.com

Hippynerd

#18
Oct 01, 2012, 03:22 am Last Edit: Oct 01, 2012, 03:32 am by Hippynerd Reason: 1
I just found a datasheet on the driver/controller for the display
http://www.datasheetarchive.com/TP6312F-datasheet.html

It also turns out the that board has 2 16meg memory chips, but I wasnt able to find out anything about the other chips on that board.

It would be neat to store 16 megs of data, and make the display scroll information or something.

I also found that the board has print next to the wires, which make things easier, they are:
INIR
VCC
Data In
CLK
STB
Data Out

So, I know its a TOPRO tp6312 chip, and I know what wires are what, how do I figure out how to make it display stuff?
https://sites.google.com/site/rgbledcubes

Hippynerd

I made a fritzing image for a schematic.
I never made a breadboard, my shift registers are piggybacked, and soldered to wires from an old ribbon cable that has SIP header pins plugged into the connecter, to connect to the arduinos connector. and a couple scrap wires connected to pins to provide + and GND to the shift registers.
https://sites.google.com/site/rgbledcubes

Hippynerd

I went through the original code that I had started with, and re-edited it to work with my cube, and I also made a version for common cathode leds.
Here are both versions. Both should work for cubes with shift registers.


Common Anode 4x4x4 cube with shift register code:


Code: [Select]
// OCT32012 editing changes to adapt this program to work with shift registers,
// and to work with Common Anode LED cube. hippynurd@gmail.com

#include <avr/pgmspace.h> // allows use of PROGMEM to store patterns in flash

#define CUBESIZE 4
#define PLANESIZE CUBESIZE*CUBESIZE
#define PLANETIME 3333 // time each plane is displayed in us -> 100 Hz refresh
#define TIMECONST 20 // multiplies DisplayTime to get ms - why not =100?

// LED Pattern Table in PROGMEM - last column is display time in 100ms units
// TODO this could be a lot more compact but not with binary pattern representation
prog_uchar PROGMEM PatternTable[] = {
// blink on and off

B0001,B0000,B0000,B0000,B0001,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,10,
B0011,B0000,B0000,B0000,B0011,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,10,
B0011,B0010,B0000,B0000,B0011,B0010,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,10,
B0011,B0011,B0000,B0000,B0011,B0011,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,10,
B0110,B0110,B0000,B0000,B0110,B0110,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,10,
B0000,B0000,B0000,B0000,B0110,B0110,B0000,B0000,B0110,B0110,B0000,B0000,B0000,B0000,B0000,B0000,10,
B0000,B0000,B0000,B0000,B0000,B0110,B0110,B0000,B0000,B0110,B0110,B0000,B0000,B0000,B0000,B0000,10,
B0000,B0000,B0000,B0000,B0000,B0000,B0110,B0110,B0000,B0000,B0110,B0110,B0000,B0000,B0000,B0000,10,
B0000,B0000,B0000,B0000,B0000,B0000,B0011,B0011,B0000,B0000,B0011,B0011,B0000,B0000,B0000,B0000,10,
B0000,B0000,B0000,B0000,B0000,B0001,B0011,B0111,B0000,B0001,B0011,B0111,B0000,B0000,B0001,B0011,10,
B0000,B0000,B0000,B0000,B0000,B0011,B0111,B0111,B0000,B0011,B0111,B0111,B0000,B0001,B0011,B0111,10,
B0000,B0000,B0000,B0000,B0000,B0111,B0111,B0111,B0000,B0111,B0111,B0111,B0000,B0011,B0111,B0111,10,
B0000,B0000,B0000,B0000,B0000,B0111,B0111,B0111,B0000,B0111,B0111,B0111,B0000,B0111,B0111,B0111,10,
B0000,B0000,B0000,B0000,B0000,B1110,B1110,B1110,B0000,B1110,B1110,B1110,B0000,B1110,B1110,B1110,10,
B0000,B1110,B1110,B1110,B0000,B1110,B1110,B1110,B0000,B1110,B1110,B1110,B0000,B0000,B0000,B0000,10,
B0000,B1110,B1110,B1110,B0000,B1110,B1110,B1110,B0000,B1100,B1110,B1110,B0000,B0000,B0000,B0000,10,
B0000,B1110,B1110,B1110,B0000,B1100,B1110,B1110,B0000,B1000,B1100,B1110,B0000,B0000,B0000,B0000,10,
B0000,B1100,B1110,B1110,B0000,B1000,B1100,B1110,B0000,B0000,B1000,B1100,B0000,B0000,B0000,B0000,10,
B0000,B1000,B1100,B1110,B0000,B0000,B1000,B1100,B0000,B0000,B0000,B1000,B0000,B0000,B0000,B0000,10,
B0000,B0000,B1000,B1100,B0000,B0000,B0000,B1000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,10,

// this is a dummy element for end of table (duration=0) aka !!!DO NOT TOUCH!!!
B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, 0
};

/*
** Defining pins in array makes it easier to rearrange how cube is wired
** Adjust numbers here until LEDs flash in order - L to R, T to B
** Note that analog inputs 0-5 are also digital outputs 14-19!
** Pin DigitalOut0 (serial RX) and AnalogIn5 are left open for future apps
*/
// Just a note to say we dont do things this way anymore. Data is serialized
// to pin 7 via 74hc595 shift registers, and the planes(layers) are controlled
// by pins 11,10,9,6. The first shift register controls the first 8 pins, the
// second shift register controls pins 9-16.
// Looking down on the cube, the column pin matrix looks like this:

// 16 15 14 13
//
// 12 11 10  9
//
//  8  7  6  5 
//
//  4  3  2  1

// My cube is common anode, meaning send 5 volts to the plane(layer), and ground
// the column to illuminate the individual led. This code was originally common cathode.


//OLD
//int LEDPin[] = {13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 14, 15};
//int PlanePin[] = {16, 17, 18, 19};
//NEW
int LEDPin[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
int PlanePin[] = {11, 10, 9, 6};
int dataPin = 7; //Data  I added these for Shift Register
int clockPin = 12; // Clock
int latchPin = 13; // Latch

// initialization
void setup()
{
int pin; // loop counter
/*
// set up LED pins as output (active HIGH)
for (pin=0; pin<PLANESIZE; pin++) {
pinMode( LEDPin[pin], OUTPUT );
}
*/
// set up pins for serial output
{
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
}

// set up plane pins as outputs (active LOW)
for (pin=0; pin<CUBESIZE; pin++) {
pinMode( PlanePin[pin], OUTPUT );
}
}

// display pattern in table until DisplayTime is zero (then repeat)
void loop()
{
// declare variables
byte PatternBuf[PLANESIZE]; // saves current pattern from PatternTable
int PatternIdx;
byte DisplayTime; // time*100ms to display pattern
unsigned long EndTime;
int plane; // loop counter for cube refresh
int patbufidx; // indexes which byte from pattern buffer
int ledrow; // counts LEDs in refresh loop
int ledcol; // counts LEDs in refresh loop
int ledpin; // counts LEDs in refresh loop
int pinState; //pinState is used to send the correct bit to the data pin

// Initialize PatternIdx to beginning of pattern table
PatternIdx = 0;
// loop over entries in pattern table - while DisplayTime>0
do {
// read pattern from PROGMEM and save in array
memcpy_P( PatternBuf, PatternTable+PatternIdx, PLANESIZE );
PatternIdx += PLANESIZE;
// read DisplayTime from PROGMEM and increment index
DisplayTime = pgm_read_byte_near( PatternTable + PatternIdx++ );
// compute EndTime from current time (ms) and DisplayTime
EndTime = millis() + ((unsigned long) DisplayTime) * TIMECONST;

// loop while DisplayTime>0 and current time < EndTime
while ( millis() < EndTime ) {
patbufidx = 0; // reset index counter to beginning of buffer
// loop over planes
for (plane=0; plane<CUBESIZE; plane++) {
// turn previous plane off (low is off, high is on)
if (plane==0) {
digitalWrite( PlanePin[CUBESIZE-1], LOW );
} else {
digitalWrite( PlanePin[plane-1], LOW );
}


/*
// load current plane pattern data into ports
ledpin = 0;
for (ledrow=0; ledrow<CUBESIZE; ledrow++) {
for (ledcol=0; ledcol<CUBESIZE; ledcol++) {
digitalWrite( LEDPin[ledpin++], PatternBuf[patbufidx] & (1 << ledcol) );
}
patbufidx++;
}
*/
// I used code from shiftout, to redo this to serialize the plane data
    //ground latchPin and hold low for as long as you are transmitting
    digitalWrite(latchPin, 0);
    //move 'em out
ledpin = 0;
for (ledrow=0; ledrow<CUBESIZE; ledrow++) {
for (ledcol=0; ledcol<CUBESIZE; ledcol++) {
 
digitalWrite(clockPin, 0);
   
// digitalWrite( dataPin, PatternBuf[patbufidx] & (1 << ledcol) );
if (PatternBuf[patbufidx] & (1 << ledcol))
    {
      pinState= 0;  // Flip these bits to suit your cubes common lead (cathode or anode)
    }
    else
    {
      pinState= 1;  // Flip these bits to suit your cubes common lead (cathode or anode)
    }

    //Sets the pin to HIGH or LOW depending on pinState
    digitalWrite(dataPin, pinState); // this is where data is sent to the shift register.
    //register shifts bits on upstroke of clock pin
    digitalWrite(clockPin, 1);

ledpin++;
}
patbufidx++;
}
digitalWrite(latchPin, 1);

// turn current plane on (plane high for on)
digitalWrite( PlanePin[plane], HIGH );
// delay PLANETIME us
delayMicroseconds( PLANETIME );
} // for plane
} // while <EndTime
} while (DisplayTime > 0); // read patterns until time=0 which signals end
}



I had to strip most of the data to get the program to fit in one post.

https://sites.google.com/site/rgbledcubes

Hippynerd

This is the original data field

Code: [Select]
B0001,B0000,B0000,B0000,B0001,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,10,
B0011,B0000,B0000,B0000,B0011,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,10,
B0011,B0010,B0000,B0000,B0011,B0010,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,10,
B0011,B0011,B0000,B0000,B0011,B0011,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,10,
B0110,B0110,B0000,B0000,B0110,B0110,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,10,
B0000,B0000,B0000,B0000,B0110,B0110,B0000,B0000,B0110,B0110,B0000,B0000,B0000,B0000,B0000,B0000,10,
B0000,B0000,B0000,B0000,B0000,B0110,B0110,B0000,B0000,B0110,B0110,B0000,B0000,B0000,B0000,B0000,10,
B0000,B0000,B0000,B0000,B0000,B0000,B0110,B0110,B0000,B0000,B0110,B0110,B0000,B0000,B0000,B0000,10,
B0000,B0000,B0000,B0000,B0000,B0000,B0011,B0011,B0000,B0000,B0011,B0011,B0000,B0000,B0000,B0000,10,
B0000,B0000,B0000,B0000,B0000,B0001,B0011,B0111,B0000,B0001,B0011,B0111,B0000,B0000,B0001,B0011,10,
B0000,B0000,B0000,B0000,B0000,B0011,B0111,B0111,B0000,B0011,B0111,B0111,B0000,B0001,B0011,B0111,10,
B0000,B0000,B0000,B0000,B0000,B0111,B0111,B0111,B0000,B0111,B0111,B0111,B0000,B0011,B0111,B0111,10,
B0000,B0000,B0000,B0000,B0000,B0111,B0111,B0111,B0000,B0111,B0111,B0111,B0000,B0111,B0111,B0111,10,
B0000,B0000,B0000,B0000,B0000,B1110,B1110,B1110,B0000,B1110,B1110,B1110,B0000,B1110,B1110,B1110,10,
B0000,B1110,B1110,B1110,B0000,B1110,B1110,B1110,B0000,B1110,B1110,B1110,B0000,B0000,B0000,B0000,10,
B0000,B1110,B1110,B1110,B0000,B1110,B1110,B1110,B0000,B1100,B1110,B1110,B0000,B0000,B0000,B0000,10,
B0000,B1110,B1110,B1110,B0000,B1100,B1110,B1110,B0000,B1000,B1100,B1110,B0000,B0000,B0000,B0000,10,
B0000,B1100,B1110,B1110,B0000,B1000,B1100,B1110,B0000,B0000,B1000,B1100,B0000,B0000,B0000,B0000,10,
B0000,B1000,B1100,B1110,B0000,B0000,B1000,B1100,B0000,B0000,B0000,B1000,B0000,B0000,B0000,B0000,10,
B0000,B0000,B1000,B1100,B0000,B0000,B0000,B1000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,10,
https://sites.google.com/site/rgbledcubes

Hippynerd

#22
Oct 04, 2012, 05:22 pm Last Edit: Oct 04, 2012, 05:24 pm by Hippynerd Reason: 1
This version should work on a 4x4x4 cube with common cathode and 2 shift registers. take the data from the previous post, and paste it into this code.


Code: [Select]
// OCT32012 editing changes to adapt this program to work with shift registers,
// and to work with Common Anode LED cube. hippynurd@gmail.com

#include <avr/pgmspace.h> // allows use of PROGMEM to store patterns in flash

#define CUBESIZE 4
#define PLANESIZE CUBESIZE*CUBESIZE
#define PLANETIME 3333 // time each plane is displayed in us -> 100 Hz refresh
#define TIMECONST 10 // multiplies DisplayTime to get ms - why not =100?

// LED Pattern Table in PROGMEM - last column is display time in 100ms units
// TODO this could be a lot more compact but not with binary pattern representation
prog_uchar PROGMEM PatternTable[] = {
// blink on and off


// Data was removed to make the program fit in one post, see previous post for data
B0001,B0000,B0000,B0000,B0001,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,10,


// this is a dummy element for end of table (duration=0) aka !!!DO NOT TOUCH!!!
B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, 0
};

/*
** Defining pins in array makes it easier to rearrange how cube is wired
** Adjust numbers here until LEDs flash in order - L to R, T to B
** Note that analog inputs 0-5 are also digital outputs 14-19!
** Pin DigitalOut0 (serial RX) and AnalogIn5 are left open for future apps
*/
// Just a note to say we dont do things this way anymore. Data is serialized
// to pin 7 via 74hc595 shift registers, and the planes(layers) are controlled
// by pins 11,10,9,6. The first shift register controls the first 8 pins, the
// second shift register controls pins 9-16.
// Looking down on the cube, the column pin matrix looks like this:

// 16 15 14 13
//
// 12 11 10  9
//
//  8  7  6  5  
//
//  4  3  2  1

// This code is for common cathnode, meaning ground the plane(layer), and send 5 volts to
// the column to illuminate the individual led.


//OLD
//int LEDPin[] = {13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 14, 15};
//int PlanePin[] = {16, 17, 18, 19};
//NEW
int LEDPin[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
int PlanePin[] = {11, 10, 9, 6};
int dataPin = 7; //Data  I added these for Shift Register
int clockPin = 12; // Clock
int latchPin = 13; // Latch

// initialization
void setup()
{
int pin; // loop counter
/*
// set up LED pins as output (active HIGH)
for (pin=0; pin<PLANESIZE; pin++) {
pinMode( LEDPin[pin], OUTPUT );
}
*/
// set up pins for serial output
{
 pinMode(latchPin, OUTPUT);
 pinMode(clockPin, OUTPUT);
 pinMode(dataPin, OUTPUT);
}

// set up plane pins as outputs (active LOW)
for (pin=0; pin<CUBESIZE; pin++) {
pinMode( PlanePin[pin], OUTPUT );
}
}

// display pattern in table until DisplayTime is zero (then repeat)
void loop()
{
// declare variables
byte PatternBuf[PLANESIZE]; // saves current pattern from PatternTable
int PatternIdx;
byte DisplayTime; // time*100ms to display pattern
unsigned long EndTime;
int plane; // loop counter for cube refresh
int patbufidx; // indexes which byte from pattern buffer
int ledrow; // counts LEDs in refresh loop
int ledcol; // counts LEDs in refresh loop
int ledpin; // counts LEDs in refresh loop
int pinState; //pinState is used to send the correct bit to the data pin

// Initialize PatternIdx to beginning of pattern table
PatternIdx = 0;
// loop over entries in pattern table - while DisplayTime>0
do {
// read pattern from PROGMEM and save in array
memcpy_P( PatternBuf, PatternTable+PatternIdx, PLANESIZE );
PatternIdx += PLANESIZE;
// read DisplayTime from PROGMEM and increment index
DisplayTime = pgm_read_byte_near( PatternTable + PatternIdx++ );
// compute EndTime from current time (ms) and DisplayTime
EndTime = millis() + ((unsigned long) DisplayTime) * TIMECONST;

// loop while DisplayTime>0 and current time < EndTime
while ( millis() < EndTime ) {
patbufidx = 0; // reset index counter to beginning of buffer
// loop over planes
for (plane=0; plane<CUBESIZE; plane++) {
// turn previous plane off (low is on, high is off)
if (plane==0) {
digitalWrite( PlanePin[CUBESIZE-1], HIGH );
} else {
digitalWrite( PlanePin[plane-1], HIGH );
}


/*
// load current plane pattern data into ports
ledpin = 0;
for (ledrow=0; ledrow<CUBESIZE; ledrow++) {
for (ledcol=0; ledcol<CUBESIZE; ledcol++) {
digitalWrite( LEDPin[ledpin++], PatternBuf[patbufidx] & (1 << ledcol) );
}
patbufidx++;
}
*/
// I used code from shiftout, to redo this to serialize the plane data
   //ground latchPin and hold low for as long as you are transmitting
   digitalWrite(latchPin, 0);
   //move 'em out
ledpin = 0;
for (ledrow=0; ledrow<CUBESIZE; ledrow++) {
for (ledcol=0; ledcol<CUBESIZE; ledcol++) {
 
digitalWrite(clockPin, 0);
 
// digitalWrite( dataPin, PatternBuf[patbufidx] & (1 << ledcol) );
if (PatternBuf[patbufidx] & (1 << ledcol))
   {
     pinState= 1;  // Flip these bits to suit your cubes common lead (cathode or anode)
   }
   else
   {
     pinState= 0;  // Flip these bits to suit your cubes common lead (cathode or anode)
   }

   //Sets the pin to HIGH or LOW depending on pinState
   digitalWrite(dataPin, pinState); // this is where data is sent to the shift register.
   //register shifts bits on upstroke of clock pin
   digitalWrite(clockPin, 1);

ledpin++;
}
patbufidx++;
}
digitalWrite(latchPin, 1);

// turn current plane on (plane high for on)
digitalWrite( PlanePin[plane], HIGH );
// delay PLANETIME us
delayMicroseconds( PLANETIME );
} // for plane
} // while <EndTime
} while (DisplayTime > 0); // read patterns until time=0 which signals end
}
https://sites.google.com/site/rgbledcubes

dutchronnie

Hello Hippynerd,

I have built a 4x4x4 ledcube, and have used your code.
I have added some patterns to.
It works fine, but as far as i can see, the code only controls the colums.

Is it possible to control every singe led
I think we can create better patters if we can control the planes too

Hippynerd

Hey :D

The way the cube code works, it sequences through each plane at a time.
Code: [Select]
for (pin=0; pin<CUBESIZE; pin++) {

That is the bit of code that starts a loop that sequences between 1,2,3,4 planes.

This code will control each LED individually. You could make a pattern that only lights up one specific LED, and repeat that pattern many times to test it.

Please post your code, and dont forget to use the code tag (use the button that looks like a #).

The nice thing about open source code is that you can modify it to suit your needs. If you want to change the code to control the planes in a different way, then you should do that right away. Please post your version here so that I may enjoy it too.
https://sites.google.com/site/rgbledcubes

dutchronnie

#25
Nov 24, 2012, 10:29 am Last Edit: Nov 24, 2012, 10:56 am by dutchronnie Reason: 1
I shall try to control the planes, but i am not so good programmer.

The code i have used is this code:

Code: [Select]
// OCT32012 editing changes to adapt this program to work with shift registers,
// and to work with Common Anode LED cube. hippynurd@gmail.com

#include <avr/pgmspace.h> // allows use of PROGMEM to store patterns in flash

#define CUBESIZE 4
#define PLANESIZE CUBESIZE*CUBESIZE
#define PLANETIME 3333 // time each plane is displayed in us -> 100 Hz refresh
#define TIMECONST 10 // multiplies DisplayTime to get ms - why not =100?

// LED Pattern Table in PROGMEM - last column is display time in 100ms units
// TODO this could be a lot more compact but not with binary pattern representation
prog_uchar PROGMEM PatternTable[] = {
// blink on and off

//top layer first four / second layer/ 2nd four / 3rd layer 3rd four  / bottom layer
B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0001,15,

// this is a dummy element for end of table (duration=0) aka !!!DO NOT TOUCH!!!
B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, 0
};

/*
** Defining pins in array makes it easier to rearrange how cube is wired
** Adjust numbers here until LEDs flash in order - L to R, T to B
** Note that analog inputs 0-5 are also digital outputs 14-19!
** Pin DigitalOut0 (serial RX) and AnalogIn5 are left open for future apps
*/
// Just a note to say we dont do things this way anymore. Data is serialized
// to pin 7 via 74hc595 shift registers, and the planes(layers) are controlled
// by pins 11,10,9,6. The first shift register controls the first 8 pins, the
// second shift register controls pins 9-16.
// Looking down on the cube, the column pin matrix looks like this:

// 16 15 14 13
//
// 12 11 10  9
//
//  8  7  6  5 
//
//  4  3  2  1

// This code is for common cathnode, meaning ground the plane(layer), and send 5 volts to
// the column to illuminate the individual led.


//OLD
//int LEDPin[] = {13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 14, 15};
//int PlanePin[] = {16, 17, 18, 19};
//NEW
//int LEDPin[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
int PlanePin[] = {2, 3, 4, 5};
int dataPin = 7;   // Data  I added these for Shift Register
int clockPin = 12; // Clock
int latchPin = 8; // Latch

// initialization
void setup()
{
int pin; // loop counter
/*
// set up LED pins as output (active HIGH)
for (pin=0; pin<PLANESIZE; pin++) {
pinMode( LEDPin[pin], OUTPUT );
}
*/
// set up pins for serial output
{
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
}

// set up plane pins as outputs (active LOW)
for (pin=0; pin<CUBESIZE; pin++) {
pinMode( PlanePin[pin], OUTPUT );
}
}

// display pattern in table until DisplayTime is zero (then repeat)
void loop()
{
// declare variables
byte PatternBuf[PLANESIZE]; // saves current pattern from PatternTable
int PatternIdx;
byte DisplayTime; // time*100ms to display pattern
unsigned long EndTime;
int plane; // loop counter for cube refresh
int patbufidx; // indexes which byte from pattern buffer
int ledrow; // counts LEDs in refresh loop
int ledcol; // counts LEDs in refresh loop
int ledpin; // counts LEDs in refresh loop
int pinState; //pinState is used to send the correct bit to the data pin

// Initialize PatternIdx to beginning of pattern table
PatternIdx = 0;
// loop over entries in pattern table - while DisplayTime>0
do {
// read pattern from PROGMEM and save in array
memcpy_P( PatternBuf, PatternTable+PatternIdx, PLANESIZE );
PatternIdx += PLANESIZE;
// read DisplayTime from PROGMEM and increment index
DisplayTime = pgm_read_byte_near( PatternTable + PatternIdx++ );
// compute EndTime from current time (ms) and DisplayTime
EndTime = millis() + ((unsigned long) DisplayTime) * TIMECONST;

// loop while DisplayTime>0 and current time < EndTime
while ( millis() < EndTime ) {
patbufidx = 0; // reset index counter to beginning of buffer
// loop over planes
for (plane=0; plane<CUBESIZE; plane++) {
// turn previous plane off (low is on, high is off)
if (plane==0) {
digitalWrite( PlanePin[CUBESIZE-1], HIGH );
} else {
digitalWrite( PlanePin[plane-1], HIGH );
}


/*
// load current plane pattern data into ports
ledpin = 0;
for (ledrow=0; ledrow<CUBESIZE; ledrow++) {
for (ledcol=0; ledcol<CUBESIZE; ledcol++) {
digitalWrite( LEDPin[ledpin++], PatternBuf[patbufidx] & (1 << ledcol) );
}
patbufidx++;
}
*/
// I used code from shiftout, to redo this to serialize the plane data
    //ground latchPin and hold low for as long as you are transmitting
    digitalWrite(latchPin, 0);
    //move 'em out
ledpin = 0;
for (ledrow=0; ledrow<CUBESIZE; ledrow++) {
for (ledcol=0; ledcol<CUBESIZE; ledcol++) {
 
digitalWrite(clockPin, 0);
   
// digitalWrite( dataPin, PatternBuf[patbufidx] & (1 << ledcol) );
if (PatternBuf[patbufidx] & (1 << ledcol))
    {
      pinState= 1;  // Flip these bits to suit your cubes common lead (cathode or anode)
    }
    else
    {
      pinState= 0;  // Flip these bits to suit your cubes common lead (cathode or anode)
    }

    //Sets the pin to HIGH or LOW depending on pinState
    digitalWrite(dataPin, pinState); // this is where data is sent to the shift register.
    //register shifts bits on upstroke of clock pin
    digitalWrite(clockPin, 1);

ledpin++;
}
patbufidx++;
}
digitalWrite(latchPin, 1);

// turn current plane on (plane high for on)
digitalWrite( PlanePin[plane], HIGH );
// delay PLANETIME us
delayMicroseconds( PLANETIME );
} // for plane
} // while <EndTime
} while (DisplayTime > 0); // read patterns until time=0 which signals end
}


this piece of code controls the leds:

//top layer first four / second layer/ 2nd four / 3rd layer 3rd four  / bottom layer
B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0001,15,

the first four are for the top layer and the last for for the bottom layer.
but it doesn't make any difference .

This line:
B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0001,15,
lighten up the same colum as:
B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0001,B0000,B0000,B0000,B0000,15,

i think that the first line must lighten up the most right led on the bottom layer, and the second line the most right led on the 3rd layer.

am i right?

dhenry

Quote
Heres the video!


google "aurura 9x18", and pay attention to its driver design.

The most impressive I have seen.

dutchronnie

i am trying for several hours to get my led cube working, but with no succes.

I have built a 4x4x4 ledcube with common kathode.
the four planes of the cube are connected with a npn transistor.
The colums are controled with two shift registers 74hc595

But when is use the code from Hippynerd, only the collums do light up with all 4 layers.
When i see the video of Hippynerd, then i can see individual leds burning.

Does anybody know what goes wrong with my cube?

Hippynerd


I shall try to control the planes, but i am not so good programmer.

The code i have used is this code:

Code: [Select]
// OCT32012 editing changes to adapt this program to work with shift registers,
// and to work with Common Anode LED cube. hippynurd@gmail.com

#include <avr/pgmspace.h> // allows use of PROGMEM to store patterns in flash

#define CUBESIZE 4
#define PLANESIZE CUBESIZE*CUBESIZE
#define PLANETIME 3333 // time each plane is displayed in us -> 100 Hz refresh
#define TIMECONST 10 // multiplies DisplayTime to get ms - why not =100?

// LED Pattern Table in PROGMEM - last column is display time in 100ms units
// TODO this could be a lot more compact but not with binary pattern representation
prog_uchar PROGMEM PatternTable[] = {
// blink on and off

//top layer first four / second layer/ 2nd four / 3rd layer 3rd four  / bottom layer
B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0001,15,

// this is a dummy element for end of table (duration=0) aka !!!DO NOT TOUCH!!!
B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, 0
};

/*
** Defining pins in array makes it easier to rearrange how cube is wired
** Adjust numbers here until LEDs flash in order - L to R, T to B
** Note that analog inputs 0-5 are also digital outputs 14-19!
** Pin DigitalOut0 (serial RX) and AnalogIn5 are left open for future apps
*/
// Just a note to say we dont do things this way anymore. Data is serialized
// to pin 7 via 74hc595 shift registers, and the planes(layers) are controlled
// by pins 11,10,9,6. The first shift register controls the first 8 pins, the
// second shift register controls pins 9-16.
// Looking down on the cube, the column pin matrix looks like this:

// 16 15 14 13
//
// 12 11 10  9
//
//  8  7  6  5 
//
//  4  3  2  1

// This code is for common cathnode, meaning ground the plane(layer), and send 5 volts to
// the column to illuminate the individual led.


//OLD
//int LEDPin[] = {13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 14, 15};
//int PlanePin[] = {16, 17, 18, 19};
//NEW
//int LEDPin[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
int PlanePin[] = {2, 3, 4, 5};
int dataPin = 7;   // Data  I added these for Shift Register
int clockPin = 12; // Clock
int latchPin = 8; // Latch

// initialization
void setup()
{
int pin; // loop counter
/*
// set up LED pins as output (active HIGH)
for (pin=0; pin<PLANESIZE; pin++) {
pinMode( LEDPin[pin], OUTPUT );
}
*/
// set up pins for serial output
{
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
}

// set up plane pins as outputs (active LOW)
for (pin=0; pin<CUBESIZE; pin++) {
pinMode( PlanePin[pin], OUTPUT );
}
}

// display pattern in table until DisplayTime is zero (then repeat)
void loop()
{
// declare variables
byte PatternBuf[PLANESIZE]; // saves current pattern from PatternTable
int PatternIdx;
byte DisplayTime; // time*100ms to display pattern
unsigned long EndTime;
int plane; // loop counter for cube refresh
int patbufidx; // indexes which byte from pattern buffer
int ledrow; // counts LEDs in refresh loop
int ledcol; // counts LEDs in refresh loop
int ledpin; // counts LEDs in refresh loop
int pinState; //pinState is used to send the correct bit to the data pin

// Initialize PatternIdx to beginning of pattern table
PatternIdx = 0;
// loop over entries in pattern table - while DisplayTime>0
do {
// read pattern from PROGMEM and save in array
memcpy_P( PatternBuf, PatternTable+PatternIdx, PLANESIZE );
PatternIdx += PLANESIZE;
// read DisplayTime from PROGMEM and increment index
DisplayTime = pgm_read_byte_near( PatternTable + PatternIdx++ );
// compute EndTime from current time (ms) and DisplayTime
EndTime = millis() + ((unsigned long) DisplayTime) * TIMECONST;

// loop while DisplayTime>0 and current time < EndTime
while ( millis() < EndTime ) {
patbufidx = 0; // reset index counter to beginning of buffer
// loop over planes
for (plane=0; plane<CUBESIZE; plane++) {
// turn previous plane off (low is on, high is off)
if (plane==0) {
digitalWrite( PlanePin[CUBESIZE-1], HIGH );
} else {
digitalWrite( PlanePin[plane-1], HIGH );
}


/*
// load current plane pattern data into ports
ledpin = 0;
for (ledrow=0; ledrow<CUBESIZE; ledrow++) {
for (ledcol=0; ledcol<CUBESIZE; ledcol++) {
digitalWrite( LEDPin[ledpin++], PatternBuf[patbufidx] & (1 << ledcol) );
}
patbufidx++;
}
*/
// I used code from shiftout, to redo this to serialize the plane data
    //ground latchPin and hold low for as long as you are transmitting
    digitalWrite(latchPin, 0);
    //move 'em out
ledpin = 0;
for (ledrow=0; ledrow<CUBESIZE; ledrow++) {
for (ledcol=0; ledcol<CUBESIZE; ledcol++) {
 
digitalWrite(clockPin, 0);
   
// digitalWrite( dataPin, PatternBuf[patbufidx] & (1 << ledcol) );
if (PatternBuf[patbufidx] & (1 << ledcol))
    {
      pinState= 1;  // Flip these bits to suit your cubes common lead (cathode or anode)
    }
    else
    {
      pinState= 0;  // Flip these bits to suit your cubes common lead (cathode or anode)
    }

    //Sets the pin to HIGH or LOW depending on pinState
    digitalWrite(dataPin, pinState); // this is where data is sent to the shift register.
    //register shifts bits on upstroke of clock pin
    digitalWrite(clockPin, 1);

ledpin++;
}
patbufidx++;
}
digitalWrite(latchPin, 1);

// turn current plane on (plane high for on)
digitalWrite( PlanePin[plane], HIGH );
// delay PLANETIME us
delayMicroseconds( PLANETIME );
} // for plane
} // while <EndTime
} while (DisplayTime > 0); // read patterns until time=0 which signals end
}


this piece of code controls the leds:

//top layer first four / second layer/ 2nd four / 3rd layer 3rd four  / bottom layer
B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0001,15,

the first four are for the top layer and the last for for the bottom layer.
but it doesn't make any difference .

This line:
B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0001,15,
lighten up the same colum as:
B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0000,B0001,B0000,B0000,B0000,B0000,15,

i think that the first line must lighten up the most right led on the bottom layer, and the second line the most right led on the 3rd layer.

am i right?

duchronnie:
That sounds about right, im not positive, but it sounds right.
Im not sure what is going wrong with your cube. Can you run it without the transistors? maybe if you take the transistors out of the equation, it will work right?

dhenry:
That aurora is pretty cool, i was checking it out last week because someone had the PCB for it (actually i think it was the 18x18) but I have too many other projects that I want to build.

https://sites.google.com/site/rgbledcubes

dutchronnie

I have tried to remove the transsistors, and attached the planes to the arduino outputs directly.
But then the leds don't work.

It looks like the cube is good

Go Up