The Arduino Project Thread

DaktologistDaktologist Global Moderator
edited August 2012 in Life
Well my shipment of electronic components arrived today allowing me to have a good restock of things I had ran out of or needed to replace, that and get a bigger breadboard as the one that came with my arduino takes the piss. It is small as fuck and I managed to burn holes in it from the numerous short circuits I accidently created while testing things :facepalm:. Anyway I got a few Shift Registers, and for those who own an arduino know the board only has 13 digital outputs which is great until you need more outputs. This is where the shift register comes in, it uses only three outputs and provides eight outputs or if you stack another shift register on top provides sixteen outputs. There is no real limit on how many you can stack on top so you can run LED cubes off of an arduino with ease.

Below you will see the first circuit based on a 74HC595N shift register. It controls eight green LEDs which sweep back and forth in sequence. This would normally require eight outputs from the arduino but with the 74HC595N, only requires three. Digital pin two provides data to the shift register, pin three provides the latching signal and pin four provides the clock signal. There is also ground and +5v lines to power the device and associated LEDs. The dimple in one end of the device denotes the end with pins 1 and 16, 1 being on the left as per the diagram below.

SingleShiftRegister_small.jpg

IMG_0582a.jpg

The code that runs the circuit is below
int dataPin = 2;        //Define which pins will be used for the Shift Register control
int latchPin = 3;
int clockPin = 4;

int seq[14] = {1,2,4,8,16,32,64,128,64,32,16,8,4,2};       //The byte sequence

void setup()
{
    pinMode(dataPin, OUTPUT);       //Configure each IO Pin
    pinMode(latchPin, OUTPUT);
    pinMode(clockPin, OUTPUT);
}

void loop()
{
    for (int n = 0; n < 14; n++)
    {
        digitalWrite(latchPin, LOW);             //Pull latch LOW to start sending data
        shiftOut(dataPin, clockPin, MSBFIRST, seq[n]);          //Send the data
        digitalWrite(latchPin, HIGH);            //Pull latch HIGH to stop sending data
        delay(75);
    }
}

So your circuit works as expected and you now have eight LEDs sweeping in sequence in front of you. Now we are going to add a second shift register. Connecting the second device is the same as the first. There is a pin called Overflow on the 74HC595N which will be joined to the data pin on the second device. This carries over the data sent to the first device and if the first bit of code you tried is running, you will see it replicated on the second device. Your power, latching and clock lines you just join between each device as shown below.

DualShiftRegister.jpg

IMG_0584a.jpg

After connecting everything correctly and ignoring the LEDs on the data, overflow and clock lines (they aren't needed), upload the next bit of code below
int dataPin = 2;        //Define which pins will be used for the Shift Register control
int latchPin = 3;
int clockPin = 4;

int seq1[14] = {1,2,4,8,16,32,64,128,64,32,16,8,4,2};  //The array for storing the 
                        // byte #1 value
int seq2[14] = {128,64,32,16,8,4,2,1,2,4,8,16,32,64};  //The array for storing the 
                        // byte #2 value

void setup()
{
    pinMode(dataPin, OUTPUT);       //Configure each IO Pin
    pinMode(latchPin, OUTPUT);
    pinMode(clockPin, OUTPUT);
}

void loop()
{
    for (int x = 0; x < 14; x++)         //Array Index
    {
        digitalWrite(latchPin, LOW);            //Pull latch LOW to start sending data
        shiftOut(dataPin, clockPin, MSBFIRST, seq1[x]);         //Send the data byte 1
        shiftOut(dataPin, clockPin, MSBFIRST, seq2[x]);         //Send the data byte 2
        digitalWrite(latchPin, HIGH);           //Pull latch HIGH to stop sending data
        delay(75);
    }
}

You should have two sets of sweeping LEDs sweeping in opposite directions if everything is done correctly.

66464f.jpg

Again there is no real limit on how many can be stacked together but after a while, powering a large amount may become a problem. Just remember to use series resistors with your LEDs as they don't like a lot of current. I used a single 390 ohm resistor on the ground bus feeding the LEDs as i'm a lazy cunt although as only one or two are illuminated at once, it doesn't make too much difference IMO.

Comments

  • edited August 2012
    Some of the things you can do with Arduino is amazing. I went to a science convention last year as someone I knew was speaking there, and he'd made some incredible stuff (robots, RC cars which drive themselves, etc) all based around the Arduino and some basic programming. I was really impressed.
  • DaktologistDaktologist Global Moderator
    edited August 2012
    Well I finally built an LED cube tonight. It is 3*3*3 so requires 27 LEDs total. It took me around an hour to build and is pretty awesome but when I get some more LEDs i'll build a larger one.

    So if you want to build one you will need...
    • 27 LEDs
    • Soldering iron and solder
    • A breadboard or similar
    • Wire
    • An Arduino
    • A block of wood
    • A drill and the correct sized drill bit (5mm LED use 5 mm drill bit etc.)


    Firstly make your soldering jig. Drill 9 holes around 2 cm apart in a 3*3 grid. Now take your LEDs and insert them leads up into the holes. This will hold them in place so you can solder them easily. Start at the top left, bend the cathode pin (short one) across to the next cathode pin. Do this to each LED so all the cathodes are joined together like below.

    ledsolderingguide.jpg

    Repeat as above two more times until you have three 3*3 grids of LEDs. Now solder the anode pins together so you end up with nine leads at the bottom of your cube. Now insert your finished cube into your breadboard. Connect a lead into the bus on your breadboard that each cube lead inserts into. Take three bits of wire and solder each wire to each cathode row (three in total). Connect from top to bottom, each wire to Analogue pins 3,4,5 respectively. Take the anode leads and connect them to the Arduino as shown below.

    anodeconnection.jpg

    Now connect your Arduino board to your PC and upload the following code. Due to its size, the Arduino will take a couple of seconds to begin running the cube after power on.
    #include <avr/pgmspace.h> // allows use of PROGMEM to store patterns in flash
    
    #define CUBESIZE 3
    #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
    B111, B111, B111, B111, B111, B111, B111, B111, B111, 5,
    B000, B000, B000, B000, B000, B000, B000, B000, B000, 1,
    B111, B111, B111, B111, B111, B111, B111, B111, B111, 5,
    B000, B000, B000, B000, B000, B000, B000, B000, B000, 1,
    // flash each LED in sequence:
    // Left->Right column, then Top->Bottom row, then Upper->Lower plane
    B100, B000, B000, B000, B000, B000, B000, B000, B000, 1,
    B010, B000, B000, B000, B000, B000, B000, B000, B000, 1,
    B001, B000, B000, B000, B000, B000, B000, B000, B000, 1,
    B000, B100, B000, B000, B000, B000, B000, B000, B000, 1,
    B000, B010, B000, B000, B000, B000, B000, B000, B000, 1,
    B000, B001, B000, B000, B000, B000, B000, B000, B000, 1,
    B000, B000, B100, B000, B000, B000, B000, B000, B000, 1,
    B000, B000, B010, B000, B000, B000, B000, B000, B000, 1,
    B000, B000, B001, B000, B000, B000, B000, B000, B000, 1,
    B000, B000, B000, B100, B000, B000, B000, B000, B000, 1,
    B000, B000, B000, B010, B000, B000, B000, B000, B000, 1,
    B000, B000, B000, B001, B000, B000, B000, B000, B000, 1,
    B000, B000, B000, B000, B100, B000, B000, B000, B000, 1,
    B000, B000, B000, B000, B010, B000, B000, B000, B000, 1,
    B000, B000, B000, B000, B001, B000, B000, B000, B000, 1,
    B000, B000, B000, B000, B000, B100, B000, B000, B000, 1,
    B000, B000, B000, B000, B000, B010, B000, B000, B000, 1,
    B000, B000, B000, B000, B000, B001, B000, B000, B000, 1,
    B000, B000, B000, B000, B000, B000, B100, B000, B000, 1,
    B000, B000, B000, B000, B000, B000, B010, B000, B000, 1,
    B000, B000, B000, B000, B000, B000, B001, B000, B000, 1,
    B000, B000, B000, B000, B000, B000, B000, B100, B000, 1,
    B000, B000, B000, B000, B000, B000, B000, B010, B000, 1,
    B000, B000, B000, B000, B000, B000, B000, B001, B000, 1,
    B000, B000, B000, B000, B000, B000, B000, B000, B100, 1,
    B000, B000, B000, B000, B000, B000, B000, B000, B010, 1,
    B000, B000, B000, B000, B000, B000, B000, B000, B001, 10,
    
    // Some little cube - big cube fun
    B000, B000, B000, B000, B011, B011, B000, B011, B011, 10,
    B111, B111, B111, B111, B111, B111, B111, B111, B111, 10,
    B000, B000, B000, B000, B011, B011, B000, B011, B011, 5,
    B000, B000, B000, B000, B000, B000, B000, B000, B001, 2,
    B000, B000, B000, B000, B011, B011, B000, B011, B011, 2,
    B111, B111, B111, B111, B111, B111, B111, B111, B111, 2,
    B000, B000, B000, B000, B011, B011, B000, B011, B011, 2,
    B000, B000, B000, B000, B000, B000, B000, B000, B001, 2,
    B000, B000, B000, B000, B011, B011, B000, B011, B011, 2,
    B111, B111, B111, B111, B111, B111, B111, B111, B111, 1,
    B000, B000, B000, B000, B011, B011, B000, B011, B011, 1,
    B000, B000, B000, B000, B000, B000, B000, B000, B001, 1,
    B000, B000, B000, B000, B011, B011, B000, B011, B011, 1,
    B111, B111, B111, B111, B111, B111, B111, B111, B111, 1,
    B110, B110, B000, B110, B110, B000, B000, B000, B000, 1,
    B100, B000, B000, B000, B000, B000, B000, B000, B000, 1,
    B110, B110, B000, B110, B110, B000, B000, B000, B000, 1,
    B111, B111, B111, B111, B111, B111, B111, B111, B111, 1,
    B000, B000, B000, B000, B011, B011, B000, B011, B011, 1,
    B000, B000, B000, B000, B000, B000, B000, B000, B001, 1,
    B000, B000, B000, B000, B011, B011, B000, B011, B011, 1,
    B111, B111, B111, B111, B111, B111, B111, B111, B111, 1,
    B110, B110, B000, B110, B110, B000, B000, B000, B000, 1,
    B100, B000, B000, B000, B000, B000, B000, B000, B000, 1,
    B110, B110, B000, B110, B110, B000, B000, B000, B000, 1,
    B111, B111, B111, B111, B111, B111, B111, B111, B111, 1,
    B000, B011, B011, B000, B011, B011, B000, B000, B000, 1,
    B000, B000, B001, B000, B000, B000, B000, B000, B000, 1,
    B000, B011, B011, B000, B011, B011, B000, B000, B000, 1,
    B111, B111, B111, B111, B111, B111, B111, B111, B111, 1,
    B000, B000, B000, B110, B110, B000, B110, B110, B000, 1,
    B000, B000, B000, B000, B000, B000, B100, B000, B000, 1,
    B000, B000, B000, B110, B110, B000, B110, B110, B000, 1,
    B111, B111, B111, B111, B111, B111, B111, B111, B111, 1,
    B000, B011, B011, B000, B011, B011, B000, B000, B000, 1,
    B000, B000, B001, B000, B000, B000, B000, B000, B000, 1,
    B000, B011, B011, B000, B011, B011, B000, B000, B000, 1,
    B111, B111, B111, B111, B111, B111, B111, B111, B111, 1,
    B000, B000, B000, B110, B110, B000, B110, B110, B000, 1,
    B000, B000, B000, B000, B000, B000, B100, B000, B000, 1,
    B000, B000, B000, B110, B110, B000, B110, B110, B000, 1,
    
    // Diagonal wipe, starting in the center
    B111, B111, B111, B111, B111, B111, B111, B111, B111, 5,
    B111, B111, B111, B111, B111, B111, B111, B101, B111, 1,
    B111, B111, B111, B111, B101, B111, B111, B101, B111, 1,
    B111, B111, B111, B111, B101, B111, B111, B100, B111, 1,
    B111, B101, B111, B111, B100, B111, B111, B100, B110, 1,
    B111, B101, B111, B111, B100, B111, B111, B100, B110, 1,
    B111, B011, B111, B111, B100, B110, B111, B100, B100, 1,
    B111, B100, B110, B111, B100, B100, B111, B100, B000, 1,
    B111, B100, B100, B111, B100, B000, B111, B000, B000, 1,
    B111, B100, B000, B111, B000, B000, B011, B000, B000, 1,
    B111, B000, B000, B011, B000, B000, B001, B001, B000, 1,
    
    // 2-LED wide diaginal stripe that orbits the cube
    B011, B000, B000, B001, B001, B000, B000, B001, B001, 1,
    B001, B001, B000, B000, B001, B001, B000, B000, B011, 1,
    B000, B001, B001, B000, B000, B011, B000, B000, B110, 1,
    B000, B000, B011, B000, B000, B110, B000, B100, B100, 1,
    B000, B000, B110, B000, B100, B100, B100, B100, B000, 1,
    B000, B100, B100, B100, B100, B000, B110, B000, B000, 1,
    B100, B100, B000, B110, B000, B000, B011, B000, B000, 1,
    B110, B000, B000, B011, B000, B000, B001, B001, B000, 1,
    
    // Now, with center flashies, for flavor
    B011, B000, B000, B001, B001, B000, B000, B011, B001, 1,
    B001, B001, B000, B000, B001, B001, B000, B000, B011, 1,
    B000, B001, B001, B000, B000, B011, B000, B010, B110, 1,
    B000, B000, B011, B000, B000, B110, B000, B100, B100, 1,
    B000, B000, B110, B000, B100, B100, B100, B110, B000, 1,
    B000, B100, B100, B100, B100, B000, B110, B000, B000, 1,
    B100, B100, B000, B110, B000, B000, B011, B010, B000, 1,
    B110, B000, B000, B011, B000, B000, B001, B001, B000, 1,
    B011, B000, B000, B001, B011, B000, B000, B001, B001, 1,
    B001, B001, B000, B000, B001, B001, B000, B000, B011, 1,
    B000, B001, B001, B000, B010, B011, B000, B000, B110, 1,
    B000, B000, B011, B000, B000, B110, B000, B100, B100, 1,
    B000, B000, B110, B000, B110, B100, B100, B100, B000, 1,
    B000, B100, B100, B100, B100, B000, B110, B000, B000, 1,
    B100, B100, B000, B110, B010, B000, B011, B000, B000, 1,
    B110, B000, B000, B011, B000, B000, B001, B001, B000, 1,
    B011, B010, B000, B001, B001, B000, B000, B001, B001, 1,
    B001, B001, B000, B000, B001, B001, B000, B000, B011, 1,
    B000, B011, B001, B000, B000, B011, B000, B000, B110, 1,
    B000, B000, B011, B000, B000, B110, B000, B100, B100, 1,
    B000, B010, B110, B000, B100, B100, B100, B100, B000, 1,
    B000, B100, B100, B100, B100, B000, B110, B000, B000, 1,
    B100, B110, B000, B110, B000, B000, B011, B000, B000, 1,
    B110, B000, B000, B011, B000, B000, B001, B001, B000, 1,
    
    // Wrapping up
    B001, B001, B000, B000, B001, B001, B000, B000, B001, 1,
    B001, B001, B000, B000, B001, B001, B000, B000, B001, 1,
    B000, B001, B001, B000, B000, B001, B000, B000, B001, 1,
    B000, B000, B001, B000, B000, B001, B000, B000, B001, 1,
    B000, B000, B000, B000, B000, B001, B000, B000, B001, 1,
    B000, B000, B000, B000, B000, B000, B000, B000, B001, 5,
    B000, B000, B000, B000, B000, B000, B000, B000, B000, 3,
    B000, B000, B000, B000, B000, B000, B000, B000, B001, 5,
    B000, B000, B000, B000, B000, B000, B000, B000, B000, 3,
    B000, B000, B000, B000, B000, B000, B000, B000, B001, 5,
    B000, B000, B000, B000, B000, B000, B000, B000, B000, 3,
    
    // this is a dummy element for end of table (duration=0)
    B000, B000, B000, B000, B000, B000, B000, B000, B000, 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
    */
    
    int LEDPin[] = {16, 3, 1, 15, 4, 6, 14, 5, 7};
    int PlanePin[] = {19, 18, 17};
    
    // 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 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
    
    // 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
    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++;
    }
    
    // turn current plane on
    digitalWrite( PlanePin[plane], LOW );
    // delay PLANETIME us
    delayMicroseconds( PLANETIME );
    } // for plane
    } // while <EndTime
    } while (DisplayTime > 0); // read patterns until time=0 which signals end
    }
    

    If you have correctly soldered everything and correctly connected the board to the Arduino, you should be greeted by a cool flashing LED cube.

    IMG_0610.JPG
Sign In or Register to comment.