Shifting in with 74HC165N Trouble

I'm having no luck whatsoever with the 74HC165 entry in the Arduino Playground.

I have it wired up according to the comments but when i fire it up it says all the inputs are low then immediately states they've changed and all have gone high. then it sits with with no updates to the serial window regardless of whether a button is pressed or not. I have 8 buttons wired to go high when pressed and pulled down low via 100k resistors when not pressed. does this sketch actually work? has anyone had success with it? It's been frustrating me going on a month now.

/*
 * SN74HC165N_shift_reg
 *
 * Program to shift in the bit values from a SN74HC165N 8-bit
 * parallel-in/serial-out shift register.
 *
 * This sketch demonstrates reading in 16 digital states from a
 * pair of daisy-chained SN74HC165N shift registers while using
 * only 4 digital pins on the Arduino.
 *
 * You can daisy-chain these chips by connecting the serial-out
 * (Q7 pin) on one shift register to the serial-in (Ds pin) of
 * the other.
 * 
 * Of course you can daisy chain as many as you like while still
 * using only 4 Arduino pins (though you would have to process
 * them 4 at a time into separate unsigned long variables).
 * 
*/

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

/* 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 int

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

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()
{
    Serial.print("Pin States:\r\n");

    for(int i = 0; i < DATA_WIDTH; i++)
    {
        Serial.print("  Pin-");
        Serial.print(i);
        Serial.print(": ");

        if((pinValues >> i) & 1)
            Serial.print("HIGH");
        else
            Serial.print("LOW");

        Serial.print("\r\n");
    }

    Serial.print("\r\n");
}

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

    /* Initialize our digital pins...
    */
    pinMode(ploadPin, OUTPUT);
    pinMode(clockEnablePin, OUTPUT);
    pinMode(clockPin, OUTPUT);
    pinMode(dataPin, INPUT);

    digitalWrite(clockPin, LOW);
    digitalWrite(ploadPin, HIGH);

    /* 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)
    {
        Serial.print("*Pin value change detected*\r\n");
        display_pin_values();
        oldPinValues = pinValues;
    }

    delay(POLL_DELAY_MSEC);
}

I eventually want to daisychain a second 165N for 16 inputs on 4 I/O lines but figured it'd be easier to find my problem working with just one shift register.

Thanks in advance,

Svaroh

I have it wired up according to the comments

The pins in the description are not the chip pins are these right?
Power and ground OK? And a decoupling capacitor across the supply of the chip?

wired to go high when pressed and pulled down low via 100k resistors

Clack handed way of going about things you should be pulling to ground with a switch and up with a 10K. However the way round you have it:-

Too high a value of resistor. Make them 10K to 1K pull downs.

does this sketch actually work

let's get the hardware right first. :wink:

ok. the pins in the description are arduino pins. the datasheet for the 74HC165N is here 74HC165 Datasheet pdf - 8-bit parallel-in/serial-out shift register - Philips

I have arduino pin 8 to IC pin 1
arduino pin 9 to IC pin 15
arduino pin 10 to IC pin 7
arduino pin 11 to IC pin 2

I have rearranged my circuit to have pull up resistors rather than pull downs, the value I'm using is 2.2K

the results are more consistant but still puzzling.

when the serial monitor is opened it reports the status of all the pins as low. this seemed odd to me as they all the pins were pulled high, maybe its the sketch compensating.

there is no change to the serial monitor when a button is pressed, that is until all 8 buttons have been pressed at least once, then it reports all pins as high then immediately reports them all low again. I've found this to be repeatable every time. Why doesn't it report when only one pin has changed?

I have no decoupling capacitor across the supply of the chip, it's being powered by the arduino. If one is necessary, what value would be appropriate?

ok, I've determined that I was wrong about all 8 buttons (numbered 0-7) having to be pressed at least once, turns out that only the button 7 is being read, no response from the others. Button 7 is connected to pin 6 on the SR, the pin designated D7.

the sketch polls the parallel input of the shift register (the buttons) at set intervals, and is only supposed to report if there is a change. so in theory if i held a button down, lets say button 7 since it seems to work, the serial monitor ought to say "pin value change detected then list all the pins and their current value, all low save pin 7. but what happens is it cycles between all low and all low save 7 which reads high.
(I should add that button 7 which is connected to pin 7 more than occasionally causes pin 2, or 3 or 6 to read high instead of pin 7, it is consistent that it causes only one pin to go high. but not always the right one.

i found this sketch in the arduino playground and took for granted that it worked. if someone can see something i've done wrong or a mistake in the code I'd really appreciate the help :slight_smile:

It does sound that your wiring is not right. things like this:-

more than occasionally causes pin 2, or 3 or 6 to read high instead of pin 7,

Do not happen with chips if they are wired up right.

I have no decoupling capacitor across the supply of the chip

It could be your problem 0.1uF is what to use. please read:-
http://www.thebox.myzen.co.uk/Tutorial/De-coupling.html

alright.
I've added the decoupling capacitor across the chip supply.
I can't find anywhere that the wiring could be wrong.
All 8 inputs on the shift register (D0-D7) are pulled high with 2.21k resistors, I've stopped using the button panel I'd made and am now using a jumper wire to simply connect an input pin to ground.

when i reset the arduino it boots up then reports all pins low.
when i ground D7 it reports all pins high with the exception of pin 7 which is reported low. If D7 is held grounded the serial monitor reports all low then all low but D7 then all low ...over and over. though there are anomalous reports occasionally. it will sometimes report D6 or D6 and D5 low while the others are high

this is what i mean

*Pin value change detected*
Pin States:
  Pin-0: LOW
  Pin-1: LOW
  Pin-2: LOW
  Pin-3: LOW
  Pin-4: LOW
  Pin-5: LOW
  Pin-6: LOW
  Pin-7: LOW

*Pin value change detected*
Pin States:
  Pin-0: HIGH
  Pin-1: HIGH
  Pin-2: HIGH
  Pin-3: HIGH
  Pin-4: HIGH
  Pin-5: HIGH
  Pin-6: HIGH
  Pin-7: LOW

*Pin value change detected*
Pin States:
  Pin-0: LOW
  Pin-1: LOW
  Pin-2: LOW
  Pin-3: LOW
  Pin-4: LOW
  Pin-5: LOW
  Pin-6: LOW
  Pin-7: LOW

*Pin value change detected*
Pin States:
  Pin-0: HIGH
  Pin-1: HIGH
  Pin-2: HIGH
  Pin-3: HIGH
  Pin-4: HIGH
  Pin-5: HIGH
  Pin-6: HIGH
  Pin-7: LOW

*Pin value change detected*
Pin States:
  Pin-0: LOW
  Pin-1: LOW
  Pin-2: LOW
  Pin-3: LOW
  Pin-4: LOW
  Pin-5: LOW
  Pin-6: LOW
  Pin-7: LOW

*Pin value change detected*
Pin States:
  Pin-0: HIGH
  Pin-1: HIGH
  Pin-2: HIGH
  Pin-3: HIGH
  Pin-4: HIGH
  Pin-5: HIGH
  Pin-6: LOW
  Pin-7: LOW

*Pin value change detected*
Pin States:
  Pin-0: LOW
  Pin-1: LOW
  Pin-2: LOW
  Pin-3: LOW
  Pin-4: LOW
  Pin-5: LOW
  Pin-6: LOW
  Pin-7: LOW

*Pin value change detected*
Pin States:
  Pin-0: HIGH
  Pin-1: HIGH
  Pin-2: HIGH
  Pin-3: HIGH
  Pin-4: HIGH
  Pin-5: HIGH
  Pin-6: HIGH
  Pin-7: HIGH

*Pin value change detected*
Pin States:
  Pin-0: LOW
  Pin-1: LOW
  Pin-2: LOW
  Pin-3: LOW
  Pin-4: LOW
  Pin-5: LOW
  Pin-6: LOW
  Pin-7: LOW

I am convinced I have this wired correctly. If anyone who understands code better than me could have a look at this sketch for anything that could be causing me these problems I would be eternally grateful.

Did you see it Grumpy_Mike? I don't know how many times I checked my connections to the arduino but i missed it every time. If you did see it, thanks for letting me find it on my own. i think i learned more.

the sketch clearly states
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

I had it wired up
int ploadPin = 8; // Connects to Parallel load pin the 165
int clockEnablePin = 9; // Connects to Clock Enable pin the 165
int dataPin = 10; // Connects to the Q7 pin the 165
int clockPin = 11; // Connects to the Clock pin the 165

see? data pin left floating and no clock pin wired in. everytime it tryed to shift the data out to the arduino the floating data pin had no input. and with no clock pin hooked up only the last bit was available.

workin great now.

cheers

Did you see it Grumpy_Mike

Well not exactly but I was convinced it wasn't wired up right. :slight_smile:

So, like a few others here whose posts I've been reading, my goal is a menu displayed on an lcd.

Length: 0
Pieces: 0

where the 0s are settable by the keypad entering numbers. the length number will also be used to to control a stepper and the pieces will be the number of cycles. It's to be an automatic wire cutter.

The issue I am currently having is how to take the binary serial data and have it represent individual button presses. The shift register code i got from the playground uses a 'for' control to report pins high or low. I'm thinking that i can repurpose this to change the values of int's representing the buttons, then i can use those to enter the number they represent into another int that will be displayed and control the stepper and countdown of cycles.

I dont know if this'll work (as i've not been able to make it as yet) or if there's a simpler solution i've not seen/ dont know about.

Help, as always, would be greatly appreciated.

my butchery of the shiftregister code from the playground follows:

/*
 * SN74HC165N_shift_reg
 *
 * Program to shift in the bit values from a SN74HC165N 8-bit
 * parallel-in/serial-out shift register.
 *
 * This sketch demonstrates reading in 16 digital states from a
 * pair of daisy-chained SN74HC165N shift registers while using
 * only 4 digital pins on the Arduino.
 *
 * You can daisy-chain these chips by connecting the serial-out
 * (Q7 pin) on one shift register to the serial-in (Ds pin) of
 * the other.
 * 
 * Of course you can daisy chain as many as you like while still
 * using only 4 Arduino pins (though you would have to process
 * them 4 at a time into separate unsigned long variables).
 * 
*/

/*INPUT BUTTON SHIFT RESIGISTER (74HC165) SETUP
*/

#define NUMBER_OF_SHIFT_CHIPS   1                               //How many shift register chips are daisy-chained.
#define DATA_WIDTH   NUMBER_OF_SHIFT_CHIPS * 8                  //Width of data (how many ext lines).
#define PULSE_WIDTH_USEC   5                                    //Width of pulse to trigger the shift register to read and latch.
#define POLL_DELAY_MSEC   1                                     //Optional delay between shift register reads.
#define BYTES_VAL_T unsigned int                                //You will need to change the "int" to "long" If the NUMBER_OF_SHIFT_CHIPS is higher than 2.

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

BYTES_VAL_T pinValues;
BYTES_VAL_T oldPinValues;

//the states of the buttons to be set by a modified version of the 'void display_pin_values()' funcion further down in the sketch
int button_1 = 0;
int button_2 = 0;
int button_3 = 0;
int button_4 = 0;
int button_5 = 0;
int button_6 = 0;
int button_7 = 0;
int button_8 = 0;
/* 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);
}

/*   LCD SCREEN SETUP STUFF (74HC595)
*/

#include <ShiftLCD.h>

ShiftLCD lcd(2, 4, 3);

int wire_length = 0;
int number_of_pieces = 0;

/* Dump the list of zones along with their current status.
*/


void display_pin_values()
{
    Serial.print("Pin States:\r\n");

    for(int i = 0; i < DATA_WIDTH; i++)
    {
        //Serial.print("  Pin-");
        //Serial.print(i);
        //Serial.print(": ");

        if((pinValues >> i) & 1)
            Serial.print("HIGH");
        else
            Serial.print("LOW");

        Serial.print("\r\n");
    }

    Serial.print("\r\n");
}

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

    /* Initialize our digital pins...
    */
    pinMode(ploadPin, OUTPUT);
    pinMode(clockEnablePin, OUTPUT);
    pinMode(clockPin, OUTPUT);
    pinMode(dataPin, INPUT);

    digitalWrite(clockPin, LOW);
    digitalWrite(ploadPin, HIGH);

    /* Read in and display the pin states at startup.
    */
    pinValues = read_shift_regs();
  //  display_pin_values();
    oldPinValues = pinValues;
    
    lcd.begin(16, 2);      // set up the LCD's number of rows and columns
    lcd.setCursor(0, 0);    // move cursor to top row
    lcd.print("Length: ");
    lcd.setCursor(0, 1);    // move cursor to bottom row
    lcd.print("Pieces:");
    lcd.setCursor(8, 0);
    lcd.print(wire_length);
    lcd.setCursor(8, 1);
    lcd.print(number_of_pieces);
}

void loop()
{

  // Turn off the cursor:
  lcd.noCursor();
  delay(500);
   // Turn on the cursor:
  lcd.cursor();
  delay(500);
  
  /* Read the state of all zones.
    */
   // pinValues = read_shift_regs();

    /* If there was a chage in state, display which ones changed.
    */
   // if(pinValues != oldPinValues)
   // {
     //   Serial.print("*Pin value change detected*\r\n");
        //display_pin_values();
     //   oldPinValues = pinValues;
  //  }

  //  delay(POLL_DELAY_MSEC); */
}

Hi,

I'm getting nowhere with this code and would really appreciate a nudge in the right direction.

I was thinking of trying to use the keypad library and define a 1 dimentional aray (ie. string) but I don't understand how to convert the binary serial data from the 165 shift register into something the keypad library understands.

if the string is keypad_binary == 00000000
then turns to read_keypad_binary == 00001000
i can say if read_keypad_binary != keypad_binary
then a button has been pressed.
(how to I have the sketch determine which button has been pressed?)
then have keypad_binary = read_keypad_binary

or

Is there a way to create virtual pins for the arduino? each represented by a digit in the serial string from the shift register?

ie: 8 bit string -> 00000000
each digit represented by a letter abcdefgh

have digit 'a' be digital pin 14, digit 'b' digital pin 15.... etc

if someone could shove me in the right direction, or even just tell me i'm so wrong it hurts to read my post, i'd be ever so thankful.

Is this what you're looking for?

if (keypad_binary & B10000) {
    // some button was pressed
}

if (keypad_binary & B1000) {
    // some other button was pressed
}