http://Bj83.de

4x4x4 Led Cube with Arduino Pro mini clone

4x4x4 cube with Arduino Pro Mini

4x4x4 cube with Arduino Pro Mini

I got some spare time at the weekend and could finally build the 4x4x4 multiplexing led cube. It took me about 5-6 hours to finish this project. I need much more practice with wiring XD This took the most time beside the soldering of the leds.

My target was to learn more about arduino programming and building something as cheap as possible without cut backs.

There are more than enough Tutorials at the Web, so i wont duplicate their content, and just presenting my own result of it 🙂

 

So this was my Shopping list:

  • 64 x Led’s (0.065 cent each)
  • 4 x NPN Transistors (15cent each)
  • 2 x 74HC595 Registers (20cent each)
  • 1 x Arduino Pro Mini clone from china (1,40 euro)
  • 1 x connector for a 9V Block Battery (about 5cent)
  • 4 x 2,2k Ohm Resistors (4cent each)
  • 16 x 220 Ohm Resistors (4cent each)
  • 1 x breadboard to mount everything (about 40cent)
  • 1 x Female Sockets (for mounting the chip) (about 5cent, needed half of an row..)
  • some wire for the wiring, shrink tubes and more solder than i thought.. (about 30cent)
  • battery pack holder (4xAA) (about 30cent)

All items are more or less from the asia area, but hey, isn’t nearly all elecronic from asia? 😉 So i payed around 4,50 Euro for the whole thing.


4x4x4 cube soldering leds

4x4x4 cube soldering leds

4x4x4 cube led test multi layer

4x4x4 cube led test multi layer

4x4x4 cube led test single layer

4x4x4 cube led test single layer

The soldering of the led’s took about 1/3 of the time, because i made my on matrix Layout. The middle Led’s are connected to the corners.

These Leds have an really nice looking green color, but if you want to make a cube your own, i would recommend using difuse or milky led’s. If mine are powered up, the light the leds one level above too, so its a bit hard to recognize which row is glowing at the moment. I tried to paint the leds at the Bottom with an edding black, but yes… next time before soldering xD

For positioning i used an old cardboard-box and put some whole freehand into it, thats why bit of the Leds are not perfectly aligned :p


4x4x4 cube npn transistors

4x4x4 cube npn transistors

4x4x4 cube 74HC959 registers

4x4x4 cube 74HC959 registers

After placing the whole structure on the board i put the NPN transistors with their corresponding resistors (2,2k) in place, and put the two 595 registers at front.

The placing i know from two other tries of cubes (2x2x2) so later it would be easer to solder then on top an beneath.

Big mistake i made was trying to put the led resistors below the led structure after soldering the leds onto the board… was hard to place the right to their led..


4x4x4 cube bottom wiring

4x4x4 cube bottom wiring

4x4x4 cube wiring registers

4x4x4 cube wiring registers

4x4x4 cube wiring the grounds

4x4x4 cube wiring the grounds

4x4x4 cube wiring chip

4x4x4 cube wiring chip

The bottom wiring took about 3/4 of the time… i know i could place some soldering lines on the board, but i dont had an plan how to wire it, big mistake no. two!

Soldering all the connections to the registers were a nightmare! so many pins an so less space xD

And by the way i have to solder with an open window, and at the last part there was a cold wind that makes troubles with the solder points… thats why they look a bit… strange..


I took the Arduino Example Code and extended and rewritten the part for the animation/multiplexing part. The code take about 12% for the Programmspace and about 13% for global Variables (for example animation array).

It displays three animations in cycle. “Shrinking Cube”, Random Leds, and something like “rainfall”

int latchPin = 8;
int clockPin = 12;
int dataPin  = 11;

int powerPin = 2;
int statusLed = 13;

int DisplayDuration = 100;

int layerFourPin  = 7;
int layerThreePin = 6;
int layerTwoPin   = 5;
int layerOnePin   = 4;

byte animation[10][4][2];
int GroundLayer = 0;
int FirstLayer = 1;
int SecondLayer = 2;
int ThirdLayer = 3;

int currentAnim = 0;

int activeLayer = 0;

void setupAnimation(){
  animation[0][GroundLayer][0] = 0x80; // 10000000
  animation[0][GroundLayer][1] = 0x00; // 00000000
  animation[0][FirstLayer][0]  = 0x40; // 01000000
  animation[0][FirstLayer][1]  = 0x00; // 00000000
  animation[0][SecondLayer][0] = 0x20; // 00100000
  animation[0][SecondLayer][1] = 0x00; // 00000000
  animation[0][ThirdLayer][0]  = 0x10; // 00010000
  animation[0][ThirdLayer][1]  = 0x00; // 00000000

  animation[1][GroundLayer][0] = 0xF9; // 11111001
  animation[1][GroundLayer][1] = 0x9F; // 10011111
  animation[1][FirstLayer][0]  = 0x90; // 10010000
  animation[1][FirstLayer][1]  = 0x09; // 00001001
  animation[1][SecondLayer][0] = 0x90; // 10010000
  animation[1][SecondLayer][1] = 0x09; // 00001001
  animation[1][ThirdLayer][0]  = 0xF9; // 11111001
  animation[1][ThirdLayer][1]  = 0x9F; // 10011111

  animation[2][GroundLayer][0] = 0x00; // 00000000
  animation[2][GroundLayer][1] = 0x00; // 00000000
  animation[2][FirstLayer][0]  = 0x06; // 00000110
  animation[2][FirstLayer][1]  = 0x60; // 01100000
  animation[2][SecondLayer][0] = 0x06; // 00000110
  animation[2][SecondLayer][1] = 0x60; // 01100000
  animation[2][ThirdLayer][0]  = 0x00; // 00000000
  animation[2][ThirdLayer][1]  = 0x00; // 00000000
}

void setup() {
  pinMode(latchPin, OUTPUT);
  
  pinMode(powerPin, OUTPUT);
  digitalWrite(powerPin, HIGH);

  pinMode(statusLed,OUTPUT);
  digitalWrite(statusLed, HIGH);

  pinMode(layerFourPin, OUTPUT);
  pinMode(layerThreePin, OUTPUT);
  pinMode(layerTwoPin, OUTPUT);
  pinMode(layerOnePin, OUTPUT);
  
  Serial.begin(9600);

  setupAnimation();

  blinkAll_2Bytes(2,500);
}

void turnLayerOff(){
  digitalWrite(layerFourPin, LOW);
  digitalWrite(layerThreePin, LOW);
  digitalWrite(layerTwoPin, LOW);
  digitalWrite(layerOnePin, LOW);
}

void showFrame(int Sequenz){
  for(int i=0;i<DisplayDuration;i++){
    turnLayerOff();
    digitalWrite(latchPin, LOW);
    digitalWrite(layerOnePin, HIGH);
    shiftOut(dataPin, clockPin, animation[Sequenz][FirstLayer][0]);   //FirstLayer
    shiftOut(dataPin, clockPin, animation[Sequenz][FirstLayer][1]);
    digitalWrite(latchPin, HIGH);

    turnLayerOff();
    digitalWrite(latchPin, LOW);
    digitalWrite(layerTwoPin, HIGH);
    shiftOut(dataPin, clockPin, animation[Sequenz][SecondLayer][0]);   //SecondLayer
    shiftOut(dataPin, clockPin, animation[Sequenz][SecondLayer][1]);
    digitalWrite(latchPin, HIGH);

    turnLayerOff();
    digitalWrite(latchPin, LOW);
    digitalWrite(layerThreePin, HIGH);
    shiftOut(dataPin, clockPin, animation[Sequenz][ThirdLayer][0]);   //ThirdLayer
    shiftOut(dataPin, clockPin, animation[Sequenz][ThirdLayer][1]);
    digitalWrite(latchPin, HIGH);
  
    turnLayerOff();
    digitalWrite(latchPin, LOW);
    digitalWrite(layerFourPin, HIGH);
    shiftOut(dataPin, clockPin, animation[Sequenz][GroundLayer][0]);   
    shiftOut(dataPin, clockPin, animation[Sequenz][GroundLayer][1]);
    digitalWrite(latchPin, HIGH);
  }
}

void randAnim(int i){
  switch(i){
    case 1: 
      shiftOut(dataPin, clockPin, 0x80);   
      shiftOut(dataPin, clockPin, 0x00);
      break;
    case 2:
      shiftOut(dataPin, clockPin, 0x40);   
      shiftOut(dataPin, clockPin, 0x00);
      break;
    case 3: 
      shiftOut(dataPin, clockPin, 0x20);   
      shiftOut(dataPin, clockPin, 0x00);
      break;
    case 4: 
      shiftOut(dataPin, clockPin, 0x10);   
      shiftOut(dataPin, clockPin, 0x00);
      break;
    case 5: 
      shiftOut(dataPin, clockPin, 0x08);   
      shiftOut(dataPin, clockPin, 0x00);
      break;
    case 6: 
      shiftOut(dataPin, clockPin, 0x04);   
      shiftOut(dataPin, clockPin, 0x00);
      break;
    case 7: 
      shiftOut(dataPin, clockPin, 0x02);   
      shiftOut(dataPin, clockPin, 0x00);
      break;
    case 8: 
      shiftOut(dataPin, clockPin, 0x01);   
      shiftOut(dataPin, clockPin, 0x00);
      break;
    case 9: 
      shiftOut(dataPin, clockPin, 0x00);   
      shiftOut(dataPin, clockPin, 0x80);
      break;
    case 10: 
      shiftOut(dataPin, clockPin, 0x00);   
      shiftOut(dataPin, clockPin, 0x40);
      break;
    case 11: 
      shiftOut(dataPin, clockPin, 0x00);   
      shiftOut(dataPin, clockPin, 0x20);
      break;
    case 12: 
      shiftOut(dataPin, clockPin, 0x00);   
      shiftOut(dataPin, clockPin, 0x10);
      break;
    case 13: 
      shiftOut(dataPin, clockPin, 0x00);   
      shiftOut(dataPin, clockPin, 0x08);
      break;
    case 14: 
      shiftOut(dataPin, clockPin, 0x00);   
      shiftOut(dataPin, clockPin, 0x04);
      break;
    case 15: 
      shiftOut(dataPin, clockPin, 0x00);   
      shiftOut(dataPin, clockPin, 0x02);
      break;
    case 16: 
      shiftOut(dataPin, clockPin, 0x00);   
      shiftOut(dataPin, clockPin, 0x01);
      break;
  }
}

void rainfallAnim(){
  int led = rand() % 16 + 1;
  for(int c = 0; c < 4; c++){
    turnLayerOff();
    switch(c){
      case 3: 
        digitalWrite(layerOnePin, HIGH);
        break;
      case 2: 
        digitalWrite(layerTwoPin, HIGH);
        break;
      case 1: 
        digitalWrite(layerThreePin, HIGH);
        break;
      case 0: 
        digitalWrite(layerFourPin, HIGH);
        break;
    }
    for(int i=0;i<DisplayDuration;i++){
      digitalWrite(latchPin, LOW);
      randAnim(led);
      digitalWrite(latchPin, HIGH);
    }
  }
}

void randFrame(){
  int layer = rand() % 4 + 1;
  int led = rand() % 16 + 1;

  for(int i=0;i<DisplayDuration;i++){
    turnLayerOff();
    digitalWrite(latchPin, LOW);
    switch(layer){
      case 1: 
        digitalWrite(layerOnePin, HIGH);
        break;
      case 2: 
        digitalWrite(layerTwoPin, HIGH);
        break;
      case 3: 
        digitalWrite(layerThreePin, HIGH);
        break;
      case 4: 
        digitalWrite(layerFourPin, HIGH);
        break;
    }
    randAnim(led);
    digitalWrite(latchPin, HIGH);
  }
}

void loop() {
  DisplayDuration = 400;
  if(currentAnim < 20){
    showFrame(1);
    showFrame(2);
  }
  if(currentAnim > 20 && currentAnim < 200){ 
    randFrame();
  }
  if(currentAnim > 200){
    rainfallAnim();
  }
  currentAnim++;
  if(currentAnim == 400){
    currentAnim = 0;
  }
}

void shiftOut(int myDataPin, int myClockPin, byte myDataOut) {
  int i=0;
  int pinState;
  pinMode(myClockPin, OUTPUT);
  pinMode(myDataPin, OUTPUT);
  digitalWrite(myDataPin, 0);
  digitalWrite(myClockPin, 0);
  for (i=7; i>=0; i--)  {
    digitalWrite(myClockPin, 0);
    if ( myDataOut & (1<<i) ) { pinState= 1; }
    else { pinState= 0; }
    digitalWrite(myDataPin, pinState);
    digitalWrite(myClockPin, 1);
    digitalWrite(myDataPin, 0);
  }
  digitalWrite(myClockPin, 0);
}

void blinkAll_2Bytes(int n, int d) {
  digitalWrite(latchPin, 0);
  shiftOut(dataPin, clockPin, 0);
  shiftOut(dataPin, clockPin, 0);
  digitalWrite(latchPin, 1);
  delay(200);
  for (int x = 0; x < n; x++) {
    digitalWrite(latchPin, 0);
    shiftOut(dataPin, clockPin, 255);
    shiftOut(dataPin, clockPin, 255);
    digitalWrite(latchPin, 1);
    delay(d);
    digitalWrite(latchPin, 0);
    shiftOut(dataPin, clockPin, 0);
    shiftOut(dataPin, clockPin, 0);
    digitalWrite(latchPin, 1);
    delay(d);
  }
}

At last a tipp for the ones that need a 5V/3.3V output from a Pro Mini. Simply put an digital pin to HIGH or 1, these pins have an output of 5V.

Leave a Reply

Your email address will not be published. Required fields are marked *

Follow

Get every new post on this blog delivered to your Inbox.

Join other followers: