Shift In 4021 is entering same bit on 2 parallel pins ! help !

Hello,
thank you for taking the time to read my post and try to help i really appreciate it.
So my problem is that I am trying to take parallel input from push buttons using 4021 shift register and an arduino nano. At first i was connecting 6 push buttons to P1-1 to P1-6 on the 4021. and all was working well but the problem happened when i connected 2 more push buttons to P1-7 and P1-8 (please find attached the datasheet and my circuit). From the code that i will share, i am debugging using Serial.println to define which button is being pressed. When i press the push button connected to P1-7 i get result “button 1 is on” and “button 8 is on”. When I press the push button connected to P1-8 I get nothing when i should get “button 8 is on”. So i took my multimeter and tested the pin when the push button is clicked and i get 5v so push button is not broken nor the pin P1-8. So I need your help please to define what is the problem after trying for hours to fix this i got out of options but to ask on this forum.

Thanks in advance for your help :slight_smile:

here is my code:

//Define pins
int dataPin = 7;   // Pin 0 of DigiSpark connected to Pin 3 of CD4021
int clockPin = 2;  // Pin 1 of DigiSpark connected to Pin 10 of CD4021
int latchPin = 4;  // Pin 2 of DigiSpark connected to Pin 9 of CD4021

//Define variable
byte RegisterValue = 0;  // Used to hold data from DC4021

boolean lastPushButton1 = LOW;
boolean currentPushButton1 = LOW;
boolean led1On = false;

boolean lastPushButton2 = LOW;
boolean currentPushButton2 = LOW;
boolean led2On = false;

boolean lastPushButton3 = LOW;
boolean currentPushButton3 = LOW;
boolean led3On = false;

boolean lastPushButton4 = LOW;
boolean currentPushButton4 = LOW;
boolean led4On = false;

boolean lastPushButton5 = LOW;
boolean currentPushButton5 = LOW;
boolean led5On = false;

boolean lastPushButton6 = LOW;
boolean currentPushButton6 = LOW;
boolean led6On = false;

boolean lastPushButton7 = LOW;
boolean currentPushButton7 = LOW;
boolean led7On = false;

boolean lastPushButton8 = LOW;
boolean currentPushButton8 = LOW;
boolean led8On = false;

int led1 = 3;
int led2 = 5;
int led3 = 6;
int led4 = 8;
int led5 = 9;
int led6 = 10;

void setup() {
  Serial.begin(9600);
  //define pins used to connect to the CD4021 Shift Register
  pinMode(dataPin, INPUT);
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT); 

  //the arduino Pins that the LEDs are connected to
  pinMode(led1, OUTPUT); 
  pinMode(led2, OUTPUT); 
  pinMode(led3, OUTPUT); 
  pinMode(led4, OUTPUT); 

}

void loop() {
  //Set latch pin to 1 to get recent data into the CD4021
  digitalWrite(latchPin,1);
  
  delayMicroseconds(20);
  
  //Set latch pin to 0 to get data from the CD4021
  digitalWrite(latchPin,0);

  //Get CD4021 register data in byte variable
  RegisterValue = shiftIn(dataPin, clockPin, MSBFIRST);

  // This is for first push button -----------------------
  currentPushButton1 = debounce(lastPushButton1, 0);
  if(lastPushButton1 == LOW && currentPushButton1 == HIGH)
  {
    led1On = !led1On;
    Serial.println("button 1 is on");
  }
    
  lastPushButton1 = currentPushButton1;
  digitalWrite(led1, led1On);
  // -------------------------------------------------

  // This is for second push button
  currentPushButton2 = debounce(lastPushButton2, 1);
  if(lastPushButton2 == LOW && currentPushButton2 == HIGH)
  {
    led2On = !led2On;
    Serial.println("button 2 is on");
  }
    
  lastPushButton2 = currentPushButton2;
  digitalWrite(led2, led2On);
  // --------------------------------------------------

  // This is for third push button
  currentPushButton3 = debounce(lastPushButton3, 2);
  if(lastPushButton3 == LOW && currentPushButton3 == HIGH)
  {
    led3On = !led3On;
    Serial.println("button 3 is on");
  }
    
  lastPushButton3 = currentPushButton3;
  digitalWrite(led3, led3On);
  // --------------------------------------------------

  // This is for fourth push button
  currentPushButton4 = debounce(lastPushButton4, 3);
  if(lastPushButton4 == LOW && currentPushButton4 == HIGH)
  {
    led4On = !led4On;
    Serial.println("button 4 is on");
  }
    
  lastPushButton4 = currentPushButton4;
  digitalWrite(led4, led4On);
  // --------------------------------------------------

  // This is for fifth push button
  currentPushButton5 = debounce(lastPushButton5, 4);
  if(lastPushButton5 == LOW && currentPushButton5 == HIGH)
  {
    led5On = !led5On;
    Serial.println("button 5 is on");
  }
    
  lastPushButton5 = currentPushButton5;
  digitalWrite(led5, led5On);
  // --------------------------------------------------

  // This is for sixth push button
  currentPushButton6 = debounce(lastPushButton6, 5);
  if(lastPushButton6 == LOW && currentPushButton6 == HIGH)
  {
    led6On = !led6On;
    Serial.println("button 6 is on");
  }
    
  lastPushButton6 = currentPushButton6;
  digitalWrite(led6, led6On);
  // --------------------------------------------------

  // This is for seventh push button
  currentPushButton7 = debounce(lastPushButton7, 6);
  if(lastPushButton7 == LOW && currentPushButton7 == HIGH)
  {
    led7On = !led7On;
    Serial.println("button 7 is on");
  }
    
  lastPushButton7 = currentPushButton7;
  // --------------------------------------------------

  // This is for eighth push button
  currentPushButton8 = debounce(lastPushButton8, 7);
  if(lastPushButton8 == LOW && currentPushButton8 == HIGH)
  {
    led8On = !led8On;
    Serial.println("button 8 is on");
  }
    
  lastPushButton8 = currentPushButton8;
  // --------------------------------------------------
  
  

//delay(100);

}

boolean debounce(boolean last, int bitToRead)
{
  boolean current = bitRead(RegisterValue, bitToRead);
  if(last != current)
  {
    delay(5);
    current = bitRead(RegisterValue, bitToRead);
  }
  return current;
}

HCF4021 Shift In.pdf (287 KB)

the problem happened when i connected 2 more pins to P1-7 and P1-8

What exactly do you mean by this?

The best way to wire up push buttons is to wire a resistor from the input to +5V and wire the buttons between the input and ground.

Grumpy_Mike: What exactly do you mean by this?

The best way to wire up push buttons is to wire a resistor from the input to +5V and wire the buttons between the input and ground.

I'm sorry i corrected it, i meant 2 more push buttons, i see but the thing is i had soldered the wires to C and NO not NC long before that's why i decided to work with 1 and not 0 on the register pins

i see but the thing is i had soldered the wires to C and NO not NC

That doesn’t matter, the only thing is that the sense of the switch is reversed which is simple to compensate for in the software.

|500x375

Grumpy_Mike: That doesn't matter, the only thing is that the sense of the switch is reversed which is simple to compensate for in the software.

Grumpy_Mike i reversed everything so now i am at pullup

I am still having the same problem :/ now when i reset the arduino i get Button 1 is on and Button 8 is on without clicking anything

Try setting the clock pin high at the start of loop(), before the latch pin is set high.

I think the problem here is because of the way the 4021 works compared to the way shiftIn() works. If I understand the data sheet, when the latch pin goes low, the value read from PI-8 is immediately available at Q8. But the first thing shiftIn() does is set the clock pin high before it reads the data. This shifts the value from PI-7 into Q8, loosing the value from PI-8 without ever reading it.

Setting the clock pin high first should prevent loosing the value read from PI-8 before it is read.

PaulRB: Try setting the clock pin high at the start of loop(), before the latch pin is set high.

I think the problem here is because of the way the 4021 works compared to the way shiftIn() works. If I understand the data sheet, when the latch pin goes low, the value read from PI-8 is immediately available at Q8. But the first thing shiftIn() does is set the clock pin high before it reads the data. This shifts the value from PI-7 into Q8, loosing the value from PI-8 without ever reading it.

Setting the clock pin high first should prevent loosing the value read from PI-8 before it is read.

PaulRB: Try setting the clock pin high at the start of loop(), before the latch pin is set high.

I think the problem here is because of the way the 4021 works compared to the way shiftIn() works. If I understand the data sheet, when the latch pin goes low, the value read from PI-8 is immediately available at Q8. But the first thing shiftIn() does is set the clock pin high before it reads the data. This shifts the value from PI-7 into Q8, loosing the value from PI-8 without ever reading it.

Setting the clock pin high first should prevent loosing the value read from PI-8 before it is read.

PaulRB !! You're a D Genius ! it worked perfectly !! :D but please explain what made you give this solution in the datasheet ? because i read the datasheet and did not notice anything unusual

firashelou:
but please explain what made you give this solution in the datasheet ?

Well, that’s what I tried to explain in my previous post.

Here’s the code for shiftIn():

#include "wiring_private.h"

 

uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) {

 uint8_t value = 0;

 uint8_t i;

 for (i = 0; i < 8; ++i) {

 digitalWrite(clockPin, HIGH);

 if (bitOrder == LSBFIRST)

 value |= digitalRead(dataPin) << i;

 else

 value |= digitalRead(dataPin) << (7 - i);

 digitalWrite(clockPin, LOW);

 }

 return value;

}

You can see that it sets clock high before reading the data pin.

Here’s the logic design for 4021:

And for 74hc165 for comparison:

@Mike, would the OP have had the same problem with 74hc165? I can’t quite work it out.

PaulRB:
Well, that’s what I tried to explain in my previous post.

Here’s the code for shiftIn():

#include "wiring_private.h"

uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) {

uint8_t value = 0;

uint8_t i;

for (i = 0; i < 8; ++i) {

digitalWrite(clockPin, HIGH);

if (bitOrder == LSBFIRST)

value |= digitalRead(dataPin) << i;

else

value |= digitalRead(dataPin) << (7 - i);

digitalWrite(clockPin, LOW);

}

return value;

}



You can see that it sets clock high before reading the data pin.

Here's the logic design for 4021:
![|500x175](https://forum.arduino.cc/index.php?action=dlattach;topic=645868.0;attach=332617)

And for 74hc165 for comparison:
![|500x155](https://forum.arduino.cc/index.php?action=dlattach;topic=645868.0;attach=332619)

@Mike, would the OP have had the same problem with 74hc165? I can't quite work it out.

I can’t quite understand what is happening on the circuits, i mean there is a NOT on both Clock and Latch which will give low if set high, then the NAND which will give 1 if both are 0 but then what and I don’t understand why all the inputs are a NOT and not a hex buffer ?

don't understand why all the inputs are a NOT and not a hex buffer ?

I think you are miss understanding two things here.

1) a hex buffer is not the name of a type of buffer, it is the name of a chip that contains six buffers. Chips like the 74xx14 or 74xx04, the xx denotes the technology like LS or HC to HCT to name but three of them.

2) while that is a logic diagram of the circuit, it is not the actual circuit they use to build the chip. It is the equivalent circuit. The real circuit they keep a secret because in the end of the day it is all made from NOR gates as that is all you need to make any logic circuit. You could use NAND gates as well but a NOR gate is simpler to fabricate so they don’t.

All inputs are buffered so they only present a one gate load to the connecting circuitry. In the case of the earliest TTL logic gates unconnected inputs would float high, so many of the compound logic ICs like this are designed to have a logic low to activate an input. When other technologies came along these conventions were kept for compatibility reasons.

Mike, would the OP have had the same problem with 74hc165

I think not. The description of the shift in function from here says:-

If you’re interfacing with a device that’s clocked by rising edges, you’ll need to make sure that the clock pin is low before the first call to shiftIn(), e.g. with a call to digitalWrite(clockPin, LOW).

Grumpy_Mike: I think you are miss understanding two things here.

1) a hex buffer is not the name of a type of buffer, it is the name of a chip that contains six buffers. Chips like the 74xx14 or 74xx04, the xx denotes the technology like LS or HC to HCT to name but three of them.

2) while that is a logic diagram of the circuit, it is not the actual circuit they use to build the chip. It is the equivalent circuit. The real circuit they keep a secret because in the end of the day it is all made from NOR gates as that is all you need to make any logic circuit. You could use NAND gates as well but a NOR gate is simpler to fabricate so they don’t.

All inputs are buffered so they only present a one gate load to the connecting circuitry. In the case of the earliest TTL logic gates unconnected inputs would float high, so many of the compound logic ICs like this are designed to have a logic low to activate an input. When other technologies came along these conventions were kept for compatibility reasons.

thanks Grumpy_Mike for taking the time to explain but I think too much technical info which are hard to get for me :/

Grumpy_Mike: I think not. The description of the shift in function from here says:-

Grumpy_Mike can you please explain what does this exactly means ? " a device that's clocked by rising edges" does it mean that clock is HIGH ?

A device clocked by rising edges responds only to a rising edge on the clock (LOW->HIGH). Simple.

Grumpy_Mike: I think not. The description of the shift in function from here says:-

If you're interfacing with a device that's clocked by rising edges, you'll need to make sure that the clock pin is low before the first call to shiftIn(), e.g. with a call to digitalWrite(clockPin, LOW).

From the '165 data sheet:

Clocking is accomplished by a low-to-high transition of the clock (CLK) input while SH/LD is held high and CLK INH is held low.

From the '4021 data sheet:

When the parallel/serial control input is in the logical “0” state, data is serially shifted into the register synchronously with the positive transition of the clock.

So they are both triggered by rising clock edge...

MarkT:
A device clocked by rising edges responds only to a rising edge on the clock (LOW->HIGH). Simple.

thank you MarkT