Go Down

Topic: I'm having trouble daisy chaining two shift registers together and executing a s (Read 5567 times) previous topic - next topic

420gandhi

I'm trying (and failing) to understand how to use shift registers to control a bunch of LEDs. I am ultimately trying to daisy chain two 74HC595 together, and control the 16 LEDs according to patterns of my choice. For example, given some kind of array stricture like:

Code: [Select]
[ [0], [1], [3,4], [5,6] ]

it would be nice if the I could make the LED at index zero turn on, then the LED at index 1, then both LEDs at indices 3 and 4, and then both LEDs at indices 5 and 6.

I've wired myself up according to this tutorial http://arduino.cc/en/tutorial/ShiftOut. I have some basic code where I feed in an array and I turn 1 LED on at a time. My code works great when I use only 1 shift register. However, attaching a second shift register causes things to go funny for the second shift register's LEDs. LEDs associated with the first register continue to light up as expected. However, LEDs associated with the second shift register don't come on when they should and blink very faintly when they shouldn't be on.

Can anyone help build a script that does something close to what I want?

The difference between what these examples do and what I'm trying to do is that most of these example scripts seem to just increment the LEDs on one at a time or something similar. I was hoping to write code to create any arbitrary pattern. Any thoughts on how to write that? I think my code is close...
Here is what I have as code: http://hastebin.com/qetugifudu.coffee

PaulRB


LEDs associated with the second shift register don't come on when they should and blink very faintly when they shouldn't be on.

Have you connected the Output Enable pins to 0V? And put 0.1uF bypass cap on Vcc pin of each reg?


I was hoping to write code to create any arbitrary pattern. Any thoughts on how to write that? I think my code is close...
Here is what I have as code: http://hastebin.com/qetugifudu.coffee


I don't see how your code will allow arbitrary patterns. Only one led on at once.

How about something like this:

Code: [Select]


int datapin = 2;
int clockpin = 3;
int latchpin = 4;

unsigned int data[16] = {
  0b1000000000000001,
  0b1100000000000010,
  0b1110000000000100,
  0b1111000000001000,
  0b1111100000010000,
  0b1111110000100000,
  0b1111111001000000,
  0b1111111110000000,
  0b1111111110000000,
  0b1111111001000000,
  0b1111110000100000,
  0b1111100000010000,
  0b1111000000001000,
  0b1110000000000100,
  0b1100000000000010,
  0b1000000000000001};
 
void setup()
{
  pinMode(datapin, OUTPUT);
  pinMode(clockpin, OUTPUT); 
  pinMode(latchpin, OUTPUT);
}


void loop()
{
  manyOnAtATime();       // Scroll down the line
}


void shiftWrite(unsigned int desiredPins)
{
  shiftOut(datapin, clockpin, MSBFIRST, highByte(desiredPins));
  shiftOut(datapin, clockpin, MSBFIRST, lowByte(desiredPins));
  digitalWrite(latchpin, HIGH);
  digitalWrite(latchpin, LOW);
}



void manyOnAtATime()
{
  int i;
  int delayTime = 1000;
  for(i = 0; i <16; i++)
  {
    shiftWrite(data[i]); // turn LEDs on
    delay(delayTime); // pause to slow down the sequence
  }
}


Paul


PaulRB


420gandhi

Yeah the flickering stopped! Thanks again!
However, I'm having another problem.

I've daisy chained a third shift register to my project. Unfortunately, using the same code as above the third shift register emits from its pins in the exact same way as the first shift register!

For example, expanding an element of the data variable to hold 24 bytes:

Code: [Select]
unsigned int data[1] = {0b000000010000000000000010};

I'm expecting pins at indices 1 and 16 are turned to HIGH. However, what happens is that pins 1 and 17 are HIGH, as if the third shift register is getting the same bytes as the first...

Similarly, something like:

Code: [Select]
unsigned int data[1] = {0b000000100000000000000001};

where I expect pins at indices 0 and 16 to turn HIGH, whats happens is that pins at indices 16 and 0 are HIGH. Making me again think that the third register is copying that of the first...

Is there anyway to get the third shift register to act correctly?

420gandhi

Sorry, with the following:

Code: [Select]
unsigned int data[1] = {
  0b000000100000000000000001};


I expect pins 0 and 17 to turn HIGH, but pins 0 and 16 turn high. Again, as if the third register is mimicking he first...

Grumpy_Mike

Did you put the 0.1uF capacitor on the chip between the 5V and ground? You need one on each shift register.

420gandhi

No, I don't have any capacitors. Just ordered some. Is that the reason? The code looks fine? In theroy I all have to do is send 24 bytes? Funny that the second register works fine without the capacitors but the 3rd doesnt.

Grumpy_Mike

The more chips you have the more decoupling capacitors you need. Yes that is your problem.

I hope you have not got a capacitor on the latch pin, that is an error in the tutorial on this site.

420gandhi

No, no capacitors at all!
I saw your comment an another thread about error in the tutorial with regards to capacitors. I'll be sure not to make that mistake!

Thanks a lot. I'll reply again tmr when the capacitors get here!

PaulRB

...decoupling capacitors... Yes that is your problem.
Mike is correct to say that you should have those caps. But that's not what's causing the problem with your 3rd shift register.

The sketch I gave you was written for only 2 shift registers and sends out only 16 bits.

When you added an extra 8 bits to the patterns, 2 things went wrong:

1. the sketch just discarded the extra 8 bits because the variable they are stored in (unsigned int) only holds 16 bits.
2. the sketch sends out 16 bits each time. The 3rd shift register becomes a copy of the previous contents of the 1st register.

So the sketch needs amending for 24 bits instead of 16. But if I do that for you, will you then say "great, that worked but then I added a fourth shift register..."?

So how many shift registers do you really want?

420gandhi

Hey Paul,
Thanks for the reply. For my specific project I only need 3 shift registers. I thought it would be as simple as figuring out how to work with two, and then copying that pattern for as many as I needed. Apparently this is not the case.

Sorry for not being clear from the beginning. I find that I learn a lot by looking at examples so that's why I asked for a simple example dealing with only two shift registers.

Thanks for letting me know that ints can only hold 16 bytes. Does this mean I could change the type of variable from unsigned int to a float, to give myself 32 bits to work with?

Could it be as simple as changing:

Code: [Select]
unsigned int data[1] = {0b000000100000000000000001};

to:

Code: [Select]
float data[1] = {0b000000100000000000000001};

?

Thanks again!

420gandhi

Paul,

I thought up this solution which seems to work! :) Thanks to your tip on ints only holding 16 bits.
Is this the best way to go about this?


Code: [Select]
int datapin = 2;
int clockpin = 3;
int latchpin = 4;

unsigned int data[1] = {0b0000000000000001};
unsigned int data2[1] = {0b0000000000000001};
 
void setup()
{
  pinMode(datapin, OUTPUT);
  pinMode(clockpin, OUTPUT); 
  pinMode(latchpin, OUTPUT);
}


void loop()
{
  manyOnAtATime();       // Scroll down the line
}


void shiftWrite(unsigned int desiredPins, unsigned int desiredPins2)
{
  shiftOut(datapin, clockpin, MSBFIRST, highByte(desiredPins));
  shiftOut(datapin, clockpin, MSBFIRST, lowByte(desiredPins));
  shiftOut(datapin, clockpin, MSBFIRST, highByte(desiredPins2));
  shiftOut(datapin, clockpin, MSBFIRST, lowByte(desiredPins2));
  digitalWrite(latchpin, HIGH);
  digitalWrite(latchpin, LOW);
 
}



void manyOnAtATime()
{
  int i;
  int delayTime = 100;
  for(i = 0; i <1; i++)
  {
    shiftWrite(data[i], data2[i]); // turn LEDs on
    delay(delayTime); // pause to slow down the sequence
  }
}

PaulRB

I was thinking you could switch to using "unsigned long" instead of "unsigned int". They hold 32 bits, so you can give your 24-bit patterns just as you wanted without having to split them into two. ("float" is not what you want at all btw!).

However, the other part of the sketch that would need to change is your ShiftWrite() function. It would need to contain 3 shiftOut() calls. But the highByte() and lowByte() functions will only extract 16 of your 24 bits. You need a third function to extract the remaining 8 bits, but Arduino does not provide one, so instead I think you can use:

Code: [Select]

void shiftWrite(unsigned long desiredPins)
{
  shiftOut(datapin, clockpin, MSBFIRST, highByte(desiredPins>>8));
  shiftOut(datapin, clockpin, MSBFIRST, highByte(desiredPins));
  shiftOut(datapin, clockpin, MSBFIRST, lowByte(desiredPins));
  digitalWrite(latchpin, HIGH);
  digitalWrite(latchpin, LOW);
}


(I have not checked the above will even verify!)

420gandhi

Works! Thanks Paul! The unsigned Long makes sense! Better than two ints.

I had to rearrange like this for my application:

Code: [Select]
  shiftOut(datapin, clockpin, MSBFIRST, lowByte(desiredPins));
  shiftOut(datapin, clockpin, MSBFIRST, highByte(desiredPins));
  shiftOut(datapin, clockpin, MSBFIRST, highByte(desiredPins>>8));
  digitalWrite(latchpin, HIGH);
  digitalWrite(latchpin, LOW);


Not quite sure why but it seems to work :) Could be the way I wired up the shift registers

Go Up