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.
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
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..
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.