I made a PCB for the CD4021 to get more inputs. But it's not working.
All resistors are 5k1 ohm. When nothing is connected to an input I measure 4.7V, when I connect 5V to simulate a button press I measure -0.3V. Clearly something is off.
//**************************************************************//
// Name : shiftIn Example 2.1 //
// Author : Carlyn Maw //
// Date : 25 Jan, 2007 //
// Version : 1.0 //
// Notes : Code for using a CD4021B Shift Register //
// : //
//****************************************************************
//define where your pins are
int latchPin = 6;
int dataPin = 2;
int clockPin = 5;
//Define variables to hold the data
//for each shift register.
//starting with non-zero numbers can help
//troubleshoot
byte switchVar1 = 72; //01001000
byte switchVar2 = 159; //10011111
byte switchVar3 = 159; //10011111
byte switchVar4 = 159; //10011111
byte switchVar5 = 159; //10011111
byte switchVar6 = 159; //10011111
void setup() {
//start serial
Serial.begin(9600);
//define pin modes
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, INPUT);
}
void loop() {
//Pulse the latch pin:
//set it to 1 to collect parallel data
digitalWrite(latchPin,1);
//set it to 1 to collect parallel data, wait
delayMicroseconds(20);
//set it to 0 to transmit data serially
digitalWrite(latchPin,0);
//while the shift register is in serial mode
//collect each shift register into a byte
//the register attached to the chip comes in first
switchVar1 = shiftIn(dataPin, clockPin);
// switchVar2 = shiftIn(dataPin, clockPin);
// switchVar3 = shiftIn(dataPin, clockPin);
// switchVar4 = shiftIn(dataPin, clockPin);
// switchVar5 = shiftIn(dataPin, clockPin);
// switchVar6 = shiftIn(dataPin, clockPin);
//Print out the results.
//leading 0's at the top of the byte
//(7, 6, 5, etc) will be dropped before
//the first pin that has a high input
//reading
Serial.println(switchVar1, BIN);
// if(switchVar1 > 0) Serial.println(switchVar1, BIN);
// if(switchVar2 > 0) Serial.println(switchVar2, BIN);
delay(500);
// Serial.println(switchVar1, BIN);
// Serial.println(switchVar2, BIN);
// Serial.println(switchVar3, BIN);
// Serial.println(switchVar4, BIN);
// Serial.println(switchVar5, BIN);
// Serial.println(switchVar6, BIN);
}
//------------------------------------------------end main loop
////// ----------------------------------------shiftIn function
///// just needs the location of the data pin and the clock pin
///// it returns a byte with each bit in the byte corresponding
///// to a pin on the shift register. leftBit 7 = Pin 7 / Bit 0= Pin 0
byte shiftIn(int myDataPin, int myClockPin) {
Serial.println("ShiftIn Function");
int i;
int temp = 0;
int pinState;
byte myDataIn = 0;
pinMode(myClockPin, OUTPUT);
pinMode(myDataPin, INPUT);
//we will be holding the clock pin high 8 times (0,..,7) at the
//end of each time through the for loop
//at the begining of each loop when we set the clock low, it will
//be doing the necessary low to high drop to cause the shift
//register's DataPin to change state based on the value
//of the next bit in its serial information flow.
//The register transmits the information about the pins from pin 7 to pin 0
//so that is why our function counts down
for (i=7; i>=0; i--)
{
digitalWrite(myClockPin, 0);
delayMicroseconds(2);
temp = digitalRead(myDataPin);
if (temp) {
pinState = 1;
//set the bit to 0 no matter what
myDataIn = myDataIn | (1 << i);
}
else {
//turn it off -- only necessary for debuging
//print statement since myDataIn starts as 0
pinState = 0;
}
//Debuging print statements
//Serial.print(pinState);
//Serial.print(" ");
//Serial.println (dataIn, BIN);
digitalWrite(myClockPin, 1);
}
//debuging print statements whitespace
//Serial.println();
//Serial.println(myDataIn, BIN);
return myDataIn;
}
Great that you posted a schematic. It is a little tangled and difficult to read. My tip to improve it would be to use the +V and GND symbols that most schematic drawing packages have. Put as many of these around your schematic as you like, one per chip or even more. Then you don't have to join up all the 5V & ground lines with wires, which is making your schematic look so tangled.
When you say you are measuring -0.3V, where are you placing the meter probes?
Are you using these old chips just to read buttons? How many? 32? This can be done with 12 Arduino pins and no extra chips, if you make your buttons into a matrix.
PaulRB:
Great that you posted a schematic. It is a little tangled and difficult to read. My tip to improve it would be to use the +V and GND symbols that most schematic drawing packages have. Put as many of these around your schematic as you like, one per chip or even more. Then you don't have to join up all the 5V & ground lines with wires, which is making your schematic look so tangled.
Hi Paul,
Thanks once again for your answer! I tried decluttering the schematic, but it didn't really look any better. So instead I painted lines over all the important parts, I sincerely hope it's readable now!
PaulRB:
When you say you are measuring -0.3V, where are you placing the meter probes?
I placed 1 probe on the Pi-1 pin for example, and the other on the GND pin.
PaulRB:
Are you using these old chips just to read buttons? How many? 32? This can be done with 12 Arduino pins and no extra chips, if you make your buttons into a matrix.
I am indeed using these just to read buttons. I thought this solution would be fancier and better expandable than a button matrix. If these don't work out (it'd be a shame because I already had the PCB's manufactured since I got it to work on my breadboards), i'll try to make another one with a matrix. I'd prefer this simply because of the fact I already have most components.
Please let me know if you can help me further or need anything else!
Okay, I removed 5 IC's and just kept going with one. It would occassionally work, the way I hold it seems to matter... this is really weird.
Edit: not sure, but now I can't get it to work anymore. I feel like all my IC's broke or something..
Edit1: I thought about the grid, but it'll use too many pins considering I am using an Arduino Mini for the HID support.
It sounds to me like you have floating inputs. They would be easily influenced by being touched, or might just not work at all sometimes. Did you design the PCB? Maybe you made an error, PCB design isn't easy, even for experienced people, and judging by your schematic, I'm guessing you're new to that also. Try using your meter to check continuity between all the points that should be ground, all the Vcc points etc.
Your bypass caps seem to be 1uF. Usually they should be 0.1uF, ceramic, and close to the Vcc pin of each chip. Using a larger cap may not be as effective.
What do you mean by "HID support"?
What else do you need the Arduino pins for, so that you can't spare 12 for the matrix?
PaulRB:
It sounds to me like you have floating inputs. They would be easily influenced by being touched, or might just not work at all sometimes. Did you design the PCB? Maybe you made an error, PCB design isn't easy, even for experienced people, and judging by your schematic, I'm guessing you're new to that also. Try using your meter to check continuity between all the points that should be ground, all the Vcc points etc.
Your bypass caps seem to be 1uF. Usually they should be 0.1uF, ceramic, and close to the Vcc pin of each chip. Using a larger cap may not be as effective.
What do you mean by "HID support"?
What else do you need the Arduino pins for, so that you can't spare 12 for the matrix?
My bypass condensators are 0.1uF tantalum capacitors (the 1uF was a typo). Could that be a problem?
By HID support I mean when the Arduino board is connected to the computer, it shows up as a device so I can use the Joystick library. The ultimate goal is a button box.
Also, I am using this Arduino Micro so it would barely have enough pins, I also need 1 pin for an output, so I'd need another Arduino aswell (which is fine, but it just gets expensive having to replace all the parts):
For now I am hoping using the right capacitor would fix the problem. What do you think?
topiek:
I am using an Arduino Mini for the HID support.
Ah, another typo. You can't use Arduino Mini for USB HID, but you can use Micro. That's why I asked the question, wondering if you had chosen the wrong Arduino for your project.
I doubt changing the capacitor type will have any effect, but try that if you like.
Can you say more about the way the keyboard will be used? For typing text? Playing music? A crucial question would be do you need the ability to cope with multiple simultaneous key presses (rollover)?
I still don't get why you think Micro will not have enough pins for a key matrix. 12 will be needed for 32 keys. 16 would allow for 64 keys. Micro has 20 digital pins.
PaulRB:
Ah, another typo. You can't use Arduino Mini for USB HID, but you can use Micro. That's why I asked the question, wondering if you had chosen the wrong Arduino for your project.
I doubt changing the capacitor type will have any effect, but try that if you like.
Can you say more about the way the keyboard will be used? For typing text? Playing music? A crucial question would be do you need the ability to cope with multiple simultaneous key presses (rollover)?
I still don't get why you think Micro will not have enough pins for a key matrix. 12 will be needed for 32 keys. 16 would allow for 64 keys. Micro has 20 digital pins.
I am making a button box, mainly for gaming (simracing). So it would be nice if I could press multiple buttons at once.
I find it weird that the PCB sometimes works and sometimes it doesn't, so I am hoping changing capacitor type fixes it (I ordered ceramic capacitors)
larryd:
Note: after your parallel load, read bit 1 first then on the subsequent bits execute the code above.
What do you mean by this exactly? My current code is the following:
//**************************************************************//
// Name : shiftIn Example 2.1 //
// Author : Carlyn Maw //
// Date : 25 Jan, 2007 //
// Version : 1.0 //
// Notes : Code for using a CD4021B Shift Register //
// : //
//****************************************************************
//define where your pins are
int latchPin = 6;
int dataPin = 2;
int clockPin = 5;
//Define variables to hold the data
//for each shift register.
//starting with non-zero numbers can help
//troubleshoot
byte switchVar1 = 72; //01001000
byte switchVar2 = 159; //10011111
byte switchVar3 = 159; //10011111
byte switchVar4 = 159; //10011111
byte switchVar5 = 159; //10011111
byte switchVar6 = 159; //10011111
void setup() {
//start serial
Serial.begin(9600);
//define pin modes
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, INPUT);
digitalWrite(clockPin, 0);
}
void loop() {
//Pulse the latch pin:
//set it to 1 to collect parallel data
digitalWrite(latchPin,1);
//set it to 1 to collect parallel data, wait
delayMicroseconds(20);
//set it to 0 to transmit data serially
digitalWrite(latchPin,0);
//while the shift register is in serial mode
//collect each shift register into a byte
//the register attached to the chip comes in first
switchVar1 = shiftIn(dataPin, clockPin);
// switchVar2 = shiftIn(dataPin, clockPin);
// switchVar3 = shiftIn(dataPin, clockPin);
// switchVar4 = shiftIn(dataPin, clockPin);
// switchVar5 = shiftIn(dataPin, clockPin);
// switchVar6 = shiftIn(dataPin, clockPin);
//Print out the results.
//leading 0's at the top of the byte
//(7, 6, 5, etc) will be dropped before
//the first pin that has a high input
//reading
//if(switchVar1 > 0) {
Serial.print("Switchvar 1:");
Serial.print(switchVar1, BIN);
Serial.print("\n");
//}
// if(switchVar2 > 0) Serial.println(switchVar2, BIN);
delay(500);
// Serial.println(switchVar1, BIN);
// Serial.println(switchVar2, BIN);
// Serial.println(switchVar3, BIN);
// Serial.println(switchVar4, BIN);
// Serial.println(switchVar5, BIN);
// Serial.println(switchVar6, BIN);
}
//------------------------------------------------end main loop
////// ----------------------------------------shiftIn function
///// just needs the location of the data pin and the clock pin
///// it returns a byte with each bit in the byte corresponding
///// to a pin on the shift register. leftBit 7 = Pin 7 / Bit 0= Pin 0
byte shiftIn(int myDataPin, int myClockPin) {
//Serial.println("ShiftIn Function");
int i;
int temp = 0;
int pinState;
byte myDataIn = 0;
pinMode(myClockPin, OUTPUT);
pinMode(myDataPin, INPUT);
//we will be holding the clock pin high 8 times (0,..,7) at the
//end of each time through the for loop
//at the begining of each loop when we set the clock low, it will
//be doing the necessary low to high drop to cause the shift
//register's DataPin to change state based on the value
//of the next bit in its serial information flow.
//The register transmits the information about the pins from pin 7 to pin 0
//so that is why our function counts down
for (i=7; i>=0; i--)
{
//digitalWrite(myClockPin, 0);
//delayMicroseconds(2);
digitalWrite(myClockPin, 1);
digitalWrite(myClockPin,0);
temp = digitalRead(myDataPin);
if (temp) {
pinState = 1;
//set the bit to 0 no matter what
myDataIn = myDataIn | (1 << i);
}
else {
//turn it off -- only necessary for debuging
//print statement since myDataIn starts as 0
pinState = 0;
}
//Debuging print statements
//Serial.print(pinState);
//Serial.print(" ");
//Serial.println (dataIn, BIN);
digitalWrite(myClockPin, 1);
}
//debuging print statements whitespace
//Serial.println();
//Serial.println(myDataIn, BIN);
return myDataIn;
}
The sketch offered you can be used with either 74HC165 or the CD4021 parallel to serial shift registers.
As the comments state, the pins are a different between these two chips.
Yours (CD4021) use 9 (latch) 10 (clock) 3 (data).
The pins on the Arduino can be any I/O pin you wish to use, hence 6, 5 and 2.
This line of code “#define CD4021” should make the code work with your CD4021.
I have proven the code works with the 74HC165, but I do not have a CD4021 to test.
Your code worked just fine with the CD4021. My issue was that I am a little dumb and I soldered 2 green wires, 1 for some LED output and one for the latch wire. Now in my code I had the led output pin (pin 6) as latch, because I got the wires mixed up as they were both green. It seems to work now though.