Maximum number of SN74HC165N

How many SN74HC165N can multiplex with one Arduino Mega 2560?

You can chain them together:

Connect all latch pins (/PL, 1) together, connect all clock pins (CP, 2) together,
Connect the Q7 pin (9) of each chip into the DS pin (10) of the next chip, and the Q7 pin (9) of the last one into an input pin on your Arduino.

This way you only need 3 pins on your Arduino regardless the number of chips.

There is no logical limit on how many you can chain.
Maybe at some point the cumulative propagation delay becomes more than half a clock, so it would also depend on the clock speed then, but I'm not even sure that is a factor. Or at some point you need driver circuitry to drive large numbers of latch and clock pins.

I realise that 'at some point' is not a very exact number, and I don't have the knowledge or experience to make an educated guess. So my uneducated guess is that you can chain at least a few dozen without special considerations.

You may be able to connect perhaps 20 chips in a daisy chain, maybe more depending on the quality and length of the wires or PCB tracks. If you add some buffer chips to the clock and latch lines as mentioned above, you can probably extend this to 40, 60, 80... chips.

But this sounds like a classic "X-Y problem". What is your project and why do you believe you need so many '165 chips?

It is a train layout and I use this for receive signal about where the trains are, with reed sensors. I have 20 HC165 and with lib Shift.in only works 8.

I have 20 HC165 and with lib Shift.in only works 8.

I don't understand what you are saying. Are you saying that a library that you are using only works with 8 shift registers? What library? Can you post a code example?

Thank you for your answers.

Below I paste my code, which combines the inputs with 74HC165 chips with outputs, with 74HC595. It is a test code. It only serves to check if Arduino recognizes the pulsations of the input switches, through the 74HC165 chip.

On this page, which talks about the ArduinoShiftIn library (see API), it is written that no more than 8 chips are supported. My question is: is this limitation of the chips or is it that library, specifically? I have made the connections as indicated in the figure of that Web page.

As for the outputs by 74HC595 I have not had any problem: all are recognized.

The code works perfectly, except that from chip 9, included, it does not recognize the pulsations: a pulse on a switch connected to chip 9 (and successive) is not reflected in the Serial Monitor. Is this a limitation of the library used or is it a limitation of the 74HC165 chips?

Here is the code:

//____________________________________________
//74HC595=====================================
int SER_Pin = 5;   //pin 14 on the 75HC595
int RCLK_Pin = 6;  //pin 12 on the 75HC595
int SRCLK_Pin = 7; //pin 11 on the 75HC595

//How many of the shift registers - change this
#define number_of_74hc595s 20 

//do not touch
#define numOfRegisterPins number_of_74hc595s * 8

boolean registers[numOfRegisterPins];

////////////////////////
int estado00 = 0;
////////////////////////

//____________________________________________
//74HC165=====================================
#include <ShiftIn.h>
// Init ShiftIn instance with one chip.
// The number in brackets defines the number of daisy-chained 74HC165 chips
// So if you are using two chips, you would write: ShiftIn<2> shift;
ShiftIn<20> shift;

//////////////////////////////////////////////
//////////////////////////////////////////////
void setup(){
//____________________________________________
//74HC595=====================================
  pinMode(SER_Pin, OUTPUT);
  pinMode(RCLK_Pin, OUTPUT);
  pinMode(SRCLK_Pin, OUTPUT);

  //reset all register pins
  clearRegisters();
  writeRegisters();
//____________________________________________
//74HC165=====================================
  Serial.begin(9600);
  // declare pins: pLoadPin, clockEnablePin, dataPin, clockPin
  shift.begin(8, 9, 11, 12);
}

//____________________________________________
//74HC595=====================================
void clearRegisters(){
//set all register pins to LOW
for(int i = numOfRegisterPins - 1; i >=  0; i--){
     registers[i] = LOW;
  }
} 

void writeRegisters(){
//Set and display registers
//Only call AFTER all values are set how you would like (slow otherwise)
  digitalWrite(RCLK_Pin, LOW);
  //for(int i = numOfRegisterPins - 1; i >=  0; i--){
  for(int i = numOfRegisterPins; i >=  1; i--){
    digitalWrite(SRCLK_Pin, LOW);
    int val = registers[i];
    digitalWrite(SER_Pin, val);
    digitalWrite(SRCLK_Pin, HIGH);
  }
  digitalWrite(RCLK_Pin, HIGH);
}

void setRegisterPin(int index, int value){
//set an individual pin HIGH or LOW
  registers[index] = value;
}

//____________________________________________
//74HC165=====================================
void displayValues() {
  for(int i = 0; i < shift.getDataWidth(); i++)
    Serial.print( shift.state(i) ); // get state of button i
  Serial.println();
//  Serial.print( shift.state(0) );
}

//////////////////////////////////////////////
//////////////////////////////////////////////
void loop(){
//____________________________________________
//74HC595=====================================
////////////////////////
  //estado = digitalRead(7);
  estado00 = ( shift.state(0) );
////////////////////////

//Serial.println(boton01);
  if(estado00 == 0) {
    setRegisterPin(80, HIGH);
    digitalWrite(13, HIGH);
  }
  else {
    setRegisterPin(80, LOW);
    digitalWrite(13, LOW);
  }
////////////////////////

  writeRegisters();  //MUST BE CALLED TO DISPLAY CHANGES
  //Only call once after the values are set how you need.

//____________________________________________
//74HC165=====================================
  if(shift.update()) // read in all values. returns true if any button has changed
    displayValues();
  delay(1);

}
no_code_tags = mangled_code;
if (mangled_code)
{
  Serial.println("Difficult to help");
}

UKHeliBob:

no_code_tags = mangled_code;

if (mangled_code)
{
 Serial.println("Difficult to help");
}

:astonished: :astonished: :astonished:

Herodes:
:astonished: :astonished: :astonished:

UKHeliBob is asking you to put the code you posted in post #5 inside code-tags. (Use the </> button.)
It makes puts your code in a scrollable box with fixed width font, preserves every character and does not render as smileys.

For example:

Herodes:
void clearRegisters(){
//set all register pins to LOW
for(int i = numOfRegisterPins - 1; i >= 0; i–){
registers = LOW;
}

Presumably, your actual code says “registers[ i ] = LOW;” but without code-tags, the [ i ] is not displayed and instead makes the rest of the text italic.

As for your question…

Instead of using that library, you can ‘do it yourself’, in much the same way you do with the 595 chips, except your serial data pin would be an input pin you read from instead of an output pin you write to.

Fixed my post # 5. I am so sorry.

Sorry for my clumsiness, Jobi-Wan and UKHeliBob, but I'm very new to Arduino and I'm learning.

You mean do not use any library? Can you tell me where can I find an example where no library is used?

I have not found it but, certainly, I have always thought that this type of chips would require a library.

You mean do not use any library? Can you tell me where can I find an example where no library is used?

Not strictly without a library, but using SPI

See http://forum.arduino.cc/index.php?topic=409739.0

An example is in your code. You can handle the 74HC165 in almost the same way you handle the 74HC595.
With only little change, you can turn your writeRegisters() function into a readRegisters() function.

When you write to the 595, you control the clock and you set the data. So the data pin is an output pin.
When you read from the 165, you control the clock, but it sets the data that you then read. So the data pin is an input pin.

Here is another example:
https://playground.arduino.cc/Code/ShiftRegSN74HC165N
The read_shift_regs() function is where it happens. Note how it looks kind of similar to your writeRegisters() function. Except it uses a digitalRead() instead of digitalWrite() on the data pin.

There are some differences. Mainly, this example uses 1 bit per pin instead of 1 byte per pin; it stores the state of 16 buttons into one unsigned 16 bit int. (Where it says: "Set the corresponding bit in bytesVal".)

I believe you can just tie the /CE pin low.

It does not work, I do not get it…

Herodes:
It does not work, I do not get it...

What hardware and software combination doesn't work and what exactly is the problem ?

The problem is, exactly, the one I described earlier, in post # 3. With the Shift.in library, I manage to make 8 chips work, but I have 20 chips... and only 8 work.

I have tried the code of the example that Jobi-Wan proposes in his post # 11 and with that code, only 4 chips worked of the 20 that I have.

Are you sure you can chain as many 74HC165 chips as you want? Will not the number of 74HC165 chips that can be chained be limited to 8?

Herodes:
[…] I have 20 chips… and only 8 work.

[…] with that code, only 4 chips worked of the 20 that I have.

Are you sure you can chain as many 74HC165 chips as you want? Will not the number of 74HC165 chips that can be chained be limited to 8?

Each chip has no idea that it is part of a chain. It doesn’t know whether its output goes to another 74hc165 or to your atmega. It just shifts on a clock pulse.

When you say it works with 4 of the 20 chips, what do you get for the other 16? All high? All low? Random values?

For me, this works:

const uint8_t pin_PL = 7; // to all pins 1
const uint8_t pin_CP = 5; // to all pins 2
const uint8_t pin_Q7 = 3; // to pin 9 of the 1st chip.
// pin 10 of each chip to pin 9 of next chip



void setup()
{
  Serial.begin(115200);

  pinMode(pin_PL, OUTPUT);
  pinMode(pin_CP, OUTPUT);
  pinMode(pin_Q7, INPUT);

  digitalWrite(pin_PL, HIGH);
  digitalWrite(pin_CP, HIGH);
}

void loop()
{
  // Latch data from input pins into shift registers
  digitalWrite(pin_PL, LOW);
  digitalWrite(pin_PL, HIGH);

  // Read all bits from all shift registers one by one
  for (int i = 0; i < 16; i++)
  {
    Serial.print("pin ");
    Serial.print(i);
    Serial.print(" is ");

    if (digitalRead(pin_Q7) == HIGH)
      Serial.println("HIGH");
    else
      Serial.println("LOW");

    // Clock pulse to shift to the next bit
    digitalWrite(pin_CP, LOW);
    digitalWrite(pin_CP, HIGH);
  }
  Serial.println();


  delay(1000);
}

I only have 2 of those chips laying around, so I can’t test with more. See if this works for you for more than 32 pins.

Great! Thanks! Your code works for me too, but only for 8 chips, no more.

Jobi-Wan:
When you say it works with 4 of the 20 chips, what do you get for the other 16? All high? All low? Random values?

Nothing. It doesn't print anything in Serial Monitor.

Up to chip 8, when I press I get a line of "0" and "1", where "1" corresponds to the switch pressed. Upon release, I get a line of "0", as befits the code you wrote from line 27.

But on chip 9, 10 ... I do not get anything, there is no answer. No line is displayed on the Series Monitor.

Herodes:
Great! Thanks! Your code works for me too, but only for 8 chips, no more.

If you change 16 to 160 in my sketch, surely it will display a value for all 160 pins. It does for me. Since I have only 2 chips, if I tie pin 10 of my 2nd chip low or high, that is what I get for pins 16 .. 159.

Edit to add...

Herodes:
Nothing. It doesn't print anything in Serial Monitor.
But on chip 9, 10 ... I do not get anything, there is no answer. No line is displayed on the Series Monitor.

That suggests that your code just doesn't process more than 64 pins. You can just read from pins and pulse other pins as often as you like regardless of what is connected to those pins.
Can you post the latest version of your code?

Are you sure you can chain as many 74HC165 chips as you want?

Yes

Will not the number of 74HC165 chips that can be chained be limited to 8?

No.

Your code works for me too, but only for 8 chips, no more.

So post the modifications to the code and let us see if you have incorporated them correctly.

It works!!! It works!!! It works!!! Great!!! It works fine!!! You are my best friends and I have a great debt to you!!!

I modified the code a little (what I know…) to see more comfortably “1” and “0”, in a line. I have also modified the speed to 9600, because at 115200 I saw strange symbols.

Here I leave it, for those who need it. I think there are a lot of people looking for something like that.

Certainly, I have a very great debt with you.

Many, many, many thanks!

const uint8_t pin_PL = 7; // to all pins 1
const uint8_t pin_CP = 5; // to all pins 2
const uint8_t pin_Q7 = 3; // to pin 9 of the 1st chip.
// pin 10 of each chip to pin 9 of next chip



void setup()
{
  Serial.begin(9600);

  pinMode(pin_PL, OUTPUT);
  pinMode(pin_CP, OUTPUT);
  pinMode(pin_Q7, INPUT);

  digitalWrite(pin_PL, HIGH);
  digitalWrite(pin_CP, HIGH);
}

void loop()
{
  // Latch data from input pins into shift registers
  digitalWrite(pin_PL, LOW);
  digitalWrite(pin_PL, HIGH);

  // Read all bits from all shift registers one by one
  for (int i = 0; i < 80; i++)
  {
    //Serial.print("pin ");
    //Serial.print(i);
    //Serial.print(" is ");

    if (digitalRead(pin_Q7) == HIGH)
      Serial.print("1");
    else
      Serial.print("0");

    // Clock pulse to shift to the next bit
    digitalWrite(pin_CP, LOW);
    digitalWrite(pin_CP, HIGH);
  }
  Serial.println();


  delay(1000);
}