3x 74HC165, one of them not working

Hi,
I have 3 74HC165in series, the first two(right and middle in the schematic) give me the correct value, but the 3rd (left)shows always on for all 8 inputs...
Trying to debug I found out that the 74HC165 that is connected to the arduino pin D11 gives always 1s. That does not make sense (at least to me), if there was a problem in hardware none of the 3 IC should work...
What I get as output is buttons 0 to 15 working, buttons 16 to 23 always on.
The code I am using is below, the schematic is attached.
Thanks.

#include <UTFT.h>

// How many shift register chips are daisy-chained.
#define NUMBER_OF_SHIFT_CHIPS   3

/* Width of data (how many ext lines).
*/
#define DATA_WIDTH   NUMBER_OF_SHIFT_CHIPS * 8

/* Width of pulse to trigger the shift register to read and latch.
*/
#define PULSE_WIDTH_USEC   5

/* Optional delay between shift register reads.
*/
#define POLL_DELAY_MSEC   1

/* You will need to change the "int" to "long" If the
 * NUMBER_OF_SHIFT_CHIPS is higher than 2.
*/
#define BYTES_VAL_T unsigned long

extern uint8_t BigFont[];
UTFT myGLCD (ILI9325D_8,38,39,40,41);   

int ploadPin        = 8;  // Connects to Parallel load pin the 165
int clockEnablePin  = 9;  // Connects to Clock Enable pin the 165
int dataPin         = 11; // Connects to the Q7 pin the 165
int clockPin        = 12; // Connects to the Clock pin the 165
int b[24]; //keeps the value of each switch (TO PRINT)
BYTES_VAL_T pinValues;
BYTES_VAL_T oldPinValues;

/* This function is essentially a "shift-in" routine reading the
 * serial Data from the shift register chips and representing
 * the state of those pins in an unsigned integer (or long).
*/
BYTES_VAL_T read_shift_regs()
{
    byte bitVal;
    BYTES_VAL_T bytesVal = 0;

    /* Trigger a parallel Load to latch the state of the data lines,
    */
    digitalWrite(clockEnablePin, HIGH);
    digitalWrite(ploadPin, LOW);
    delayMicroseconds(PULSE_WIDTH_USEC);
    digitalWrite(ploadPin, HIGH);
    digitalWrite(clockEnablePin, LOW);

    /* Loop to read each bit value from the serial out line
     * of the SN74HC165N.
    */
    for(int i = 0; i < DATA_WIDTH; i++)
    {
        bitVal = digitalRead(dataPin);

        /* Set the corresponding bit in bytesVal.
        */
        bytesVal |= (bitVal << ((DATA_WIDTH-1) - i));

        /* Pulse the Clock (rising edge shifts the next bit).
        */
        digitalWrite(clockPin, HIGH);
        delayMicroseconds(PULSE_WIDTH_USEC);
        digitalWrite(clockPin, LOW);
    }

    return(bytesVal);
}

/* Dump the list of zones along with their current status.
*/
void display_pin_values()
{
    for(int i = 0; i < DATA_WIDTH; i++)
    {
        if((pinValues >> i) & 1)
            b[i]=1;
            
        else
            b[i]=0;

        
    }
   myGLCD.setColor(VGA_WHITE);
   myGLCD.setBackColor(VGA_BLACK);
   myGLCD.printNumI(b[0], 0, 20);
   myGLCD.printNumI(b[1], 36, 20);
   myGLCD.printNumI(b[2], 72, 20);
   myGLCD.printNumI(b[3], 108, 20);
   myGLCD.printNumI(b[4], 144, 20);
   myGLCD.printNumI(b[5], 180, 20);
   myGLCD.printNumI(b[6], 216, 20);
   myGLCD.printNumI(b[7], 252, 20);
   
   myGLCD.printNumI(b[8], 0, 120);
   myGLCD.printNumI(b[9], 36, 120);
   myGLCD.printNumI(b[10], 72, 120);
   myGLCD.printNumI(b[11], 108, 120);
   myGLCD.printNumI(b[12], 144, 120);
   myGLCD.printNumI(b[13], 180, 120);
   myGLCD.printNumI(b[14], 216, 120);
   myGLCD.printNumI(b[15], 252, 120);
   
   myGLCD.printNumI(b[16], 0, 220);
   myGLCD.printNumI(b[17], 36, 220);
   myGLCD.printNumI(b[18], 72, 220);
   myGLCD.printNumI(b[19], 108, 220);
   myGLCD.printNumI(b[20], 144, 220);
   myGLCD.printNumI(b[21], 180, 220);
   myGLCD.printNumI(b[22], 216, 220);
   myGLCD.printNumI(b[23], 252, 220);
 
}
void buttonNumberDisplay()
{//prints a number for each button, below this number 0 or 1 will be printed by display_pin_values()
   myGLCD.setColor(VGA_WHITE);
   myGLCD.setBackColor(VGA_BLUE);
   myGLCD.printNumI(1, 0, 0);
   myGLCD.printNumI(2, 36, 0);
   myGLCD.printNumI(3, 72, 0);
   myGLCD.printNumI(4, 108, 0);
   myGLCD.printNumI(5, 144, 0);
   myGLCD.printNumI(6, 180, 0);
   myGLCD.printNumI(7, 216, 0);
   myGLCD.printNumI(8, 252, 0);
   
   myGLCD.printNumI(9, 0, 100);
   myGLCD.printNumI(10, 36, 100);
   myGLCD.printNumI(11, 72, 100);
   myGLCD.printNumI(12, 108, 100);
   myGLCD.printNumI(13, 144, 100);
   myGLCD.printNumI(14, 180, 100);
   myGLCD.printNumI(15, 216, 100);
   myGLCD.printNumI(16, 252, 100);
   
   myGLCD.printNumI(17, 0, 200);
   myGLCD.printNumI(18, 36, 200);
   myGLCD.printNumI(19, 72, 200);
   myGLCD.printNumI(20, 108, 200);
   myGLCD.printNumI(21, 144, 200);
   myGLCD.printNumI(22, 180, 200);
   myGLCD.printNumI(23, 216, 200);
   myGLCD.printNumI(24, 252, 200); 
}//end firstDisplay
void setup()
{
   // Serial.begin(9600);
    myGLCD.InitLCD();
    myGLCD.clrScr();
    myGLCD.setFont(BigFont);
    myGLCD.setBackColor(VGA_BLACK);
    /* Initialize our digital pins...
    */
    pinMode(ploadPin, OUTPUT);
    pinMode(clockEnablePin, OUTPUT);
    pinMode(clockPin, OUTPUT);
    pinMode(dataPin, INPUT);

    digitalWrite(clockPin, LOW);
    digitalWrite(ploadPin, HIGH);
    buttonNumberDisplay();
    /* Read in and display the pin states at startup.
    */
    pinValues = read_shift_regs();
    display_pin_values();
    oldPinValues = pinValues;
}

void loop()
{
    /* Read the state of all zones.
    */
    pinValues = read_shift_regs();

    /* If there was a chage in state, display which ones changed.
    */
    if(pinValues != oldPinValues)
    {
        display_pin_values();
        oldPinValues = pinValues;
    }

    delay(POLL_DELAY_MSEC);
}

Does the problem change if you swap the chips around? If so, it's a hardware problem. If not, it's a software problem.

Try a simpler sketch for loading the data in.
Make sure you have 0.1uF cap from power pin of all devices to Gnd.

#include <SPI.h> // use internal hardware shift register
byte byte0;
byte byte1;
byte byte2;
byte latchPin = 10;

void setup(){
pinMode (latchPin, OUTPUT);
SPI.begin(); // connect D13 to CLK & CLKINHIBIT; connect D12 to final QH; connect latchPin to SH/LD
}

void loop(){
digitalWrite (latchPin, LOW);
digitalWrite (latchPin, HIGH); // 165s capture data on inputs
byte0 = SPI.transfer(0); // sends dummy byte out on D11 while reading on D12
byte1 = SPI.transfer(0);
byte2 = SPI.transfer(0);

Serial.print ("byte0");
Serial.printl(byte0);
Serial.print ("byte1");
Serial.printl(byte1);
Serial.print ("byte2");
Serial.printl(byte3);

delay(500); // give yourself a chance to see the data
}

If that doesn't work, remove the MC14490 and connect the 165 inputs to +5, GND, see if they are read correctly. Keep narrowing down the possibilities of what can be bad.

You may want to check your hardware design. It looks like the notes in the schematic say these two things:

  • You're grounding the 14490 inputs through a 10K resistor. The 14490's have an internal pullup resistor; they're intended to be driven by an active input, or grounded directly. When the switch is closed, the 10K resistor keeps the input voltage close to the worst-case VIL of the 14490, 1.5V at VDD=5V. A 14490, or more than one, might not be able to see a low input at that voltage.
  • The Q'H outputs of the 74HC165's are grounded. Q'H - pin 7 - is an output on the 74HC165; if it's not used, it should be open, not grounded. Maybe that's a typographical error?

Hi,
thanks for the replies.
@PAULS: swapping the ics around, even using a new set of 3 74HC165 and 4 mc14490, gives same results.
putting rightmost ic(instead of leftmost) as output to arduino gives buttons 0 to 7 always on , buttons 8 to 23
working.
@tmd3: q'h to GND is a typo, they are left alone... i have to correct the diagram.
removed the resistor (checked the datasheet, you are right)->same results
i think that if the 14490 was the problem i would have only 6 "bad" outputs, instead i have 8 "bad" ones (i think
this should be a bad 74hc165 and/or bad software?)
@CrossRoads:
removing the debouncers is a complete chaos(everything constantly fluctuating...)
using your sketch (with or without debouncers) i always get byte0:0 byte1:0 byte2:0 as an output

#include <SPI.h> // use internal hardware shift register
byte byte0;
byte byte1;
byte byte2;

byte latchPin = 10;

void setup(){
pinMode (latchPin, OUTPUT);
SPI.begin(); // connect D13 to CLK & CLKINHIBIT; connect D12 to final QH; connect latchPin to SH/LD
Serial.begin(9600);
}

void loop(){
digitalWrite (latchPin, LOW);
digitalWrite (latchPin, HIGH); // 165s capture data on inputs
byte0 = SPI.transfer(0); // sends dummy byte out on D11 while reading on D12
byte1 = SPI.transfer(0);
byte2 = SPI.transfer(0);

Serial.print ("byte0:");
Serial.println(byte0);
Serial.print ("byte1:");
Serial.println(byte1);
Serial.print ("byte2:");
Serial.println(byte2);

delay(500); // give yourself a chance to see the data
}

output sample:
byte0:0
byte1:0
byte2:0
......
byte0:0
byte1:0
byte2:0

i also am not sure about "Make sure you have 0.1uF cap from power pin of all devices to Gnd"
something like the diagram below (cap.jpg)? wouldn't that be a short circuit?
i will try it when i get the capacitors, unfortunately i will not have them until tomorrow...

my thoughts are: i tested individually each ic using many arduino boards, then started building more complex systems (1 piso / 2 debouncers, then 2 piso/3 debouncers) everything is fine until i introduce the 3rd piso in the circuit. from my pov there is something wrong with the software, i cannot identify it though...

Many many thanks to all of you for the help!!!

cap.jpg

kolasni:
i think this should be a bad 74hc165 and/or bad software?

Alternative 3: Wiring error. If I had to speculate, based on what you've told us so far, I'd guess that the LOAD signal isn't getting to your third IC. That would mean that the IC would never get new data, but it would dutifully shift out its powerup value. That might be 0xFF. A way to test that might be to program the Arduino to toggle the LOAD pin low for several seconds, and then high for several seconds. You should be able to see it on a voltmeter. If there's no voltmeter, you could hook up an LED and resistor, or set pin 13 to INPUT and run a jumper from LOAD to pin 13 and watch the on-board LED.

I think that this

swapping the ICs around, even using a new set of 3 74HC165 and 4 mc14490, gives same results.

argues against the theory that one of the 165's is broken. The problem follows the location in the circuit, rather than the specific IC, suggesting that it's a software problem - like something being an int that should be a long - or a wiring problem - like some signal isn't going where you think it does.

Another possibility for this error might be a bad ground for some of your switches. We can't tell how they're wired - they might be hooked up in groups of eight. One way to test this is to look at the 14490's output pin voltages relative to ground, and observe that they change.

removing the debouncers is a complete chaos (everything constantly fluctuating...)

Can you clarify that? Do you mean that the outputs change even when the inputs are stable, or do you mean that changing an input results in many changes in the output? When you removed the 14490's, did you reconnect the switches directly to the 165, or did you leave the 165's input pins open-circuited?

from my pov there is something wrong with the software

Maybe. Your symptoms - failure to register changes on the highest of three bytes of data - suggest that the data passes through some storage location that's only 16 bits wide, making the high-order byte disappear. A cursory look through your code doesn't find that, though. I'm favoring a wiring error.

I posted my solution here chain from 3 x 74hc165 shiftin registers - General Electronics - Arduino Forum,
enjoy :slight_smile:

i also am not sure about "Make sure you have 0.1uF cap from power pin of all devices to Gnd"
something like the diagram below (cap.jpg)? wouldn't that be a short circuit?

Capacitors do not conduct at DC so there is no short circuit.
See:-
http://www.thebox.myzen.co.uk/Tutorial/De-coupling.html

I cleaned up the above code a little and added qty4 shift registers using SPI. It works, it works... yay

#include <SPI.h> // use internal hardware shift register
byte byte0;
byte byte1;
byte byte2;
byte byte3;
byte byte4;
byte latchPin = 10;

void setup(){
Serial.begin(9600);
pinMode (latchPin, OUTPUT);
SPI.begin(); // connect D13 to CLK & CLKINHIBIT; connect D12 to final QH; connect D10 latchPin to SH/LD
}

void loop(){
digitalWrite (latchPin, LOW);
digitalWrite (latchPin, HIGH); // 165s capture data on inputs
byte0 = SPI.transfer(0); // sends dummy byte out on D11 while reading on D12
byte1 = SPI.transfer(0);
byte2 = SPI.transfer(0);
byte3 = SPI.transfer(0);
byte4 = SPI.transfer(0);

Serial.print ("byte0: ");
Serial.println(byte0);
Serial.print ("byte1: ");
Serial.println(byte1);
Serial.print ("byte2: ");
Serial.println(byte2);
Serial.print ("byte3: ");
Serial.println(byte3);
Serial.print ("byte4: ");
Serial.println(byte4);
Serial.println(" ");
delay(1000); // give yourself a chance to see the data
}

this code makes it really easy to check your inputs:

//define where your pins are
int latchPin = 8; // Connects to /PL aka Parallel load aka latch pin on the 74HC165
int dataPin = 10; // Connects to the Q7 pin on the 74HC165 (MISO for SPI)
int clockPin = 12; // Connects to the Clock pin on the 74HC165

int clockEnablePin = 9; // Connects to Clock Enable pin on the 74HC165 (should always be low)

//Define variables to hold the data
//for each shift register.
byte switchVar1;
byte OLDswitchVar1;
byte switchVar2;
byte OLDswitchVar2;
byte switchVar3;
byte OLDswitchVar3;
byte switchVar4;
byte OLDswitchVar4;

//------------------------------------------------start print loop
void display_switch_values()
{
for(int i = 0; i <= 7; i++)
{
if((switchVar1 >> i) & 1)
Serial.print(1);
else
Serial.print(0);
}
for(int i = 0; i <= 7; i++)
{
if((switchVar2 >> i) & 1)
Serial.print(1);
else
Serial.print(0);
}
for(int i = 0; i <= 7; i++)
{
if((switchVar3 >> i) & 1)
Serial.print(1);
else
Serial.print(0);
}
for(int i = 0; i <= 7; i++)
{
if((switchVar4 >> i) & 1)
Serial.print(1);
else
Serial.print(0);
}

Serial.print("\r\n");
}
//------------------------------------------------end print loop

////------------------------------------------------start setup
void setup() {
//start serial
Serial.begin(9600);

//define pin modes
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, INPUT);

pinMode(clockEnablePin, OUTPUT);
digitalWrite(clockEnablePin, LOW);
}
//------------------------------------------------end setup

////------------------------------------------------start main loop
void loop() {
digitalWrite(latchPin, LOW);
delayMicroseconds(5);
digitalWrite(latchPin, HIGH);

switchVar1 = shiftIn(dataPin, clockPin);
switchVar2 = shiftIn(dataPin, clockPin);
switchVar3 = shiftIn(dataPin, clockPin);
switchVar4 = shiftIn(dataPin, clockPin);

if (switchVar1 != OLDswitchVar1 || switchVar2 != OLDswitchVar2 || switchVar3 != OLDswitchVar3 || switchVar4 != OLDswitchVar4)
{
display_switch_values();
OLDswitchVar1 = switchVar1;
OLDswitchVar2 = switchVar2;
OLDswitchVar3 = switchVar3;
OLDswitchVar4 = switchVar4;
}
//delay so all these print satements can keep up.
delay(50);
}
//------------------------------------------------end main loop

////// ----------------------------------------start shiftIn function

byte shiftIn(int myDataPin, int myClockPin) {
int i;
int temp = 0;
int pinState;
byte myDataIn = 0;

pinMode(myClockPin, OUTPUT);
pinMode(myDataPin, INPUT);

for (i=7; i>=0; i--)
{
digitalWrite(myClockPin, 0);
delayMicroseconds(2);
temp = digitalRead(myDataPin);
if (temp) {
pinState = 1;
myDataIn = myDataIn | (1 << i);
}
digitalWrite(myClockPin, 1);
}
return myDataIn;
}
//------------------------------------------------end shiftIn function

@hydronics: Code tags, please.