Arduino Pro Micro and 74HC165 for 20 buttons

Hello.
I am struggling for a few weeks now to code a 20 button series and to use a joystick library with a daisy-chained shift register to allow for that many inputs on an Arduino pro micro. (leonardo) to use as HID device.

Could anyone guide me or help me troubleshoot this code?

This is the code I was able to get so far.

#include <ShiftIn.h>
#include <Joystick.h>

ShiftIn<3> shift; // use one shift register

//Joystick_ joystick;

//Setting my Joystick Left MFCD with 20 buttons(Jostick ID"0x15, Type, N#of buttons, N#of Axis)
Joystick_ Joystick(0x15, JOYSTICK_TYPE_GAMEPAD, 20, 0, false, false, false, false, false,false,false,false,false,false,false);
void setup() {

// Initialize Button Pins
pinMode(8, INPUT_PULLUP);
pinMode(9, INPUT_PULLUP);
pinMode(10, INPUT_PULLUP);
pinMode(16, INPUT_PULLUP);

// declare pins: pLoadPin, clockEnablePin, dataPin, clockPin
shift.begin(8, 9, 10, 16); // set pins of the shift register
// Initialize Button Pins

// Initialize Joystick Library
Joystick.begin();
}

void loop() {

if (digitalRead(0) == HIGH)
{Joystick.setButton(13, LOW);}
else
{Joystick.setButton(13, HIGH);}

if (digitalRead(1) == HIGH)
{Joystick.setButton(14, LOW);}
else
{Joystick.setButton(14, HIGH);}

if (digitalRead(2) == HIGH)
{Joystick.setButton(15, LOW);}
else
{Joystick.setButton(15, HIGH);}

if (digitalRead(3) == HIGH)
{Joystick.setButton(16, LOW);}
else
{Joystick.setButton(16, HIGH);}

if (digitalRead(4) == HIGH)
{Joystick.setButton(12, LOW);}
else
{Joystick.setButton(12, HIGH);}

if (digitalRead(5) == HIGH)
{Joystick.setButton(11, LOW);}
else
{Joystick.setButton(11, HIGH);}

if (digitalRead(6) == HIGH)
{Joystick.setButton(10, LOW);}
else
{Joystick.setButton(10, HIGH);}

if (digitalRead(7) == HIGH)
{Joystick.setButton(9, LOW);}
else
{Joystick.setButton(9, HIGH);}

if (digitalRead(8) == HIGH)
{Joystick.setButton(5, LOW);}
else
{Joystick.setButton(5, HIGH);}

if (digitalRead(9) == HIGH)
{Joystick.setButton(6, LOW);}
else
{Joystick.setButton(6, HIGH);}

if (digitalRead(10) == HIGH)
{Joystick.setButton(7, LOW);}
else
{Joystick.setButton(7, HIGH);}

if (digitalRead(11) == HIGH)
{Joystick.setButton(8, LOW);}
else
{Joystick.setButton(8, HIGH);}

if (digitalRead(12) == HIGH)
{Joystick.setButton(1, LOW);}
else
{Joystick.setButton(1, HIGH);}

if (digitalRead(13) == HIGH)
{Joystick.setButton(2, LOW);}
else
{Joystick.setButton(2, HIGH);}

if (digitalRead(14) == HIGH)
{Joystick.setButton(3, LOW);}
else
{Joystick.setButton(3, HIGH);}

if (digitalRead(15) == HIGH)
{Joystick.setButton(4, LOW);}
else
{Joystick.setButton(4, HIGH);

if (digitalRead(16) == HIGH)
{Joystick.setButton(17, LOW);}
else
{Joystick.setButton(17, HIGH);}

if (digitalRead(17) == HIGH)
{Joystick.setButton(18, LOW);}
else
{Joystick.setButton(18, HIGH);}

if (digitalRead(18) == HIGH)
{Joystick.setButton(19, LOW);}
else
{Joystick.setButton(19, HIGH);}

if (digitalRead(19) == HIGH)
{Joystick.setButton(20, LOW);}
else
{Joystick.setButton(9, HIGH);}

if (digitalRead(20) == HIGH)
{Joystick.setButton(10, LOW);}
else
{Joystick.setButton(10, HIGH);}

{
if (shift.update())
for (int i = 0; i < shift.getDataWidth(); i++)
Joystick.setButton(i, shift.state(i)); // just press or release the button
}
delay(10);
}

I thank you in advance to help me troubleshoot this code.

This one is not like the others.

There seems to be too much code, and not enough debug statements - the Pro Micro has a USB serial, does it not?

Please remember to use code tags when posting code

Thanks . I think this is a typo. But it was not in the original coding. I have fixed. The issue is somewhere else.

As I said, there seems to be too much code, so try reducing the amount of somewhere else.

How are the shift registers wired? Pullup resistor on each input, and switch closure to Gnd?
Do you have 0.1uF/100nF cap on each shift registers Vcc pin to Gnd?

Why are the control pins to the shift registers declared as inputs? Odd.

I think I can reduce the
if (digitalRead(0) == HIGH)
{Joystick.setButton(13, LOW);}
else
{Joystick.setButton(13, HIGH);}

to:
Joystick.setButton(13, !digitalRead(0));

But I am a bit confused with what the 0 and the 13 are in this context?

They're pin numbers.

Even with your optimisation, there's still a lot of somewhere else.

Where do the shift registers get used?

Basically I need to set 20 buttons to a pro micro using the joystick library. As there is not enough inputs, I am using 3 shift registers connected in cascade.
The confusing part to me is the pin numbers. I am only using 4 pins in the arduino and all the inputs are going in the shift register pins, which to my understanding are not stated in the code.

But it's your code.

Didn't you notice the lack of shift register reading?

Why? It seems odd using a library that in the face if it has nothing to do with your problem.

Just code the thing and forget about libraries, you don’t seem to understand how to use it and I am dubious about it being the right solution.

If all your buttons are connected to the shift register inputs, then they are not in an array , they are just individual buttons.

All that code you have could probably be done in less that 8 lines of code.

I am creating a franckstein out of all I can get off of the internet and this forum. I am new to arduino coding. My understanding is really limited to figure out and troubleshoot. I had it working once for 8 buttons and only one shift register. But when i tried to cascade another one it stoped working.

One fix I figured out now is this..

//Define connections to 74HC165
int load = 8;
int clockEnablepin = 9;
int dataIn = 10;
int clockIn = 16;
  
void setup() {

// Initialize Button Pins
pinMode(load, OUTPUT);//load
pinMode(clockEnablepin, OUTPUT);//clock
pinMode(dataIn, OUTPUT);//data
pinMode(clockIn, INPUT); //clockin

I had it all pins previously set as INPUTS and I declared a variable to them.

Thanks. I am using the library because it is the only way I know how to then connect the arduino to my PC via USB and the PC recognizes it as a Joystick.
You are right, I used the word array wrongly, but the intended outcome is to have 20 individual buttons sending the serial data to one arduino inpit and then turning that individual signal to a joystick button press.

My updated code so far:

#include <ShiftIn.h>
#include <Joystick.h>

ShiftIn<3> shift; // use one shift register

//Joystick_ joystick;

//Setting my Joystick Left MFCD with 20 buttons(Jostick ID"0x15, Type, N#of buttons, N#of Axis)
Joystick_ Joystick(0x15, JOYSTICK_TYPE_GAMEPAD, 21, 0, false, false, false, false, false,false,false,false,false,false,false);

//Define connections to 74HC165
int load = 8;
int clockEnablepin = 9;
int dataIn = 10;
int clockIn = 16;
  
void setup() {

// Initialize Button Pins
pinMode(load, OUTPUT);//load
pinMode(clockEnablepin, OUTPUT);//clock
pinMode(dataIn, OUTPUT);//latch
pinMode(clockIn, INPUT); //input from buttons

// declare pins: pLoadPin, clockEnablePin, dataPin, clockPin
shift.begin(8, 9, 10, 16); // set pins of the shift register
// Initialize Button Pins

// Initialize Joystick Library
Joystick.begin();
}

void loop() {

Joystick.setButton(13, !digitalRead(0));
Joystick.setButton(14, !digitalRead(1));
Joystick.setButton(15, !digitalRead(2));
Joystick.setButton(16, !digitalRead(3));
Joystick.setButton(12, !digitalRead(4));
Joystick.setButton(11, !digitalRead(5));
Joystick.setButton(10, !digitalRead(6));
Joystick.setButton(9, !digitalRead(7));
Joystick.setButton(5, !digitalRead(8));
Joystick.setButton(6, !digitalRead(9));
Joystick.setButton(7, !digitalRead(10));
Joystick.setButton(8, !digitalRead(11));
Joystick.setButton(1, !digitalRead(12));
Joystick.setButton(2, !digitalRead(13));
Joystick.setButton(3, !digitalRead(14));
Joystick.setButton(4, !digitalRead(15));
Joystick.setButton(17, !digitalRead(16));
Joystick.setButton(18, !digitalRead(17));
Joystick.setButton(19, !digitalRead(18));
Joystick.setButton(20, !digitalRead(19));
Joystick.setButton(10, !digitalRead(20));
{
  
if (shift.update()) 
for (int i = 0; i < shift.getDataWidth(); i++)
Joystick.setButton(i, shift.state(i)); // just press or release the button
}
delay(10);
}

Did that code look anything at all like what you are trying now? Imma guess no...

Post that working 8 buttons one shift register code and we can help you expand it to many buttons, multiple shift registers.

a7

I would just do it with 3 SPI transfers.
Connect SCK to the shift register clock,
MISO to the shift register data out with all 3 of them daisychained (data out to data in, data out to data in, data out to MISO),
and a Load line to the Shift register Load/latch pin

then:

digitalWrite (loadPin, LOW); // capture the inputs
digitalWrite (loadPin, HIGH); // inputs ignored when SH/LD is high
shift1 = SPI.transfer (0); // 0  would get shifted out on MOSI if it was connected
shift2 = SPI.transfer(0);
shift3 = SPI.transfer(0);

The A-H inputs need pullup resistors, and button/switches are used to connect them low.
After sampling and reading in the data, compare each byte to 0xFF, if not = then a button has been closed, send the data out.
Or combine the 3 bytes into an unsigned long and send that out.
Or process as you need.

That digitalRead, and all others are wrong.
That command reads a physical pin from the processor, unless you have all your buttons connected to pins and not a shift register it will not work.

You need to read all your shift registers into a long int variable type. Then go through that variable one bit at a time to extract each button and pass it to the appropriate joystick pin.

If you wire your buttons the other way round to your shift register you will not have to invert the signal before passing it to the shift register. How have you wired them? The recommended way is to wire them between input and ground and put a 10K resistor from input to 5V. This is known as a pull up resistor, where as a lot of examples you see use a resistor to ground a pull down resistor which is sub optimal.

Thanks, that's right on! my difficulty is I could not yet figure out how I read the data string coming from the shift register and attribute a joystick button to it. Would you have a code example to share?

For the circuit, I am using a 1K resistor connected to the ground pin on the arduino ( I believe its a Pull Down set up) see image schematic image attached.

The '165 Gnd pins do not appear to be connected to the Promicro Gnd.
You need a 0.1uF cap from 16 to 8 on each chip.

After that, it's just a matter of reading in the 3 bytes. I would use SPI.transfer() as I suggested earlier, or shiftIn() 3 times.

Thats true the ground is not connected on my schematics. Good catch, thanks. I will try the SPI transfer method. But I believe I will still get stuck on the same issue. I can not figure out how to transform the bit string reading into a joystick push button. This is where I can not get around.

Where/what is this library? Does it allow a concept of multiple serially connected hardware shift registers?

a7