Expanding shift register code

hello, im struggling a little to understand this code for esp32 that reads the pin states of 4 shift registers(74hc165).
my wiring(except its expanded to 9 registers, following exactly the same pattern the 4 registers follow):


i need to expand the code to read my 9 shift registers rather than the 4 the code was designed for:

const byte latchPin = 14;        // to latch the inputs into the registers
const byte clockPin = 13;       // I choose the SCK pin
const byte dataPin = 12;        // I choose the MISO pin
uint32_t oldOptionSwitch = 0;   // previous state of all the inputs

const int pulseWidth = 10;      // pulse width in microseconds

void setup ()
{
  Serial.begin( 115200);
  Serial.println( "Turn on and off the switches");
  Serial.println( "Top row is switch 0 (right) to switch 7 (left)");
  Serial.println( "Second row is 8 to 15, and so on");

  pinMode( clockPin, OUTPUT);   // clock signal, idle LOW
  pinMode( latchPin, OUTPUT);   // latch (copy input into registers), idle HIGH
  digitalWrite( latchPin, HIGH);
}

void loop ()
{
  // Give a pulse to the parallel load latch of all 74HC165
  digitalWrite( latchPin, LOW);
  delayMicroseconds( pulseWidth);
  digitalWrite( latchPin, HIGH);

  // Reading one 74HC165 at a time and combining them into a 32 bit variable
  // The last 74HC165 is at the bottom, but the switches start numbering
  // at the top. So the first byte has to be shifted into the highest place.
  uint32_t optionSwitch = 0;
  for ( int i = 24; i >= 0; i -= 8)
  {
    optionSwitch |= ((uint32_t) ReadOne165()) << i;
  }

  for ( int i = 0; i < 32; i++)
  {
    if ( bitRead( optionSwitch, i) != bitRead( oldOptionSwitch, i))
    {
      Serial.print( "Switch ");
      if ( i < 10)
        Serial.print( " ");
      Serial.print( i);
      Serial.print( " is now ");
      Serial.println( bitRead( optionSwitch, i) == 0 ? "down ↓" : "up   ↑");
    }
  }

  oldOptionSwitch = optionSwitch;
  delay( 25);      // slow down the sketch to avoid switch bounce
}

// The ReadOne165() function reads only 8 bits,
// because of the similar functions shiftIn() and SPI.transfer()
// which both use 8 bits.
//
// The shiftIn() can not be used here, because the clock is set idle low
// and the shiftIn() makes the clock high to read a bit.
// The 74HC165 require to read the bit first and then give a clock pulse.
//
byte ReadOne165()
{
  byte ret = 0x00;

  // The first one that is read is the highest bit (input D7 of the 74HC165).
  for ( int i = 7; i >= 0; i--)
  {
    if ( digitalRead( dataPin) == HIGH)
      bitSet( ret, i);

    digitalWrite( clockPin, HIGH);
    delayMicroseconds( pulseWidth);
    digitalWrite( clockPin, LOW);
  }

  return ( ret);
}

code taken from this tutorial, except i am using an esp32 devkit v1, not arduino uno.
to read 9 registers (72 i/o's) is it as simple as changing:

for ( int i = 0; i < 32; i++)
  {
    if ( bitRead( optionSwitch, i) != bitRead( oldOptionSwitch, i))......

to:

for ( int i = 0; i < 72; i++)
  {
    if ( bitRead( optionSwitch, i) != bitRead( oldOptionSwitch, i))......

?
thanks

Hello

optionSwitch is a 32 bits variable, so it can hold only 32 buttons states.

You cannot just increase the iterations of the for loop.

You have to use another method of storing the buttons states. The easiest way is to use an array, where each element of the array contains one button state. It will waste memory, using at least one byte per button state, instead of one bit.

1 Like

Ok, im making a start on changing optionSwitch to an array.

Im a bit confused on what the piece below does, its my first time touching the “|=“ symbol.


optionSwitch |= ((uint32_t) ReadOne165()) << i;

This is bitwise OR operator

To make it easier to understand, this for loop :

uint32_t optionSwitch = 0;
for ( int i = 24; i >= 0; i -= 8)
{
  optionSwitch |= ((uint32_t) ReadOne165()) << i;
}

Could be written in a single line, like this :

optionSwitch = ( ((uint32_t) ReadOne165()) << 24 ) | ( ((uint32_t) ReadOne165()) << 16 ) | ( ((uint32_t) ReadOne165()) << 8 ) | ( ((uint32_t) ReadOne165()) )

It reads 4 bytes from the shift registers and store each byte into optionSwitch which can hold 4 bytes (32 bits)

As an example, suppose ReadOne165() always gives result 11011011 (binary)

  11011011 << 24
= 11011011000000000000000000000000
| 11011011 << 16
= 11011011110110110000000000000000
| 11011011 << 8
= 11011011110110111101101100000000
| 11011011
= 11011011110110111101101111011011
1 Like

Here is an example that is using an array but without wasting memory, each state still using one bit

1 Like

i switched over to this code, im finding it alot easier to understand:

const int dataPin = 12;   /* Q7 */
const int clockPin = 13;  /* CP */
const int latchPin = 14;  /* PL */
 
const int numBits = 72;   /* Set to 8 * number of shift registers */
 
void setup() {
  Serial.begin(115200);
  pinMode(dataPin, INPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(latchPin, OUTPUT);
}
 
void loop() {
  // Step 1: Sample
  digitalWrite(latchPin, LOW);
  digitalWrite(latchPin, HIGH);
 
  // Step 2: Shift
  Serial.print("Bits: ");
  for (int i = 0; i < numBits; i++) {
    int bit = digitalRead(dataPin);
    if (bit == HIGH) {
      Serial.print("1");
    } else {
      Serial.print("0");
    }
    digitalWrite(clockPin, HIGH); // Shift out the next bit
    digitalWrite(clockPin, LOW);
  }
 
  Serial.println();
  delay(1000);
}

final code, reads 9 registers:

const int dataPin = 12;   /* Q7 */
const int clockPin = 13;  /* CP */
const int latchPin = 14;  /* PL */
 
const int bits = 72;   //8x number of registers e.g 2 registers = 16

void setup() {
  Serial.begin(115200);
  pinMode(dataPin, INPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(latchPin, OUTPUT);
}
String ios = ""; //in my case, strings fit better. recommend using array
void loop() {
  // Step 1: Sample
  digitalWrite(latchPin, LOW);
  digitalWrite(latchPin, HIGH);
 
  // Step 2: Shift
  ios = "";
  for (int i = 0; i < bits; i++) {
    int bit = digitalRead(dataPin);
    if (bit == HIGH) {
      ios.concat("1");
    } else {
      ios.concat("0");
    }
    digitalWrite(clockPin, HIGH); // Shift out the next bit
    digitalWrite(clockPin, LOW);
  }
  for(int a = 8; a < bits+8; a = a+8){
    Serial.println("register " + String(a/8) + ": " + ios.substring(a-8,a));
  }
  Serial.println();
  delay(1000);
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.