// File : Cascade165.ino
//
// Version 1, 5 August 2021, by Koepel
// Initial version.
// Version 2, 5 August 2021, by Koepel
// Layout of the wiring made better.
// Version 3, 13 August 2021, by Koepel
// Changed 'SCK' to 'clockPin'.
//
// Cascade of four 74HC165 shift-in registers.
// Only three pins are used on the Arduino board, to read 32 switches.
//
// Using the 74HC165 is safe, because a pulse to the Latch pin
// ('PL' on the 74HC165) will make a new start every time.
// In case of an error or a wrong clock pulse by noise,
// it synchronizes the data when inputs are read the next time.
//
// Based on:
// (1)
// Demo sketch to read from a 74HC165 input shift register
// by Nick Gammon, https://www.gammon.com.au/forum/?id=11979
// (2)
// 74HC165 Shift register input example
// by Uri Shaked, https://wokwi.com/arduino/projects/306031380875182657
//
//
//TO INVERT OUTPUT THE 74HC165 Connected directly to UNO connect uno with Q7_N
//FOR CONNECTION INSIDE OF CHAIN USE Q7
const byte latchPinIn = 9;
const byte clockPin = 13;
const byte dataPinIn = 12;
const byte latchPinOut = 6;
const byte dataPinOut = 5;
void setup ()
{
//Serial.begin( 115200);
pinMode( clockPin, OUTPUT); // clock signal, idle LOW
digitalWrite (clockPin, LOW);
pinMode( latchPinIn, OUTPUT); // latch (copy input into registers), idle HIGH
digitalWrite( latchPinIn, HIGH);
pinMode( dataPinIn, INPUT);
pinMode(latchPinOut, OUTPUT);
digitalWrite( latchPinOut, HIGH);
pinMode(dataPinOut, OUTPUT);
}
// 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 requires to read the bit first and then give a clock pulse.
//
uint8_t shiftIn74HC165(uint8_t _dataPin, uint8_t _clockPin, uint8_t bitOrder) {
uint8_t value = 0;
uint8_t i;
for (i = 0; i < 8; ++i) {
if (bitOrder == LSBFIRST)
value |= digitalRead(_dataPin) << i;
else
value |= digitalRead(_dataPin) << (7 - i);
digitalWrite(_clockPin, HIGH);
digitalWrite(_clockPin, LOW);
}
return value;
}
void updateShiftRegister(word state_reg)
{
digitalWrite(latchPinOut, LOW);
shiftOut(dataPinOut, clockPin, MSBFIRST, state_reg >> 8);
shiftOut(dataPinOut, clockPin, MSBFIRST, state_reg >> 0);
digitalWrite(latchPinOut, HIGH);
}
word readShiftRegister()
{
// Give a pulse to the parallel load latch of all 74HC165
digitalWrite( latchPinIn, LOW);
digitalWrite( latchPinIn, 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.
word inreg = shiftIn74HC165(dataPinIn, clockPin, MSBFIRST);
inreg |= shiftIn74HC165(dataPinIn, clockPin, MSBFIRST) << 8;
return inreg;
}
void loop()
{
word _state = readShiftRegister();
updateShiftRegister(_state);
/*Serial.print(millis());
Serial.print(" : ");
Serial.println(_state, BIN);*/
}