LED cube,shift registers and fun.

Maybe you should try the common anode version.
I never used any transistors in my build, If it was working fine with them before, than it should work find after also, but the cube should run without them (like mine and many others work).

Shift registers should work with to source or sink current, so it shouldnt matter if you have CC or CA setup, but the transistors probably are for sourcing current, which leads me to believe you have a common cathode setup.

yES :slight_smile:
IT IS WORKING

I now have tried your code for the common anode, and changed the lines

      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)

but stil i think i do have an common kathode cube.
The colums are the positive leads of the led
The planes are the negative leads of the led

Thanks Hippynerd for your help

That bit there, and the bit at the top that says cathode/anode are the only differences between the 2 programs. I should change that to a binary variable (true/false) and embed it with a comment.

The cube setups that I have seen that use 4 transistors on the planes are common anode, and the transistors are to source current to the plane. I think you could also use transistors to sink current to the planes also, but I dont think that i have seen that yet. I think all the LED rigs I have setup are common cathode, even when I tried to make one common anode! Shift registers should work with either setup.

Now that things are working, you can start messing around with data fields, and make up your own patterns. Please share all the cool patterns that you come up with, post them here, or link them here, and I will try them out on my cube.

There are other 4x4x4 cube programs out there to try, I had trouble getting them to work on my cube, but they may run on your cube.

very good job , i like it !!!

from spain

Seasons Greeting All

Sparkie4080 Here
New to this fourm.
Hi Hippynerd
Spotted your comments on the 4x4x4 led cube, and was glad to follow your code input, just what I was looking for.
I am hopefully attaching my schematic and code for my 4x4x4 led cube. I built mine on a 4.25x6.5 purfaboard and point to point wiring. the cube works well with the off board uno, but brighter with a 5Volt 2Amp wall wort.
I had a bit of trouble finding a working code for this unit. the one I found didn't have the collum part so I added it as:
int data=2; //pin 2 on the arduino board
int data=3; //pin 3 on the arduino board
int data=4; //pin 4 on the arduino board
int Col1=5; //pin 5 on the arduino board
int Col2=6; //pin 6 on the arduino board
int Col2=7; //pin 7 on the arduino board
int Col2=8; //pin 8 on the arduino board

Im going to try your code and see if it works on my cube.

Let me know if the attached files made it
Thanks
Sparkie4080

sketch_dec30a_6_in_progress.pde (3.88 KB)

Hi Sparkie4080,
Thats a real nice looking schematic. My cube started as just 4 resistors, and 64 white LEDs, Then upgraded it to 2 shift registers and then 16 resistors. 1 resistor. It looks like you are sourcing with your shift registers, sinking with the 4 transistor, which is a much better way to do it than my, and its really only 8 more parts. I also notice you have a 1k resistor on pin 74hc595 10(MR) what it that for?

Thats a much nicer circuit. It looks about how I probably should have made my first cube.

Happy New Year to all

Hi Hippynerd

Thank You for your reply.
I found that schematic somewhere on the internet, just can't remember where though.
I built that circuit on a perfiboard with point to point wiring. The Arduino Uno is off board for now as I not sure weather I want to use the Arduino Atmel328 or use a PIC chip. I have room on the board for one or the other, but I'll have to do more research.
Being a NUBE in C++ programming it's a problem understanding what I'm doing.
I've done some Basic programming back in the Vic20 days, but haven't done anything in C or C++.
As for the Program I'm using Now, (Which I Attached in my last message) I found it again somewhere on the internet. It didn't have any way of controlling the Columns, so I added the four lines to bring the Transisters High to Sink the Columns.
Looking at the schematic, notice on the top left are two sets of input pins that get the signals from the offboard Arduino Uno. I had trouble setting the pins, forgetting that the pins are labled 0-7 on the Arduino, but on the schematic, they are marked 1-7, I had put the Data-Clock and Latch in the wrong Place.
I'm Going to try to upload the code in this message....HOPE IT Works...:wink:
And Hope You and others can guide me with C++.
Thanks.

/*    Arduino Experimentation Kit Example Code             |
 *    CIRC-05 .: 8 More LEDs :. (74HC595 Shift Register)   |
 *    We have already controlled 8 LEDs however this does it in a slightly
 *    different manner. Rather than using 8 pins we will use just three
 *    and an additional chip.
 */
// This is My Version of the Pin Connections
//Pin Definitions
//The 74HC595 uses a serial communication 
//link which has three pins Data-Clock and Latch 
// Pins 5-6-7-8 are the Columns
int data = 2; 
int clock = 3;
int latch = 4;

int Col1 = 5; // Transistor1 Base
int Col2 = 6; // Transistor2 Base
int Col3 = 7; // Transistor3 Base
int Col4 = 8; // Transistor4 Base

//Used for single LED manipulation
int ledState = 0;
const int ON = HIGH;
const int OFF = LOW;
             
/*setup() - this function runs once when you turn your Arduino on
 * We set the three control pins to outputs
 */
void setup()
{
  pinMode(data, OUTPUT);
  pinMode(clock, OUTPUT);  
  pinMode(latch, OUTPUT);  
  
  pinMode(Col1, OUTPUT);
  pinMode(Col2, OUTPUT); 
  pinMode(Col3, OUTPUT);
  pinMode(Col4, OUTPUT);
  
}
/*
 * loop() - this function will start after setup finishes and then repeat
 * we set which LEDs we want on then call a routine which sends the states to the 

74HC595
 */
void loop()                     // run over and over again
{
  int delayTime = 100; //the number of milliseconds to delay between LED updates
  for(int i = 0; i < 256; i++){
   updateLEDs(i);
   delay(delayTime); 
  }
}

/*
 * updateLEDs() - sends the LED states set in ledStates to the 74HC595
 * sequence
 */
void updateLEDs(int value){
  digitalWrite(latch, LOW);     //Pulls the chips latch low
  shiftOut(data, clock, MSBFIRST, value); //Shifts out the 8 bits to the shift 

register
  digitalWrite(latch, HIGH);   //Pulls the latch high displaying the data
  
  digitalWrite(Col1, HIGH);   //Pulls the Col1 high and turn on transistor-1
  digitalWrite(Col2, HIGH);   //Pulls the Col1 high and turn on transistor-2
  digitalWrite(Col3, HIGH);   //Pulls the Col1 high and turn on transistor-3
  digitalWrite(Col4, HIGH);   //Pulls the Col1 high and turn on transistor-4
}

/* updateLEDsLong() - sends the LED states set in ledStates to the 74HC595
 * sequence. Same as updateLEDs except the shifting out is done in software
 * so you can see what is happening.
 */ 
void updateLEDsLong(int value){
  digitalWrite(latch, LOW);    //Pulls the chips latch low
  for(int i = 0; i < 8; i++){  //Will repeat 8 times (once for each bit)
  int bit = value & B10000000; //We use a "bitmask" to select only the eighth 
                               //bit in our number (the one we are addressing this 

time through
  value = value << 1;          //we move our number up one bit value so next time 

bit 7 will be
                               //bit 8 and we will do our math on it
  if(bit == 128){digitalWrite(data, HIGH);} //if bit 8 is set then set our data 

pin high
  else{digitalWrite(data, LOW);}            //if bit 8 is unset then set the data 

pin low
  digitalWrite(clock, HIGH);                //the next three lines pulse the clock 

pin
  delay(1);
  digitalWrite(clock, LOW);
  }
  digitalWrite(latch, HIGH);  //pulls the latch high shifting our data into being 

displayed
}
//These are used in the bitwise math that we use to change individual LEDs
//For more details http://en.wikipedia.org/wiki/Bitwise_operation
int bits[] = {B00000001, B00000010, B00000100, B00001000, B00010000, B00100000, 

B01000000, B10000000};
int masks[] = {B11111110, B11111101, B11111011, B11110111, B11101111, B11011111, 

B10111111, B01111111};
/*
 * changeLED(int led, int state) - changes an individual LED 
 * LEDs are 0 to 7 and state is either 0 - OFF or 1 - ON
 */
 void changeLED(int led, int state){
   ledState = ledState & masks[led];  //clears ledState of the bit we are 

addressing
   if(state == ON){ledState = ledState | bits[led];} //if the bit is on we will 

add it to ledState
   updateLEDs(ledState);              //send the new LED state to the shift 

register
 }

Hippynerd

Pin 10 on the 74hc595 is the master reset, and needs to be active Low.
Also if you notice on the schemo, on the bottom left is the pinout for the IC's Power Pins 8(GND) and 16(VCC) and has Two .1uF caps needed for both IC's.
As I stated before, I powered VCC with an external 5V Power Supply, + to VCC, and - to Ground and also Ground to the Arduino as well for signal return.
By Offboard powering, the Led's are Brighter, and I don't pull too much from the Arduino.

I also have about a thousand Questions about C++ programming, but I have to settle for a few for now.
(1)
How would I set up a data file of different patterens, and make the program point to it.
(2)
How would I set it to Randomly make it's own patterns?

I'm Attaching the Datasheet for the 74hc595 for viewing

Thanks

74HC_HCT595.pdf (367 KB)

The code I wrote/modified, should run on your cube. You may need to change it a tiny bit, or use the CA or CC version (one is for common cathode planes, the other is common anode planes).
The major difference is the transistors, and you dont need to change the code for that. You just need to wire the cube like I did, or change the code to suit your wiring.

I also made this instructable, it has some pictures and stuff that are not on this forum thread, you may find good stuff there too:

that instructable is all about converting parallel to serial communication, but it has pertinent info about what you are trying to build.

I understand that the MR need to be connected to the power source(high), but I havnt seen one with a 1k resistor on it. The caps are called decoupling caps, and they are just there to make sure the shift registers dont go hungry.

The size of the resister on the columns will depend on the LEDs you use. Different color LEDs have different forward voltages. Its a simple calculation to figure out the right resistor, but you need to know your LEDs forward voltage, red ones are often around 1.9v, blue ones are often over 3 volts, I am unsure about the white ones that I used, but I think that they were in a flashlight running at 4.5v with no resistor, so I guessed and stuck 100 ohm resistors in.

C/C++ is object oriented programming, and a lot more robust than basic. a lot of that basic knowlege will be handy when writing new code, but object oriented programming is dramatically different. I consider myself a terrible programmer, but I manage to muddle through it.

The program I posted is a pattern based solution, you have to create the pattern for it to display, and it just repeats the pattern. There are other ways, like applying math and graphing it on the cube. or random, like you ask about, thats machine generated patterns and not static, but rather dynamic.

The cube works by holding a column high/low, while holding the plane high/low. In your example you will need to turn one plane low, and one column high to illuminate one LED.
The way i have the program setup, it sequences through each plane, with a loop, within that loop, it reads in 16 bits of data, and shuffles them out to the shift registers in a serial fashion.

To do what you want, you would do it completely different.

What you want to do is pick a random number(integer) between 1 and 4, and pick a number between 1 and 16. The first number you bring that plane low, the second number you bring the column high. That lights up an LED, then you wait a few miliseconds, and turn it off. Then repeat the procedure.
With the parallel program that was a bit straightforward, but with the shift registers, you will have to do it a bit differently, since you will need to pad the other 15 bits with 0s. Lets say you randomly pick plane 2, and LED 5, you will need to send the shift registers 4 0's, then a 1, then 11 more 0s.

I dont know how you could separate the data from the program. There is a way to get the arduino to read data via serial, its possible to run the cube from serial data, but I havnt done that.

I never had a vic20, but I had a c64, and a TRS-80, I did a lot of basic, back in the 70s 80s and 90s even. I didnt learn C until just before this century.

Hi Again Hippynerd

Seen your Instructable..Not Bad..
If I master the 4x4x4 cube I might try the 8x8x8 RGB Cube Next.

this is where I got the original code from

http://oomlout.com/a/products/ardx/circ-05/
I found this site helpful with some of the layouts for testing the LED's using the 74hc595 shift reg.

After I made the cube and mounted the components, I tested each LED by putting 5v to the base resister and one of the IC socket pins (1-7 and pin 15). this was done before the IC's were plugged in. Bread boarding the LED's and the 74hc595 first, and using a program that took input from the keyboard numbers 1-8, I could press the #1 key and the #1 LED would Light.
From there I used the perfaboard to mount the components with Point to Point wireing. The next board I will etch and put the Arduino Chip on board or use a Pic.

So you used to own a Commie 64 Eh..kinda shows your age :wink: I think my first kit computer was the Timax St Clair with 1k of memmory and a bubble keyboard.

Hope this post helps someone
TTFN
Sparkie

I remember the sinclair, and that horrible keyboard, similar to the atari 400 keyboard. I think they still use that style keyboard in restaurant cash registers.

The C64 wasnt my first computer, it wasnt even the first computer that I had at home.

I havnt built one with its own dedicated micro-controller. I got some cheap nanos that cost about what the parts for a basic build your own arduino with usb and voltage regulator.
Then I use connectors to plug the nano onto the cube.

Even though an arduino has a lot more memory than those older computers, you can easily fill the 32k memory with program. I have some RGB LEDs blinking on 30k of code, and it only lasts about 2 minutes before you've seen the whole program.

Hi Again

Have you had a chance to look at my code??
I have some questions i'd like to ask.

TTFN
Sparkie

FYI
Sparkie comes from my days as a radio operator in the Army. We were called sparks back then.

HI, just glancing over the code, this seems odd.
for(int i = 0; i < 256; i++){

I dont know if you can use a for statement, and there doesnt seem to be a next or else statement.

It also seems like it turns the LEDs on, and has a delay, then loop, and I think you will also want to turn those LEDs off. before looping. Maybe it doesnt matter...

Im not sure eather.
it may be different in C++
for(int i = 0; i < 256; i++){
I think it is saying that the int=0 and that i is less than 256 and then adds 1????
At least thats how I see it, if it had a <<256 it would mean to shift left 256 bits, which wouldn't make sence.
I think the line you are refering to is:

void loop() //runs over and over again
{

int delayTime = 100; //the number of milliseconds delay between led updates
for(int i = 0; i < 256; i++){
updateLEDs (i);
delay (delayTime);
}
}
I think it is saying that the int i is the place holder for ledState, the integer ledState waits for the update
from the line you mentioned....I Think....???
it took me a while to read it over and over again to semiunderstand it.

But you say it works on your 74hc595 setup??

let me know.

TTFN
Sparkie

What is a for loop?

for(int i = 0; i < 256; i++){
   ... //some code
}

When you declare a for loop, you have to supply up to four bits of information:
[1] The initialisation
[2] The conditional
[3] The end statement (for lack of a better name)
[4] The code to execute
In the format shown below.

for ( [1] ; [2] ; [3] ) {
  [4]
}

Any of the four options can be omitted if you don't need them.

The way it works is best summarised in the equivalent block of code below:

{
  [1]
  while ([2]) {
     [3]
     [4]
  }
}

At the start, the 'initialisation' is performed. This is usually something along the lines of creating a variable which will be used for the while() condtion.
Then the code enters a while loop whose condition is the 'conditional' part of the for loop. What that means is the block of code inside the while loop will be executed repeatedly while the conditional is true.
In each pass of the while loop, first the 'code to execute' portion is run, then the 'end statement' is run.

If we take the for loop you were wondering about, it becomes this:

{ //create a scope for the while loop.
  int i = 0; //create a variable called i and assign it a value of 0
  while (i < 256) { //check if i is less than 256. This is true at the beginning as i is initially 0
     ... //some code
     i++; //Increment i at the end of the loop.
  }
  //After 256 passes, i == 256, which mean the while() condition becomes false and so the loop completes.
}

Hopefully that helps. If there is anything you are unclear on, let me know.

Good Morning Tom

What you said makes sence to me. The code I offered in this Fourm was taken from someone elses code. I'd have to check my files to find out who, but I don't think it's important in this case. Oh I found the website:

http://oomlout.com/a/products/ardx/circ-05/
Check out the site and copy the code to study.

The code I got, I changed a few lines to make the 74hc595 turn on the four (4) transistors needed for this 4x4x4 Cube.

Have you look at the code??
Everyones input will be helpfull to me for a better understanding of C and C++.

I'm hoping to use Hippynerds Data to set different patterns, but havent got that far yet. I just keep reading my and others code to see whats been done, Program wise, for the Cube.

As mentioned before, I only have progremmed in Basic many many years ago, and didn't have a need to learn C or C++ until I bought an Arduino Uno two years ago.

But again Tom, Thanks for your input and hope to hear from you again.

Hi Hippynerd

I found what I think is an answer to your reply #42

It explanes about that for statement:
for(int i=0; i<256; i++)

Aparently it sets up a chunk of memory in the stacks or heap...

http://www.societyofrobots.com/member_tutorials/book/export/html/202

Some microcontroller compilers do allow you to dynamically allocate memory – but with this one enormous proviso:- The memory is automatically freed when the method that allocated it in the first place exits. How does that work? Well its then very similar to the stack. It will just use the heap pointer to allocate new memory and then move it back to its original position when the method exits. Therefore: you can never have any fragmentation in the heap. However: its usage is fairly limited.

Consider this code:-


void myMethod(){

char buffer[256];

for(int I=0; I<256;I++){

buffer*=I;*

  • }*

}

--------------------------------------------------------------------------------
This will allocate space for ‘buffer’ by moving the stack pointer down by 256 bytes.

Whereas this code:-

--------------------------------------------------------------------------------
void myMethod(){

_ char buffer* = malloc(256);_

  • for(int I=0; I<256;I++){*

_ buffer->=I;_

* }*

}

--------------------------------------------------------------------------------
will allocate space for ‘buffer’ by moving the heap pointer up by 256 bytes. So they are almost identical.

But you must be careful not to do the following:-

--------------------------------------------------------------------------------
char buffer*;

void myMethod(){

* buffer = malloc(256);*

* for(int I=0; I<256;I++){*

_ buffer->=I;_

* }*

}

--------------------------------------------------------------------------------
since ‘buffer’ is assigned a value in the method – but, unlike a ‘proper’ C compiler - once the method exits then ‘buffer’ is referring to a lump of memory that is now being used by other things. So changing some of its values will corrupt something else. Bad!

So dynamic memory allocation should generally be avoided and we will not discuss it any further!!

I think I am right in saying that there is an important omission from the example you posted.
This:

void myMethod(){
    char buffer* = malloc(256);
    for(int I=0; I<256;I++){
        buffer[l]=I;
    }
   //When the function returns, the 'buffer' memory remains allocated, but the pointer to this memory is lost.
   //As nothing now knows the address of the allocated memory, nothing can use it. This is known as a memory leak.
}

Should be:

void myMethod(){
    char buffer* = malloc(256);
    for(int I=0; I<256;I++){
        buffer[l]=I;
    }
    free(buffer); //free the memory otherwise there is a memory leak.
}

Hi Tom

The message you speak of is one I tol ok from the internet. the explanation was quite extensive so I didn't get it all in my cut and past :wink:

The more I look at all the codes, the more my head spins. I think it'll take some time before I really catch on.
I bought a book on C++ How To Program by Deitel & Deitel and I'm reading it from the start.

Do I understand the the program has a header and a body??
And how long is the body of the program, or is it everything after the header??

Thanks again for your input.
Sparkie