Shift register basic code help

This may seem like a noob question but I’m new to using shift registers. I was going through the code in the link below, its the third shift register example and I’m a bit confused. It seems like calling the registerWrite one time to turn the current LED on and then again to turn the previous one off is redundant or maybe just wouldn’t even work. I don’t have a register set up right now I’m just thinking conceptually btw.

Looking at the code for that function it looks like every time you called it it would automatically clear out anything that was being previously displayed. Considering that at the beginning of the function bitsToSend is set to 0 and then later the 2 bytes in that variable are split up and written to the registers it seems to me like anything that was on there before would get erased. Maybe I’m not understanding either that function or the shiftOut function but maybe you could help me out. Thanks in advance.

//Pin connected to latch pin (ST_CP) of 74HC595
const int latchPin = 8;
//Pin connected to clock pin (SH_CP) of 74HC595
const int clockPin = 12;
////Pin connected to Data in (DS) of 74HC595
const int dataPin = 11;

char inputString[2];

void setup() {
  //set pins to output because they are addressed in the main loop
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);  
  pinMode(clockPin, OUTPUT);
  Serial.begin(9600);
  Serial.println("reset");
}

void loop() {
  // iterate over the 16 outputs of the two shift registers
  for (int thisLed = 0; thisLed < 16; thisLed++) {
    // write data to the shift registers:
    registerWrite(thisLed, HIGH);
    // if this is not the first LED, turn off the previous LED:
    if (thisLed > 0) {
      registerWrite(thisLed - 1, LOW);
    } 
    // if this is  the first LED, turn off the highest LED:
    else {
      registerWrite(15, LOW);
    } 
    // pause between LEDs:
    delay(250);
  }

}

// This method sends bits to the shift registers:

void registerWrite(int whichPin, int whichState) {
  // the bits you want to send. Use an unsigned int,
  // so you can use all 16 bits:
  unsigned int bitsToSend = 0;    

  // turn off the output so the pins don't light up
  // while you're shifting bits:
  digitalWrite(latchPin, LOW);

  // turn on the next highest bit in bitsToSend:
  bitWrite(bitsToSend, whichPin, whichState);

  // break the bits into two bytes, one for 
  // the first register and one for the second:
  byte registerOne = highByte(bitsToSend);
  byte registerTwo = lowByte(bitsToSend);

  // shift the bytes out:
  shiftOut(dataPin, clockPin, MSBFIRST, registerTwo);
  shiftOut(dataPin, clockPin, MSBFIRST, registerOne);

  // turn on the output so the LEDs can light up:
  digitalWrite(latchPin, HIGH);
}

Well, it all depends on what you shift out, doesn't it?

For example, if you had a variable called dataByte, and you did bit-arithmetic on it, then everytime you shifted out you would have the same data except for what you changed.

example: | is bitwise OR . Result of: 0 | 0 is 0, 0 | 1 is 1, 1 | 1 is 1. Generally used to set a bit High. & is bitwise AND. Result of: 0 & 0 is 0, 0 & 1 is o, 1 & 1 is 1. Generally used to set a bit Low.

So to start: databyte = 0b00000000; // load variable with all 0

databyte = databyte | 0b00001111; // databyte now holds 0b00001111

databyte = databyte & 0b00001110; // dtabyte now holds 0b00001110

So if you had two bytes that you were manipulating, and you only changed one of them and then you shifted them both out again, it would look like only 1 had changed when you were all done.

Make sense?

Yeah I get that with binary but the part that makes me think that it would clear automatically is the first line of the function.

So if you were starting with 0b00000000 and 0b00000001 (one for each register) and you wanted to change to 0b00000010 I can see why you would have to write the least significant to 0 and the next one to 1 which would require the two steps that are in the code. But the first line of the function changes your bytes to 0b00000000 and 0b00000000.

So aren’t you going from 0b00000000 and 0b000000001 to 0b00000000 and 0b00000000 and then writing the second (from right side) bit to 1 with bitWrite so you would end up with the variable that gets sent to the registers 0b00000000 and 0b000000010. It seems like using that function only 1 LED could be turned on at any given time even if you called something like

for (int i = 0; i < 16; i++){
  registerWrite(i, HIGH);
  delay(100);
}

Which seems like the way I would accomplish this same program.

Maybe I’m missing something though. I love binary but sometimes getting out of the integer mindset gets confusing haha. Thanks for the help, this is helping

Looks like a bad example to me.

You are right. There is no need to “turn off the previous LED”.

The “registerWrite()” function can turn on only one light at a time and if you pass LOW for the second argument it will turn off all the lights.

Here is how I would write it:

/*
  Shift Register Example
 for two 74HC595 shift registers

 This sketch turns on each of the LEDs attached to two 74HC595 shift registers,
 in sequence from output 0 to output 15.

 Hardware:
 * 2 74HC595 shift register attached to pins 2, 3, and 4 of the Arduino,
 as detailed below.
 * LEDs attached to each of the outputs of the shift register

 Created 22 May 2009
 Modified 23 Mar 2010
 by Tom Igoe
 Re-written by John Wasser
 */

const int latchPin = 8;  //Pin connected to latch pin (ST_CP) of 74HC595
const int clockPin = 12;  //Pin connected to clock pin (SH_CP) of 74HC595
const int dataPin = 11;  //Pin connected to Data in (DS) of 74HC595

void setup() {
  //set pins to output because they are addressed in the main loop
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);  
  pinMode(clockPin, OUTPUT);
  Serial.begin(9600);
  Serial.println("reset");
}

void loop() 
{
  // iterate over the 16 outputs of the two shift registers
  for (int thisLed = 0; thisLed < 16; thisLed++) 
  {
    // write data to the shift registers:
    registerWrite(1U << thisLed);

    // pause between LEDs:
    delay(250);
  }
}

// This method sends 16 bits to the shift registers:

void registerWrite(unsigned int bitsToSend)
{
  // Pull the latch pin low to separate the output register from the shift registers
  digitalWrite(latchPin, LOW);

  // shift the bytes out:
  shiftOut(dataPin, clockPin, MSBFIRST, lowByte(bitsToSend);
  shiftOut(dataPin, clockPin, MSBFIRST, highByte(bitsToSend));

  // The rising edge of the Latch copies the shift registers to the output registers
  digitalWrite(latchPin, HIGH);
}

Ok thanks. I got my hardware up and running (mostly) last night and just using the first row of leds not multiplexing I ran some of those examples and that one didn't work until I got rid of the writing the previous LED low part. Now I just have to figure out my hardware problems.