3x3 led cube by a n00b

Hello everyone,
this is my first post here on the arduino forums. I just got my first arduino a week ago and i have almost no programming knowledge so bear with me.

i am aware that there is a forum for multiplexing and multiple leds, but my question is not so much about that, so thats why i have it here.

i know you are going to laugh when you see my code, but basically i have my cube set up like this:

i built a 3x3 cube and i have it so that each layer, or you could say plane, has a ground that is separate from the other layers. then, i have all of the anodes are connected to in collums. so basically i have 3 negative contacts and 9 positive contacts. since there is only one ground on the arduino, i used three transistors each connected to a different pin, to switch the ground between layers. i have the 9 columns connected directly to the 9 remaining pins on the arduino.

here is a diagram of my setup

and here is a picture

based on this setup, here is how my code turned out in order to light up the bottom layer of leds

                    digitalWrite(lev1,HIGH);     //lev1,lev2, and lev3 refer to the pins that are connected to the transistors
                    digitalWrite(lev2,LOW);      // to provide a ground to each of the layers
                    digitalWrite(lev3,LOW);
                    
                    digitalWrite(led1,HIGH);     //led1 to led9 are the pins that connect to each column 
                    digitalWrite(led2,HIGH);
                    digitalWrite(led3,HIGH);
                   
                    digitalWrite(led4,HIGH);
                    digitalWrite(led5,HIGH);
                    digitalWrite(led6,HIGH);
                    
                    digitalWrite(led7,HIGH);
                    digitalWrite(led8,HIGH);
                    digitalWrite(led9,HIGH);

with this code you can figure that the the entire bottom plane of leds would light up.
but, lets say i wanted one led in the bottom level to light up and an led on the second level to light up that is in a different column. well, with my setup i would have to turn on the ground to both level on and two and if i turn on any of the led pins, all of the leds in that column would light up.
so, here is what i did

                    digitalWrite(lev1,HIGH);
                    digitalWrite(lev2,LOW);
                    digitalWrite(lev3,LOW);
                    
                    digitalWrite(led1,HIGH);
                    digitalWrite(led2,LOW);
                    digitalWrite(led3,LOW);
                  
                    digitalWrite(led4,LOW);
                    digitalWrite(led5,LOW);
                    digitalWrite(led6,LOW);
                   
                    digitalWrite(led7,LOW);
                    digitalWrite(led8,LOW);
                    digitalWrite(led9,LOW);
                  
                   delay(5);

                    digitalWrite(lev1,LOW);
                    digitalWrite(lev2,HIGH);
                    digitalWrite(lev3,LOW);
                    
                    digitalWrite(led1,LOW);
                    digitalWrite(led2,HIGH);
                    digitalWrite(led3,LOW);
                  
                    digitalWrite(led4,LOW);
                    digitalWrite(led5,LOW);
                    digitalWrite(led6,LOW);
                   
                    digitalWrite(led7,LOW);
                    digitalWrite(led8,LOW);
                    digitalWrite(led9,LOW);
 
                    delay(5);

the leds light up individually with out all of the leds in the column lighting up. and with a delay that short you dont notice it flash back and forth

this is were my problems lie:

i have each pattern defined as a function, for example sequence1() is a pattern sequence2() is a different pattern.
i want my arduino to cycle through the patterns (after a set time, not by user input) and i need it to repeat the pattern/function until it goes to the next one.

here is what i have tried

  unsigned long time=millis();               
  unsigned long lasttime=0;            
  unsigned long x;                            //the difference between time and lasttime will be stored in x
  int seq;                                     // this will tell the loop which function/sequence to run

void setup()
{

seq=1;                                                    //i want to start with the first sequence
lasttime=0                                                //last time will be 0     
                                                          //here is where i have all of my patterns 
void sequence4()
{
                    digitalWrite(lev1,HIGH);         // this is an example of one pattern 
                    digitalWrite(lev2,HIGH);
                    digitalWrite(lev3,HIGH);
                    
                    digitalWrite(led1,HIGH);
                    digitalWrite(led2,LOW);
                    digitalWrite(led3,LOW);
                    
                    digitalWrite(led4,LOW);
                    digitalWrite(led5,HIGH);
                    digitalWrite(led6,LOW);
                    
                    digitalWrite(led7,LOW);
                    digitalWrite(led8,LOW);
                    digitalWrite(led9,HIGH);
                    
                    
                    delay(val);
                    
                    
                    digitalWrite(lev1,HIGH);
                    digitalWrite(lev2,HIGH);
                    digitalWrite(lev3,HIGH);
                    
                    digitalWrite(led1,LOW);
                    digitalWrite(led2,HIGH);
                    digitalWrite(led3,LOW);
                    
                    digitalWrite(led4,LOW);
                    digitalWrite(led5,HIGH);
                    digitalWrite(led6,LOW);
                    
                    digitalWrite(led7,LOW);
                    digitalWrite(led8,HIGH);
                    digitalWrite(led9,LOW);
                    
                    
                    delay(val);
                    
                    
                    digitalWrite(lev1,HIGH);
                    digitalWrite(lev2,HIGH);
                    digitalWrite(lev3,HIGH);
                    
                    digitalWrite(led1,LOW);
                    digitalWrite(led2,LOW);
                    digitalWrite(led3,HIGH);
                    
                    digitalWrite(led4,LOW);
                    digitalWrite(led5,HIGH);
                    digitalWrite(led6,LOW);
                    
                    digitalWrite(led7,HIGH);
                    digitalWrite(led8,LOW);
                    digitalWrite(led9,LOW);
                    
                    
                    delay(val);
                    
                    
                    digitalWrite(lev1,HIGH);
                    digitalWrite(lev2,HIGH);
                    digitalWrite(lev3,HIGH);
                    
                    digitalWrite(led1,LOW);
                    digitalWrite(led2,LOW);
                    digitalWrite(led3,LOW);
                    
                    digitalWrite(led4,HIGH);
                    digitalWrite(led5,HIGH);
                    digitalWrite(led6,HIGH);
                    
                    digitalWrite(led7,LOW);
                    digitalWrite(led8,LOW);
                    digitalWrite(led9,LOW);
                    
                    
                    delay(val);
                    
                    
}
}

void loop()                                                          // i think this is where my problem is
{

x=time-lasttime;

if(x==3000)                                                         
  {
    seq=seq+1;                                                    //after 3 seconds, increase seq by 1, and make lasttime equal to the current time
    lasttime=time;
   }

if (seq==1)
 {
   sequence1();
  }

if (seq=3)
  {
   sequence3();
   }

}

what am i doing wrong?

A simpler way might be to write the patterns as elements in an array

so maybe like this

byte cathodes[3] = {2,3,4};
byte ledPins[9]={5,6,7,8,9,10,11,12,13};
 // declare these as outputs in setup
byte x; // used in counters
byte y;
byte z;
// sequence of 3 patterns to be written
byte 9x9Array[9][9]={
  {1,1,1,0,0,0,0,0,0}, // will be level 1; row 1,columns 0-8
  {0,0,0,1,1,1,0,0,0}, // level 2
  {0,0,0,0,0,0,1,1,1}, // level 3
  {0,0,0,1,1,1,0,0,0}, // will be level 1
  {0,0,0,0,0,0,1,1,1}, // level 2
  {1,1,1,0,0,0,0,0,0}, // level 3
  {0,0,0,0,0,0,1,1,1}, // will be level 1
  {1,1,1,0,0,0,0,0,0}, // level 2
  {0,0,0,1,1,1,0,0,0}, // level 3
};
void setup(){
// declare the output pins
} // end void setup
// then in loop:
void loop(){
for (z = 0; z<3; z=z+1){
    for (x = 0; x<3; x=x+1){ // cycle thru the layers 0,1,2
        for (y = 0; y<9; y=y+1){  // cycle thru the LEDs, 0-8
        digitalWrite (ledPins[y], 9x9array[z+x][y]); // so write to the pins 5,6,7,8... with the data at 9x9array[rows][columns]
        }  // end writing the 9 columns
       digitalWrite(cathodes[x], HIGH); // turn on the ground
       delay (100); // hold the displayed pattern a bit
       digitalWrite (cathodes[x], LOW);  // turn off the ground
    } // next row
}  // next set of rows
} // end void loop
  1. Do you have a current limiting resistors (9 overall) ?
  2. I'm not sure you can declare: unsigned long time=millis();
    Probably, better just: unsigned long time;
    and initialize it it in the setup: time=millis();

i could use an array, however my cube works perfectly with the code i already have (as long as there is only one sequence in the loop). i want to fully understand what i have before i start learning a new concept.

i simply need to know how to keep a function looping and then, after a fixed amount of time, loop a different function

i did try changing the way i defined time and it still does not work right

  time = millis();  // update your "time" regularly, not once

x=time-lasttime;  // you starting with lasttime = 0, and undefined "time"
                                    
if(x==3000)                  // why you expecting exact 3000 value?
                                     // try x > 3000                                        
  {
    seq=seq+1;
    lasttime=time;
   }

if (seq==1)
 {
   sequence1();
  }

if (seq=3)  // !!! you mean seq == 3 ?
  {
   sequence3();
   }

}

thanks magician. that worked fine for me. i guess i just had the variables in the wrong places. how do you suggest i have the program continue to cycling through after it gets to the last sequence

Ok, it's easy:

if( x > 3000 )       // hope it's like in your sckech                               
  {
    seq=seq+1;
    lasttime=time;

if ( seq > 4 ) seq = 1;   // assuming that you have 4 sequences so far, change 4 to right number if  you have more than 4.
   }

marban: I stumbled on this topic trying to trouble shoot my 3x3 cube. I'm fairly new to coding and building circuits, however I seem to be approaching this project the same way you did. Right now I'm only testing one face of my cube (i.e. layers 1,2,3 and columns, 1,2,3 on a breadboard). I have everything connected in the same manner you do (other than I'm using different I/O pin assignments, but my connections are the same other wise) I'm using 3 ksp222a transistors to control the levels. The emitters are connected to ground, the base pins are each connected to 100ohm resistors and then to their respective I/O pins to control them and my collector pins are connected to the cathode layers I want to control.
The LED's I'm using have these specs:
5mm diameter
520 nm wavelength
3.2-3.8V Forward Voltage, at 20mA current
8000 mcd typical brightness
Viewing Angle : ±10 degrees
Maximum continuous current: 30mA
I've connected the LED columns to their respective I/O pins through 100Ohm resistors.

Here is the code I'm currently using:

#define C1 1
#define C2 2
#define C3 3
#define L1 11
#define L2 12
#define L3 13

void setup()
{
  pinMode(C1, OUTPUT);
  pinMode(C2, OUTPUT);
  pinMode(C3, OUTPUT);
  pinMode(L1, OUTPUT);
  pinMode(L2, OUTPUT);
  pinMode(L3, OUTPUT);
}
void loop()
{
digitalWrite(L1,HIGH);
  digitalWrite(L2,HIGH);
  digitalWrite(L3,HIGH);
  
  digitalWrite(C1,HIGH);
  digitalWrite(C2,LOW);
  digitalWrite(C3,LOW);
  
  delay(500);
  
  //all lvl 2
  digitalWrite(L1,HIGH);
  digitalWrite(L2,HIGH);
  digitalWrite(L3,HIGH);
  
  digitalWrite(C1,LOW);
  digitalWrite(C2,HIGH);
  digitalWrite(C3,LOW);
  
  delay(500);
  
  //all lvl 3
  digitalWrite(L1,HIGH);
  digitalWrite(L2,HIGH);
  digitalWrite(L3,HIGH);
  
  digitalWrite(C1,LOW);
  digitalWrite(C2,LOW);
  digitalWrite(C3,HIGH);
  
  delay(500);
  
}

(code tags added by moderator)
My assumption was that this would light up each column individually, and it does, however the C1 LED's barely light up and when I tried changing the I/O pin that conrtolled the C1 LED's they stayed on throughout the entire loop. I'm not quite sure what I'm doing wrong or if I've got a bad connection / part in the circuit. Any troubleshooting ideas would help at this point. Thanks!

So you have basically this, but with only three columns wired up.

It would appear that you are driving what I show connected to D11-D19 with the L-names, and the transistors with the C names.

Otherwise you are turning on all layers at once, which kinda defeats the purpose of multiplexing. And stresses the Arduino output pin by driving 3 LEDs at the same time.

Or perhaps you are wired up some other way?

before anyone wastes their time responding to my comment. I finally discovered one of my output pins is broken :confused: so it works now...