Using 8 x 74HC165N Shift Registers with Arduino to scan 64 inputs

My first post to the forum here, so thank you to whomever may be able to guide me on this.

I have been reading for days regarding the Arduino usage with shift registers, and understand the concept as a whole. I do also understand the ability to theoretically cascade as many shift registers as needed by reading the various tutorials and watching video's. These tutorials unfortunately don't usually go beyond 2 shift registers. My specific question relates to how to handle the ever increasing length of the variable to store.

One great tutorial on the following Arduino page makes the following suggestion:

"Arduino Playground - ShiftRegSN74HC165N"

"Of course you can daisy chain as many as you like while still
using only 4 Arduino pins (though you would have to process
them 4 at a time into separate unsigned long variables)."

Unfortunately that tutorial stops short of providing a coding example of how to achieve this. I also would appreciate any advice or code samples as to how to detect only pins that have changed status since last scanned. I don't want to provide extra unneeded commands to turn things on that are already on, or turn off things that are already off, if you know what I mean.

I do appreciate any help provided,

Thank you!

digitalWrite (loadPin, LOW);
digitalWrite (loadPin,  HIGH); // capture the state of all the parallel inputs

// now read them out, perhaps into an array
for (index = 0; index<4; index = index+1){
dataArray[index] = shiftIn(dataPin, clockPin, MSBFIRST);
}
// I use SPI myself
dataArray[index] = SPI.transfer(0); // 0 shifted out on MOSI pin while data comes in on MISO pin

lpme126:
I also would appreciate any advice or code samples as to how to detect only pins that have changed status since last scanned. I don't want to provide extra unneeded commands to turn things on that are already on, or turn off things that are already off, if you know what I mean.

One way would be to make a copy of the current array to compare against the next one. When a new read is complete XOR the two arrays against each other. Any changed bits will produce a non-zero result. You'd then have to work out which bit changed and take appropriate action. Think state-change detection en masse.

some log base 2 of an integer algorithms.

You can use unsigned long long int. These are 64 bits long. You could then compare the current inputs with the previous with a single "==" comparison. But you would still have to transform the 8 x 8 bits read from the shift registers into the 64-bit variable. Worse still, when you have detected a change, to figure out which input changed, you cannot use the normal bitRead() function with unsigned long long.

digitalWrite (loadPin, LOW);
digitalWrite (loadPin,  HIGH); // capture the state of all the parallel inputs

// now read them out, unto an unsigned long long
unsigned long long int myData;
for (byte i = 0; i<8; i++){
  myData = myData << 8 | shiftIn(dataPin, clockPin, MSBFIRST);
}

// Check for any changes
if (myData != myPreviousData) {
  
  // Find the changes
  unsigned long long int mask = 1;
  for (byte i = 0; i<64; i++){
    if (myData & mask != myPreviousData & mask) {
      Serial.print("input changed:");
      Serial.println(i);
      }
    mask <<= 1;
    }
  }
}

Thank you for the replies.

I will study the code examples very carefully and learn from them.

Many Thanks!