Shift registers working in paralel

I’ve tried figuring out how to send a bit of information along 2 shift registers but all my atemps failed. It seems like the second register works in paralel with the first one with 1 bit delay. Here’s my code:

  int latchPin = 10;
  int clockPin = 12;
  int dataPin = 11;
  
  void setup() 
  {
    pinMode(latchPin, OUTPUT);
    pinMode(clockPin, OUTPUT);
    pinMode(dataPin, OUTPUT);
  }
  
  void loop()
  {
   int i;
   for(i=0; i<8;i++)
   {
     digitalWrite(latchPin, LOW);
     shiftOut(dataPin, clockPin, LSBFIRST, B00000001 << i);
     digitalWrite(latchPin, HIGH);
     delay(125);  
   }
   
   for(i=0; i<8;i++)
   {
     digitalWrite(latchPin, LOW);
     shiftOut(dataPin, clockPin, LSBFIRST, B00000000 << i);
     digitalWrite(latchPin, HIGH);
     delay(125);  
   }
   
   for(i=0; i<8;i++)
   {
    digitalWrite(latchPin, LOW);
     shiftOut(dataPin, clockPin, LSBFIRST, B10000000 >> i);
     digitalWrite(latchPin, HIGH);
     delay(125);  
   } 
   
    for(i=0; i<8;i++)
   {
    digitalWrite(latchPin, LOW);
     shiftOut(dataPin, clockPin, LSBFIRST, B00000000 >> i);
     digitalWrite(latchPin, HIGH);
     delay(125);  
   } 
  }

How have you wired up the shift registers?

Are you sure that the problem it's with the code? How do you made the connections?

The connections are well made, i can shift manually one bit through both of them using pushbutton with no problem. What's wronge here? :(

Did you folow this tutorial: http://arduino.cc/en/Tutorial/ShiftOut

?

Yes, is the code right?

alexmath:
Yes, is the code right?

Depends on how you have wired it all up. If you have daisy chained the shift registers then you need to latch, shift out ALL bits needed for ALL the shift registers, unlatch. Your code seems to be toggling latch every 8 bits so no data will get passed to the next chip (if wired serially)

You are actually shifting two bits along the registers. Try using an int instead of a byte. Something like this…

  int i;
  unsigned int data=1;
   for(i=0; i<16;i++)
   {
     digitalWrite(latchPin, LOW);
     shiftOut(dataPin, clockPin, LSBFIRST, data & 0xFF);
     shiftOut(dataPin, clockPin, LSBFIRST, data & 0xFF00 >> 8);
     digitalWrite(latchPin, HIGH);
     data = data << 1;
     delay(125);  
   }

Or for an int:

     shiftOut(dataPin, clockPin, LSBFIRST, lowByte(data) );
     shiftOut(dataPin, clockPin, LSBFIRST, highByte(data) );

alexmath: I've tried figuring out how to send a bit of information along 2 shift registers but all my atemps failed. It seems like the second register works in paralel with the first one with 1 bit delay. Here's my code:

I don't know what you mean by "the second register works in paralel with the first one ". The register chips are described as connected in serial. The chips themselves each have parallel output but the chips are 1-->2 serial.

Are you trying to clock 1 bit on and the rest off slowly through the 2 chips, so each led is ON then OFF as the next lights up in turn? That is what I get when I read

The connections are well made, i can shift manually one bit through both of them using pushbutton with no problem. What's wronge here? smiley-sad

The button does not shiftOut(), which sends 8 bits quickly. Manual button is 1 bit at a time.

Then you start with clear registers, or clear them first. Without using shiftOut you send a 1 on data (make the pin HIGH) then latch (and release the latch), wait, send 0, latch (release), wait, and 14 more times send 0.

You can "walk" the bits 1 at a time by controlling just the pins. Inside the registers, each has 8 bits 0 to 7 in a row. Each time the clock transitions the state of the data in pin becomes the new bit 0, the rest move up 1 bit and whatever was the top bit (bit 7) becomes the register chip serial out that connected to the next chip serial data in is clocked in to that chip in the same way.

Say you have a line of 8 people, a space, 8 more people all holding signs saying LOW and then you take a picture. Then you have a new person ready with sign saying HIGH. On command everyone moves 1 spot ahead except for the last one, the 8th person in the second group leaves and now you have 8 people and 8 people, the first person's sign says HIGH and the rest say LOW. And then you take a picture. One at a time you bring in 15 new people all with signs that say LOW and do the same on-command procedure and take a picture. That would be a human version of what you want, no? Every LOW or HIGH sign is a bit. Every 'command' is a clock toggle. Every picture is a latch toggle. The shiftOut() is sending 8 new people at a time before a new picture -can- be taken.

Thank you for helping!

This code is not working so well…

int i;
  unsigned int data=1;
   for(i=0; i<16;i++)
   {
     digitalWrite(latchPin, LOW);
     shiftOut(dataPin, clockPin, LSBFIRST, data & 0xFF);
     shiftOut(dataPin, clockPin, LSBFIRST, data & 0xFF00 >> 8);
     digitalWrite(latchPin, HIGH);
     data = data << 1;
     delay(125);  
   }

The code that works is this one:

shiftOut(dataPin, clockPin, LSBFIRST, lowByte(data) );
     shiftOut(dataPin, clockPin, LSBFIRST, highByte(data) );

And what does “data & 0xFF” do?

All i want to know now is how do i change the nr. of bytes accordingly with the nr. of shift register? What if i want to send 4 bytes? what is the piece of code which does that?

How are the four bytes stored? In an array? In four separate variables?

alexmath: All i want to know now is how do i change the nr. of bytes accordingly with the nr. of shift register? What if i want to send 4 bytes? what is the piece of code which does that?

you shiftOut() one byte per register

     digitalWrite(latchPin, LOW);
     shiftOut(dataPin, clockPin, LSBFIRST, BYTEone);
     shiftOut(dataPin, clockPin, LSBFIRST, BYTEtwo);
     digitalWrite(latchPin, HIGH);

the second byte 'pushes' the first byte along, so to speak.

alexmath,
I’m with GoForSmoke.
We need to know what you are trying/wanting to do.
For example, if someone says to me:
“I want two shift register working in parallel”,
I interpret that to mean that both shift registers are connected to the same clk, data, and latch pins and both
will have EXACTLY the same outputs.
i.e. both are working in parallel doing exactly the same thing with matching outputs.
I don’t think that is what you are wanting to do.

I’m assuming you are probably wanting them to be serially connected so the output of one
feeds the input of the other, but that is just a guess on my part since you haven’t really
given us much to go on.

In several of the example code segments it looks like perhaps there is a misunderstanding
of how shiftOut() works.
shiftOut() shifts out 8 bits of data.

For example, some loops like this:

   for(i=0; i<8;i++)
   {
     digitalWrite(latchPin, LOW);
     shiftOut(dataPin, clockPin, LSBFIRST, B00000000 << i);
     digitalWrite(latchPin, HIGH);
     delay(125);  
   }

are shifting out way more bits than can be held in two shift registers even
if they are hooked up serially.
This loop will shift out eight 8 bit values of zero. or 64 zero bits.

It would be helpful if you were to step back and tell us what you are you wanting to accomplish
and how you have the chips wired up.
That way we can then look at the code and the wiring of the chips to determine if it
will accomplish what you are wanting to do.
Without knowing both pieces of information, all anybody can do is guess, and guessing
wastes time and can get very frustrating.

— bill

If you have 8 bit registers (there are 16's) you write up to 1 byte per register in the chain.

I thought from earlier that you wanted to make it light each led in turn for a short time. That or moving a pattern like marquee lights is easier done 1 bit at a time instead of 8 or 16 or 32.

It seems like i've created a little bit of confusion here. Let's see what do i have and what do i want. I have 2 - 74HC595 - NXP shift register daisy chained together and what do i want is to be able to send 16 bits of information at a time, in which pattern i want and after that latch them. Ex. 00000000 00000001 - latch 00000000 00000010 - latch so on and so forth or every other pattern i want so that i can make a function for each of them and call them in the main. Another think i want to do is to make a binary counter for 16 bits (2bytes).

Ex. 00000000 00000001 - latch 00000000 00000010 - latch

Any patterns that move 1 bit at a time, latch and wait before the next bit can be fed in. But the direction always has to be low to high though the number of bits may vary.

To appear to move backward or change all the leds or different selected leds all at once generally requires full 16 bit changes.

Depending on what patterns you want and how many changes they have to make, your program may need sections built around different kinds of data handling and/or data generation. I can see that PROGMEM or SD or data fed from a PC or other device could become a defining feature of your program. What you want to do shapes the sketch to some degree.

You need 4 pins and if you use the SPI port you can move bytes into the registers at about 1 MByte/second. You do not need a set of pins per register and you can chain all the registers you can wire and power.

alexmath:
It seems like i’ve created a little bit of confusion here. Let’s see what do i have and what do i want.
I have 2 - 74HC595 - NXP shift register daisy chained together and what do i want is to be able to send 16 bits of information at a time, in which pattern i want and after that latch them.
Ex. 00000000 00000001 - latch
00000000 00000010 - latch
so on and so forth
or every other pattern i want so that i can make a function for each of them and call them in the main.
Another think i want to do is to make a binary counter for 16 bits (2bytes).

@GoForSmoke will shoot me for showing an example with delays, but you want to do something like this to move one light at a time across the 16 LEDs. So your preference to call functions, you can build several examples off of this.

Read the notes in the sketch for a fuller understanding…

//put your pin definition here
//
const byte Leds [8] = { 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};// equiv to{ B00000001,B00000010,B00...
int displayDelay = 20;// Faster  or Slower??  play with this number

void setup()
{
  Serial.begin(115200);
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
}

void loop()
{
//One LED kites, running across 16 LEDs
  for (int i = 0; i < 8; i++)
  {
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, LSBFIRST, Leds[i]); //first 8 bits from the array above
    shiftOut(dataPin, clockPin, LSBFIRST, 0x00);  //second 8 bits is B00000000, 16 total bits now pushed in.
    digitalWrite(latchPin, HIGH);
    delay(displayDelay);
  }
  for (int i = 0; i < 8; i++)
  {
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, LSBFIRST, 0x00);// These first 8 bits are the B00000000
    shiftOut(dataPin, clockPin, LSBFIRST, Leds[i]); // These 8 bits from the array above, now 16 bits pushed in.
    digitalWrite(latchPin, HIGH);
    delay(displayDelay);
  }
  for (int i = 0; i < 8; i++)
  {
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, LSBFIRST, 0x00);// and so on, reversing the direction of the 'movement' of the lit LED
    shiftOut(dataPin, clockPin, LSBFIRST, Leds[7-i]); 
    digitalWrite(latchPin, HIGH);
    delay(displayDelay);
  }
  for (int i = 0; i < 8; i++)
  {
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, LSBFIRST, Leds[7-i]); 
    shiftOut(dataPin, clockPin, LSBFIRST, 0x00);
    digitalWrite(latchPin, HIGH);
    delay(displayDelay);
  }
}

hopefully you can visualize the lit LED marching back and forth across the array of 16 LEDs…

Not tested. Call these pseudocode.

//put your pin definition here -- this code is not complete
//
const unsigned long displayDelay = 20UL;// Faster  or Slower??  play with this number
unsigned long displayStart;
unsigned long displayNow;

void setup()
{
  Serial.begin(115200);
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
}

void loop()
{
//One LED kites, running across 16 LEDs
  word pattern = 1U; // word is unsigned int, 16 bit

  displayNow = millis();

  byte i = 0; // only need to count to 15

  if (( displayNow - displayStart >= displayDelay ) && ( i++ < 16 ))
  {
      digitalWrite(latchPin, LOW);
      shiftOut(dataPin, clockPin, LSBFIRST, pattern); //first 8 bits from pattern
      shiftOut(dataPin, clockPin, LSBFIRST, 0x00);  //second 8 bits from pattern
      digitalWrite(latchPin, HIGH);
      pattern = pattern << 1;
      displayStart = displayNow;
  }

// add user button or serial control here, it will accept input even while the pattern is running
// that why you don't want delays, they close off the ability to do anything not clunky
}
//put your pin definition here -- this code is not complete
//
const unsigned long displayDelay = 20UL;// Faster  or Slower??  play with this number
unsigned long displayStart;
unsigned long displayNow;

void setup()
{
  Serial.begin(115200);
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
}

void loop()
{
//One LED kites, running across 16 LEDs
  word pattern = 1U; // word is unsigned int, 16 bit

  displayNow = millis();

  byte i = 0; 

  if ( displayNow - displayStart >= displayDelay ) // this way runs over and over
  {
      digitalWrite(latchPin, LOW);
      digitalWrite( dataPin, pattern & bit( i ));
      digitalWrite( clockPin, HIGH ); // THIS MAY NEED TO BE REVERSED
      // there may need to be some kind of very short delay, like NOP instruction(s) here, probably not
      digitalWrite( clockPin, LOW ); // THIS MAY NEED TO BE REVERSED
      digitalWrite(latchPin, HIGH);
      displayStart = displayNow;
      i = ( ++i & 15 ); // i keeps cycling from 0 to 15
  }

// add user button or serial control here, it will accept input even while the pattern is running
// that why you don't want delays, they close off the ability to do anything not clunky
}

I'd do it quite a bit differently. First I'd write a simple function that given a 16 bit value, pushed it out to update all 16 output pins. Then write the logic of updating the output pins around that. It keeps things simple and modular and allows for any patterns since the patterns and delays are outside the actual updating of the SR output pins.

--- bill