Controlling LED's with two shift registers.

Hello everyone

I’m as good as new to Arduino and only have a basic electronics background, but I thought a fun first project to do, would be a 4x4x4 LED cube. So far, I have created my first level: a grid of 4 by 4 LED’s (16 in total). I am working with two 8bit shift registers (the 74HC595) and just want to have a basic LED chase to see if all LED’s are connected properly.

At the moment, this is my code:

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

int values[] = {1, 2, 4, 8, 16, 32, 64, 128};

void setup() {
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
}

void loop() {
  // count from 0 to 255 and display the number 
  // on the LEDs
  int index;
  int value1, value2; 
  
  for (int i = 0; i < 16; i++) {
    // take the latchPin low so 
    // the LEDs don't change while you're sending in bits:
    digitalWrite(latchPin, LOW);
    // shift out the bits:
    index = i%8;
    if(i < 8)
    {
      value2 = values[index];
      value1 = 0;
    } else {
      value2 = 0;
      value1 = values[index];
    } 
    
    shiftOut(dataPin, clockPin, MSBFIRST, value1); 
    shiftOut(dataPin, clockPin, MSBFIRST, value2);  
    
    //take the latch pin high so the LEDs will light up:
    digitalWrite(latchPin, HIGH);
    // pause before next value:
    delay(100);
    
  }

}

Since I am working with two shift registers, I have to shiftout twice, but seeing as I want to do a LED chase (where one shift register is only needed for half the for-loop), I have to shift 0 out as well? I come from a webdevelopment background and I’m still trying to wrap my ahead around the Arduino logic. The way I’m switching value1 and value2 feels very clumsy. Is there any better way of doing this?

Instead of shifting out a zero, should I use the master reset pin?

You have plenty of IO available - why not have separate Latch for each? Then only shift to 1 if only 1 is changing.

Might also consider using SPI.transfer() vs shiftout() for faster performance. clock comes from D13, data comes from D11, latch comes from D10

digitalWrite (latch, LOW); SPI.transfer(value1); SPI.transfer(value2); digitalWrite(latch, HIGH);

Brammm:
Since I am working with two shift registers, I have to shiftout twice, but seeing as I want to do a LED chase (where one shift register is only needed for half the for-loop), I have to shift 0 out as well? I come from a webdevelopment background and I’m still trying to wrap my ahead around the Arduino logic. The way I’m switching value1 and value2 feels very clumsy. Is there any better way of doing this?

Instead of shifting out a zero, should I use the master reset pin?

Firstly I want to clarify how you have the shift registers wired up - normally you’d run the shift out of one into the shift in of the other (pin 9 of one to 14 of the other. Then you always shift 16 bits at a time before pulsing the RCLK line. So have you connected your “latchpin” to RCLK (pin 12 on each shift register)? If you’ve connected to pins 13 (OE) instead you’ll get unnecessary flicker.

As for you loop, I think its best to pass one 16 bit value to your output code (which will work with any pattern). so something like

void update_LEDs (int patt)  // general LED update with 16 bits
{
  shiftOut (dataPin, clockPin, MSBFIRST, patt >> 8);   // shift 16 bits into registers
  shiftOut (dataPin, clockPin, MSBFIRST, patt & 0xFF); 
  digitalWrite (latchPin, HIGH) ;  // toggle RCLK to update outputs
  digitalWrite (latchPin, LOW) ;
}

void loop ()
{
  for (int i = 0 ; i < 16 ; i++)
  {  
    update_LEDs (1 << i) ;  // create a pattern with a shift left - no table needed for a simple pattern like this
    delay (100) ;
  }
}

There’s no need to waste storage for a simple pattern like that as it can be generated on the fly simply (1 << i). int or unsigned int are 16 bit which is just what you need for 2 shift registers - use long int if 4 shift registers

You can daisy-chain the shift registers, every bit you shift in moves the rest up overflow from the first goes to bit zero of the second and overflow from that goes back MISO to the Arduino.

IMO, you want to latch on every bit transferred instead of bytes and then your leds will scroll.

Or send out 2 bytes every time, do the math on the int that you want displayed.

put the pattern in an array

int displayArray[] = {0x01, 0x02, 0x04, 0x08,0x10, 0x20,0x40,0x80, 0x80, 0x40, 0x20,0x10,0x08,0x04,0x02,0x01};
// or whatever, maybe 2 LEDs move across, or 3, that scrunch into 1 at the ends
void loop(){
for (x = 0; x<16, x=x+1){
digitalWrite (CS, LOW);
SPI.transfer (lowByte, displayArray[x]);
SPI.transfer (highByte, displayArray[x]);
digitalWrite (CS, HIGH);
delay(200);
}
}

And you have plenty of time between changes if you want to run it slow enough for eyes (not just make dim lit leds). Heck you could SCK real slow, 1 bit per 1/10th second would move 10 pixels per second. They'reshift registers, bits shift in and bits shift out. The pattern is in the bits.

You can move 1 bit per interval or you can move 16 to do the same thing. You wouldn't need the SPI port at all if you don't mind shifting your own bits. Best way IMO is all 4 pins on the same PORT to operate on using PORT reads and writes to get/set data all at once.

MarkT:
Firstly I want to clarify how you have the shift registers wired up - normally you’d run the shift out of one into the shift in of the other (pin 9 of one to 14 of the other. Then you always shift 16 bits at a time before pulsing the RCLK line. So have you connected your “latchpin” to RCLK (pin 12 on each shift register)? If you’ve connected to pins 13 (OE) instead you’ll get unnecessary flicker.

As for you loop, I think its best to pass one 16 bit value to your output code (which will work with any pattern). so something like

There’s no need to waste storage for a simple pattern like that as it can be generated on the fly simply (1 << i). int or unsigned int are 16 bit which is just what you need for 2 shift registers - use long int if 4 shift registers

This is how they are connected: the two are daisy chained, as described in http://arduino.cc/en/Tutorial/ShiftOut

I’m going to have a look at this tutorial here: http://www.arduino.cc/playground/Code/BitMath and bitmath in general as this is complete magic for me at the moment. Your code works like a charm and I’ve found that if I change the code to update_LEDs (3 << i), two leds chase (as expected), but I have no clue or how :stuck_out_tongue:

edit: I’ve now editted Mark’s code a little to suit my LED cube:

void loop ()
{
  for(int y=1; y<=4; ++y)
  {
     for(int x=1; x<=4; ++x)
     {
      light(x, y);
      delay(200);
     }
  }
}

void light(int x, int y)
{
  int patt = 1;
  patt <<= x-1;
  patt <<= (y-1)*4;
  
  shiftOut (data, clock, MSBFIRST, patt >> 8);   // shift 16 bits into registers
  shiftOut (data, clock, MSBFIRST, patt & 0xFF); 
  digitalWrite (latch, HIGH) ;  // toggle RCLK to update outputs
  digitalWrite (latch, LOW) ;
}

I think this will allow me better to animate the cube. Can anyone tell me if I’m on the right track?

Have fun with binary and bitwise operators!