CD4021 incoming byte format question.

I've got a TI CD4021BE hooked up and functioning on an UNO with 8 buttons attached to it. The data received from the buttons comes in as 10 for button one, 100 for button 2, etc. Or, 110 if buttons 1 & 2 are pressed at the same time.

I'm wanting to get an output of the entire set of buttons, kind of like an array ( [10011001] } or something so that I can see which buttons are pressed during each clock pulse. I just can't figure out how to format that correctly to get that to happen.

The code so far, is simple enough...

int dataPin = 9;   
int clockPin = 7;  
int latchPin = 8;  


byte RegisterValue = 0;  

void setup() {
  Serial.begin(9600);
  pinMode(dataPin, INPUT);
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT); 

}

void loop() {

  digitalWrite(latchPin,1);
  delayMicroseconds(20);
  digitalWrite(latchPin,0);
  RegisterValue = shiftIn(dataPin, clockPin, MSBFIRST);
  
  if (RegisterValue > 1) {
    Serial.println(RegisterValue, BIN);
  }
delay(200);

}

I'm getting some occasional 1s popping out of it. I'm assuming that is some noise, since I don't have a capacitor hooked up. Hence the cavoite to the If statement there. Any advise of how to get all the values?

'm getting some occasional 1s popping out of it.

You expect an analysis of something like that with no schematic or wiring diagram? Not going to happen.

Show us a good schematic of your circuit.
Show us a good image of your ‘actual’ wiring.
Give links to components.
Posting images:
https://forum.arduino.cc/index.php?topic=519037.0

CMOS inputs float, you should ensure they are valid H/L.

I'm not too worried about the occasional 1s just yet. I'm trying to figure out how to format the data.

That's up to you. It is already formatted, so to speak, it's an 8 bit byte.

There are as many ways of dealing with that as there are programmers. <- hyperbole.

Often you will see bit testing, like to check for switch N if you number the switches 0..7 you could

if (RegisterValue & (1 << N)) {
/* switch N is pressed! /
/
do whatever! */
}

But what means "something so that I can see which buttons are pressed during each clock pulse"? ShiftIn does all the clocking and returns the entire register… printing it in BIN format will show you what buttons are pressed each time through the loop().

Take the cavoite off you Serial.println and just let the result spin up the screen whilst you play with the buttons.

BTW your latch is up for an eternity, it's your time to waste but take a look at the CD4021 data sheet. Just sayin'.

a7

Imgur: The magic of the Internet
A schematic of what I've done.
Imgur: The magic of the Internet
What it currently looks like...

Okay, so the pics didn't work. Meh,

The bulk of the code is just copied and pasted from others, so I'm just building on their foundation. That's where I got the 20ms from for the latch.

I'd just like to see the data represented as an array. It's gotta be either so simple that nobody want's to say it, or so freakin hard that nobody wants to say they don't know how.

How do I make this: 110 Look like this: 00000011 ???

Try this is a trick:

intr kk = 0x100 + RegisterValue;
Serial.println(kk, BIN);

It will always have a 1 in the ninth position but you'll see the 8 lower order bits including any what were leading 0s.

HTH

a7

Bugiroff:
How do I make this: 110 Look like this: 00000011 ???

Divide by 2. If you search the forum for "leading zero binary" or something like that, you'll find the many threads covering this common question.

Okay, so the pics didn't work.

Load them in a paint program and export the image to another file, to strip the metadata that the forum software rejects. I know, it's a PITA.

Right then. Using Alto777's method (thank you!) this is what I'm now getting:
100000010 (for button 1)
100000100 (for button 2)
100001000 (for button 3)
100010000 (for button 4)
100100000 (for button 5)
101000000 (for button 6)
110000001 (for button 7)
Button 8 is not giving me anything at all. Going by the schematic that I now have up above, the button is hooked up to Q8. Which should, I think, be a viable pin to use for another input. Am I wrong on that? Looks like it is on the data sheet. Am I off a pin somewhere? Pin 1 is giving me a 10, not a 1. Is there something I missed?

Oh, my shipment of buttons came in this afternoon, so now I have all 8 hooked up. Probably should have mentioned that. :slight_smile:

Updated code:

int dataPin = 9;   
int clockPin = 7;  
int latchPin = 8;  


byte RegisterValue = 0;  

void setup() {
  Serial.begin(9600);
  pinMode(dataPin, INPUT);
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT); 

}

void loop() {

  digitalWrite(latchPin,1);
  delayMicroseconds(15);
  digitalWrite(latchPin,0);
  RegisterValue = shiftIn(dataPin, clockPin, MSBFIRST);
  int kk = 0x100 + RegisterValue;
  if (RegisterValue > 0) {
    Serial.println(kk, BIN);
    //Serial.println(RegisterValue, BIN);
  }
delay(200);

}

Edit - need more time to look at this, meanwhile this is interesting from the shiftIn() docs,

"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)."

Just a bit of an update...

My 8th button did not want to work, and I couldn't figure out why. Turns out that you do indeed need to set the clock HIGH between the latch high and lows to get the proper reading of all 8 buttons. The web sites I've seen this on say it may be some sort of a glitch in the library or something, but this works and gets all 8 buttons working the way I wanted them to. Other than adding the first 1 to the output, but I can find a way to deal with that.

Good Stuff!

int dataPin = 9;   
int clockPin = 7;  
int latchPin = 8;  


byte RegisterValue = 0;  

void setup() {
  Serial.begin(9600);
  pinMode(dataPin, INPUT);
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT); 

}

void loop() {

  digitalWrite(latchPin,1);
  digitalWrite(clockPin, 1);
  delayMicroseconds(20);
  digitalWrite(latchPin,0);
  RegisterValue = shiftIn(dataPin, clockPin, MSBFIRST);
  int kk = 0x100 + RegisterValue;
  if (RegisterValue != 0) {
    Serial.println(kk, BIN);
    //Serial.println(RegisterValue, BIN);
  }
delay(250);

}

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