Problem with 5 shiftreg 74HC165

Hi,
I am creating a state machine using 36 switches mounted on 12 ports (3swich x port) connected on 5 shiftreg 74hc165 named from U1 to U5, the latter are connected in chain using ports 9 and 10 and connected to the MISO port of the Adafruit M0, therefore I use the SPI protocol. The first in the chain is U5 on which the last 4 switches are connected (one for port 11 and 3 for port 12).
If I use this sketch to check the connections it works correctly:

#include <SPI.h>

const byte LATCH = A5;
//const byte INTER = D1;
const byte chips = 5; // number of 74HC165 (8bit) chips used(18)

static unsigned long lastMillis;
static unsigned long frameCount;
static unsigned int framesPerSecond;
const int seconds = 1;

// FIXME: finish interrupt support ...

void setup()
{
  SPI.begin ();
  SPI.beginTransaction(SPISettings(3000000, MSBFIRST, SPI_MODE2)); // 32MHz
  Serial.begin(115200);
  pinMode (LATCH, OUTPUT);
  digitalWrite (LATCH, HIGH);
}

void loop() {
  unsigned long now = millis();
  frameCount ++; // Once around the moon ...

  byte Switch[chips];

  digitalWrite (LATCH, LOW);
  digitalWrite (LATCH, HIGH);

  for (byte i = 0; i < chips; i++)
  {
    Switch[i] = SPI.transfer(0);
  }

  if (now - lastMillis >= seconds * 1000) {
    framesPerSecond = frameCount / seconds;

    for (byte i = 0; i < 8; i++) {
      Serial.print((Switch[0] & (1 << i)) != 0 ? 1 : 0);
    }

    Serial.print(" ");

    for (byte i = 0; i < 8; i++) {
      Serial.print((Switch[1] & (1 << i)) != 0 ? 1 : 0);

    }
    Serial.print(" ");
    for (byte i = 0; i < 8; i++) {
      Serial.print((Switch[2] & (1 << i)) != 0 ? 1 : 0);
    }
    Serial.print(" ");
    for (byte i = 0; i < 8; i++) {
      Serial.print((Switch[3] & (1 << i)) != 0 ? 1 : 0);
    }
    Serial.print(" ");
    for (byte i = 0; i < 8; i++) {
      Serial.print((Switch[4] & (1 << i)) != 0 ? 1 : 0);
    }
    Serial.print(" ");
    Serial.print(framesPerSecond);
    Serial.println(" fps");

    frameCount = 0;
    lastMillis = now;
  }
}

However, if I use this sketch it does not detect the status of the switches connected to the U5 chip, therefore one on port 11 and three on port 12.

If I change the number of chips from 5 to 4 the numbering moves starting from U2 and ends regularly on U5 clearly missing ports 11 and 12 as above.

I also tried to shorten the chain by connecting the ICs to the bus one after the other and the problem always recurs with the aforementioned ports.

#include <SPI.h>

const int latchPin = A5;  // Pin di latch
const byte numShiftRegisters = 5;  // Numero di shift register utilizzati
const byte numPorts = 12;  // Numero totale di porte
const byte switchesPerPort = 3;  // Numero di interruttori per ogni porta

unsigned long currentState = 0;
unsigned long previousState = 0;

void setup() {
  Serial.begin(115200);
  pinMode(latchPin, OUTPUT);
  digitalWrite (latchPin, HIGH);
  SPI.begin();
  SPI.beginTransaction(SPISettings(3000000, MSBFIRST, SPI_MODE2)); // Configura SPI
}

void loop() {
  readInputs();
  updateStateMachine();
}

void readInputs() {
  digitalWrite(latchPin, LOW);
  delayMicroseconds(5);  // Assicura la stabilità del segnale
  digitalWrite(latchPin, HIGH);

  currentState = 0;
  for (int i = 0; i < numShiftRegisters ; ++i) {
    //for (int i = numShiftRegisters - 1; i >= 0; --i) {
    currentState <<= 8;
    currentState |= SPI.transfer(0);
  }
}

void updateStateMachine() {
  if (currentState != previousState) {
    for (int port = 0; port < numPorts; ++port) {
      int startIndex = port * switchesPerPort ;
      int portState = (currentState >> startIndex) & 0b111;

      switch (portState) {
        case 0b000:  // Tutti gli interruttori sono spenti
          Serial.println("Porta " + String(port + 1) + ": Nessun interruttore attivo");
          break;
        case 0b001:  // Solo il primo interruttore è attivo
          Serial.println("Porta " + String(port + 1) + ": Solo In attivo");
          break;
        case 0b010:  // Solo il secondo interruttore è attivo
          Serial.println("Porta " + String(port + 1) + ": Solo Middle attivo");
          break;
        case 0b011:  // Primo e secondo interruttore sono attivi
          Serial.println("Porta " + String(port + 1) + ": In e Middle attivi");
          break;
        case 0b100:  // Solo il terzo interruttore è attivo
          Serial.println("Porta " + String(port + 1) + ": Solo Out attivo");
          break;
        case 0b101:  // Primo e terzo interruttore sono attivi
          Serial.println("Porta " + String(port + 1) + ": In e Out attivi");
          break;
        case 0b110:  // Secondo e terzo interruttore sono attivi
          Serial.println("Porta " + String(port + 1) + ": Middle e Out attivi");
          break;
        case 0b111:  // Tutti gli interruttori sono attivi
          Serial.println("Porta " + String(port + 1) + ": Tutti gli interruttori attivi");
          break;
      }
    }

    previousState = currentState;
  }
}

Any idea?? Thankyou

How many bytes in an unsinged long?

I'm only looking through a tiny window, but with numShiftRegisters set to five, I wonder if you don't make some trouble here:

for (int i = 0; i < numShiftRegisters ; ++i) {
    //for (int i = numShiftRegisters - 1; i >= 0; --i) {
    currentState <<= 8;

a7

Thank you.
you're right, it only manages 4 Bytes, how can I solve it?

There is a longer long,

 uint64_t xx;

which would take you out to eight bytes or 64 bits. Above, xx is an eight byte unsigned integer.

Without tearing your code apart, I can't say that is the smartest way forward, nor have I used that type (also known as long long) very much.

Be careful how you use it, make experiments and use any means you can to verify that the code is doing what you think.

HTH

a7

Resolved !!!!!
I had first tried with uint8_t but it didn't work.
Thank you!!!