Arduino Micro Pro Switch button question using keypad 6x6

I want to ask you a question.
I connected it like this, but only some of it works.
I want to know why.
Is it because of insufficient voltage that only some of it works?
Or I wonder if this Arduino does not support 32 buttons at the same time in the language.
Please tell me what is wrong.
Can't 16 buttons work at the same time?

/********** 36 Buttons and 3 Rotary Encoders button box by BaldEagle gaming **********/ 

/*
*This code is for creating a button box with 36 buttons with 3 rotaries and 0 axis
*This code is for Arduino pro micro
*The table below is showing how the buttons are connected to the board (pin)

*A3, A2, A1, A0, 15 and 14 Are the Row Pins for the Keypad 16 and 10-6 are the Column Pins
*the buttons are connected to each others according to this table

*      : A3    A2    A1    A0    15    14
*  ....................................................
*  16  :  0     1     2     3     4     5           I
*  10  :  6     7     8     9    10    11      
*   9  : 12    13    14    15    16    17
*   8  : 18    19    20    21    22    23
*   7  : 24    25    26    27    28    29
*   6  : 30    31    32    33    34    35

* Pin 0, 1, 2, 3, 4, and 5 plus the GND are used for rotaries
*/

//Including libraries and define variables and give a constant value name

#include <Keypad.h>          //#include is used to include libraries from outside the code.
#include <Joystick.h>        


#define enablePullUps      //#define is used to give a name to a constant value.
						  //or to define a new variable 



const byte numOfRotaries = 3;      //creating variables to define number of rotary encoders     
     


//Creating an array with pins that are used
// for more info: 21 = A3, 20 = A2, 19 = A1, 18 = A0 ....
byte colPins[] = {21,20,19,18,15,14};   
byte rowPins[] = {16,10,9,8,7,6}; 

       										
//define size of array
const int numOfColumns = sizeof(colPins)/sizeof(colPins[0]);
const int numOfRows = sizeof(rowPins)/sizeof(rowPins[0]);


// Creating a 2D array that contains the buttons and also symboling them
byte buttons[numOfRows][numOfColumns] = {          
	{0,1,2,3,4,5},              
	{6,7,8,9,10,11},            
	{12,13,14,15,16,17},       
	{18,19,20,21,22,23},
	{24,25,26,27,28,29},
	{30,31,32,33,34,35},
};

       
//Inislize new keypad class
Keypad ButtonBox = Keypad( makeKeymap(buttons), 
	rowPins, colPins, numOfRows, numOfColumns); 
  

//create and define the joystick
Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID, JOYSTICK_TYPE_JOYSTICK, 
	42, 0,                  // 36 atsButtons, 3x2 rotary encoder (each rotary is count as 2 buttons 
							//(clockwise (turn right) and counterclockwise (turn left)), 0 hat switch,          
	false, false, false,       // no X axis, Y axis, and/or Z axis
	false, false, false,      // no Rx, Ry, Rz                          
	false, false,             // no rudder and/or throttle
	false, false, false);     // no accelerator, break, and/or steering
  
  
//creating structure (A structure can contain variables, methods, static constructor, ...)
struct rotariesStruct {
	byte pin1;             //define pins and create 3 variabes
	byte pin2;
	int cClockWise;
	int clockWise;
	volatile unsigned char state;																								
};


rotariesStruct rotariesEncoders[numOfRotaries] {
	//this will create 3 rotaries
	{0,1,36,37,0},    //pin 0 and 1 are connected to button 36, 37  (rotary)
	{2,3,38,39,0},   
	{4,5,40,41,0},
};

//rotary table
#define DIR_CCW 0x10     //DIR = Directory            
#define DIR_CW 0x20     //ccw = counter clockwise   CW = clockwise
#define R_START 0x0     //R_start = rotary start

#ifdef HALF_STEP
//use half step
	#define R_CCW_BEGIN    0x1
	#define R_CW_BEGIN     0x2
	#define R_START_M      0x3
	#define R_CW_BEGIN_M   0x4
	#define R_CCW_BEGIN_M  0x5
	const unsigned char rotaryTable[6][4] = {  //[6][4] mean 6 rows and 4 columns 
	// R_START (00)
	{R_START_M,            R_CW_BEGIN,     R_CCW_BEGIN,  R_START},
	// R_CCW_BEGIN
	{R_START_M | DIR_CCW, R_START,        R_CCW_BEGIN,  R_START},
	// R_CW_BEGIN
	{R_START_M | DIR_CW,  R_CW_BEGIN,     R_START,      R_START},
	// R_START_M (11)
	{R_START_M,            R_CCW_BEGIN_M,  R_CW_BEGIN_M, R_START},
	// R_CW_BEGIN_M
	{R_START_M,            R_START_M,      R_CW_BEGIN_M, R_START | DIR_CW},
	// R_CCW_BEGIN_M
	{R_START_M,            R_CCW_BEGIN_M,  R_START_M,    R_START | DIR_CCW},                                
	};

#else
//use full step
	#define R_CW_FINAL      0x1
	#define R_CW_BEGIN      0x2
	#define R_CW_NEXT       0x3
	#define R_CCW_BEGIN     0x4
	#define R_CCW_FINAL     0x5
	#define R_CCW_NEXT      0x6

	const unsigned char rotaryTable[7][4] = {  //7*4
	// R_START
	{R_START,    R_CW_BEGIN,  R_CCW_BEGIN, R_START},
	// R_CW_FINAL
	{R_CW_NEXT,  R_START,     R_CW_FINAL,  R_START | DIR_CW},
	// R_CW_BEGIN
	{R_CW_NEXT,  R_CW_BEGIN,  R_START,     R_START},
	// R_CW_NEXT
	{R_CW_NEXT,  R_CW_BEGIN,  R_CW_FINAL,  R_START},
	// R_CCW_BEGIN
	{R_CCW_NEXT, R_START,     R_CCW_BEGIN, R_START},
	// R_CCW_FINAL
	{R_CCW_NEXT, R_CCW_FINAL, R_START,     R_START | DIR_CCW},
	// R_CCW_NEXT
	{R_CCW_NEXT, R_CCW_FINAL, R_CCW_BEGIN, R_START},
	};
#endif

  

void setup() {      //setup() is a method called when the program start, and create the variabes and 
                    //pin mode......
	Joystick.begin();
	initializeRotaryEncoders();
}


void loop() {    //loop() is a method that run for ever

	CheckingButtons();           //this mean that these 2 methods will run for ever
	CheckingRotaryEncoder();
  
}


//CheckingButtons() function will check the state of the buttons
void CheckingButtons() {       
    if (ButtonBox.getKeys()){      
       for (int i=0; i<LIST_MAX; i++) {     //LIST_MAX is a variabe created in keypad.ccp and keypad.h
           if ( ButtonBox.key[i].stateChanged ) {  //this mean if the button has been pressed/hold or released
              switch (ButtonBox.key[i].kstate) {    
                    case PRESSED:     //if the button is pressed and/or hold
                    case HOLD:                        
						Joystick.setButton(ButtonBox.key[i].kchar, 1);  //value will be set to 1 = ON in binary
						break;                                          
                    case RELEASED:    //if the button is idle or released          
                    case IDLE:
						Joystick.setButton(ButtonBox.key[i].kchar, 0);  //value will set to 0 = OFF in binary
						break;                                           
              }                 
          }                   
      }          
   }
}


void initializeRotaryEncoders() {        //create and initial rotary
	for (int i=0;i<numOfRotaries;i++) {
	pinMode(rotariesEncoders[i].pin1, INPUT);  //set pins to input 
	pinMode(rotariesEncoders[i].pin2, INPUT);
	#ifdef enablePullUps
		digitalWrite(rotariesEncoders[i].pin1, HIGH);   //set pins value to high
		digitalWrite(rotariesEncoders[i].pin2, HIGH);  
	#endif
  }
}

//Create and check pin state
unsigned char rotaryProcess(int i) {   
	unsigned char pinState = (digitalRead(rotariesEncoders[i].pin2) << 1) 
								| digitalRead(rotariesEncoders[i].pin1);	//get the pins state
	rotariesEncoders[i].state = rotaryTable[rotariesEncoders[i].state     //determine a new state
								& 0xf][pinState];
	return (rotariesEncoders[i].state & 0x30);		//return the created event																																
}

//check all rotaries encoder
void CheckingRotaryEncoder() {    
	for (int i=0;i<numOfRotaries;i++) {
		unsigned char result = rotaryProcess(i);
		if (result == DIR_CCW) {         //if the rotary has been turned to left
			Joystick.setButton(rotariesEncoders[i].cClockWise, 1); //value will be set to 1
			delay(250);    //waiting 250ms = 1/4 second before set the value to 0
			Joystick.setButton(rotariesEncoders[i].cClockWise, 0);
		}
		if (result == DIR_CW) {  //if  the rotary is turned to the right
			Joystick.setButton(rotariesEncoders[i].clockWise, 1); 
			delay(250); 
			Joystick.setButton(rotariesEncoders[i].clockWise, 0);
		}
	}
}

please teach me

Which part does not work ?

Only 4~6 buttons work, other buttons don't work.
Is it because of insufficient power?

Please describe exactly which buttons do not work
Do they use a common row or column pin ?

You need to use pinMode() to declare some of your pins as outputs.

Edit:
or does keypad.h do that for you?

incorrect

@shinjaehwan
you can disconnect half of Rows and generate presses from releases appropriate switches
pro 1 instance is 32 buttons allowed, but you can using second instance for next 4 buttons and encoders
UPD. it is possible to create single device with 128 buttons, but seems not all apps and OSs support this.

image
image

Thanks for your reply.
When I test it by connecting rows and columns individually, it works fine.
(It works fine for 1 column, 6 rows.)
But from 2 columns and 6 rows, only some buttons work.
ㅠㅠ

Thank you for your interest and reply.
I don't use an inverter.
Is the problem caused by the inverter command in the Arduino code?

/********** 36 Buttons and 3 Rotary Encoders button box by BaldEagle gaming **********/

/*
  This code is for creating a button box with 36 buttons with 3 rotaries and 0 axis
  This code is for Arduino pro micro
  The table below is showing how the buttons are connected to the board (pin)

  A3, A2, A1, A0, 15 and 14 Are the Row Pins for the Keypad 16 and 10-6 are the Column Pins
  the buttons are connected to each others according to this table

       : A3    A2    A1    A0    15    14
   ....................................................
   16  :  0     1     2     3     4     5           I
   10  :  6     7     8     9    10    11
    9  : 12    13    14    15    16    17
    8  : 18    19    20    21    22    23
    7  : 24    25    26    27    28    29
    6  : 30    31    32    33    34    35

  Pin 0, 1, 2, 3, 4, and 5 plus the GND are used for rotaries
*/

//Including libraries and define variables and give a constant value name

#include <Keypad.h>          //#include is used to include libraries from outside the code.
#include "Joystick.h"


#define enablePullUps      //#define is used to give a name to a constant value.
//or to define a new variable



const byte numOfRotaries = 3;      //creating variables to define number of rotary encoders



//Creating an array with pins that are used
// for more info: 21 = A3, 20 = A2, 19 = A1, 18 = A0 ....
byte colPins[] = {21, 20, 19, 18, 15, 14};
byte rowPins[] = {16, 10, 9, 8, 7, 6};


//define size of array
const int numOfColumns = sizeof(colPins) / sizeof(colPins[0]);
const int numOfRows = sizeof(rowPins) / sizeof(rowPins[0]);


// Creating a 2D array that contains the buttons and also symboling them
byte buttons[numOfRows][numOfColumns] = {
  {0, 1, 2, 3, 4, 5},
  {6, 7, 8, 9, 10, 11},
  {12, 13, 14, 15, 16, 17},
  {18, 19, 20, 21, 22, 23},
  {24, 25, 26, 27, 28, 29},
  {30, 31, 32, 33, 34, 35},
};


//Inislize new keypad class
Keypad ButtonBox = Keypad( makeKeymap(buttons),
                           rowPins, colPins, numOfRows, numOfColumns);


//create and define the joystick
Joystick_ Joystick1(JOYSTICK_DEFAULT_REPORT_ID, JOYSTICK_TYPE_JOYSTICK,
                    32, 0,                  // 36 atsButtons, 3x2 rotary encoder (each rotary is count as 2 buttons
                    //(clockwise (turn right) and counterclockwise (turn left)), 0 hat switch,
                    false, false, false,       // no X axis, Y axis, and/or Z axis
                    false, false, false,      // no Rx, Ry, Rz
                    false, false,             // no rudder and/or throttle
                    false, false, false);     // no accelerator, break, and/or steering
Joystick_ Joystick2(JOYSTICK_DEFAULT_REPORT_ID + 1, JOYSTICK_TYPE_JOYSTICK,
                    10, 0,                  // 36 atsButtons, 3x2 rotary encoder (each rotary is count as 2 buttons
                    //(clockwise (turn right) and counterclockwise (turn left)), 0 hat switch,
                    false, false, false,       // no X axis, Y axis, and/or Z axis
                    false, false, false,      // no Rx, Ry, Rz
                    false, false,             // no rudder and/or throttle
                    false, false, false);

//creating structure (A structure can contain variables, methods, static constructor, ...)
struct rotariesStruct {
  byte pin1;             //define pins and create 3 variabes
  byte pin2;
  int cClockWise;
  int clockWise;
  volatile unsigned char state;
};


rotariesStruct rotariesEncoders[numOfRotaries] {
  //this will create 3 rotaries
  {0, 1, 36, 37, 0}, //pin 0 and 1 are connected to button 36, 37  (rotary)
  {2, 3, 38, 39, 0},
  {4, 5, 40, 41, 0},
};

//rotary table
#define DIR_CCW 0x10     //DIR = Directory            
#define DIR_CW 0x20     //ccw = counter clockwise   CW = clockwise
#define R_START 0x0     //R_start = rotary start

#ifdef HALF_STEP
//use half step
#define R_CCW_BEGIN    0x1
#define R_CW_BEGIN     0x2
#define R_START_M      0x3
#define R_CW_BEGIN_M   0x4
#define R_CCW_BEGIN_M  0x5
const unsigned char rotaryTable[6][4] = {  //[6][4] mean 6 rows and 4 columns
  // R_START (00)
  {R_START_M,            R_CW_BEGIN,     R_CCW_BEGIN,  R_START},
  // R_CCW_BEGIN
  {R_START_M | DIR_CCW, R_START,        R_CCW_BEGIN,  R_START},
  // R_CW_BEGIN
  {R_START_M | DIR_CW,  R_CW_BEGIN,     R_START,      R_START},
  // R_START_M (11)
  {R_START_M,            R_CCW_BEGIN_M,  R_CW_BEGIN_M, R_START},
  // R_CW_BEGIN_M
  {R_START_M,            R_START_M,      R_CW_BEGIN_M, R_START | DIR_CW},
  // R_CCW_BEGIN_M
  {R_START_M,            R_CCW_BEGIN_M,  R_START_M,    R_START | DIR_CCW},
};

#else
//use full step
#define R_CW_FINAL      0x1
#define R_CW_BEGIN      0x2
#define R_CW_NEXT       0x3
#define R_CCW_BEGIN     0x4
#define R_CCW_FINAL     0x5
#define R_CCW_NEXT      0x6

const unsigned char rotaryTable[7][4] = {  //7*4
  // R_START
  {R_START,    R_CW_BEGIN,  R_CCW_BEGIN, R_START},
  // R_CW_FINAL
  {R_CW_NEXT,  R_START,     R_CW_FINAL,  R_START | DIR_CW},
  // R_CW_BEGIN
  {R_CW_NEXT,  R_CW_BEGIN,  R_START,     R_START},
  // R_CW_NEXT
  {R_CW_NEXT,  R_CW_BEGIN,  R_CW_FINAL,  R_START},
  // R_CCW_BEGIN
  {R_CCW_NEXT, R_START,     R_CCW_BEGIN, R_START},
  // R_CCW_FINAL
  {R_CCW_NEXT, R_CCW_FINAL, R_START,     R_START | DIR_CCW},
  // R_CCW_NEXT
  {R_CCW_NEXT, R_CCW_FINAL, R_CCW_BEGIN, R_START},
};
#endif



void setup() {      //setup() is a method called when the program start, and create the variabes and
  //pin mode......
  Joystick1.begin();
  Joystick2.begin();
  initializeRotaryEncoders();
}


void loop() {    //loop() is a method that run for ever

  CheckingButtons();           //this mean that these 2 methods will run for ever
  CheckingRotaryEncoder();

}


//CheckingButtons() function will check the state of the buttons
void CheckingButtons() {
  if (ButtonBox.getKeys()) {
    for (int i = 0; i < LIST_MAX; i++) { //LIST_MAX is a variabe created in keypad.ccp and keypad.h
      if ( ButtonBox.key[i].stateChanged ) {  //this mean if the button has been pressed/hold or released
        switch (ButtonBox.key[i].kstate) {
          case PRESSED:     //if the button is pressed and/or hold
          case HOLD:
            if (i < 32) Joystick1.setButton(ButtonBox.key[i].kchar, 1); //value will be set to 1 = ON in binary
            else Joystick2.setButton(ButtonBox.key[i].kchar - 32, 1); //value will be set to 1 = ON in binary
            break;
          case RELEASED:    //if the button is idle or released
          case IDLE:
            if (i < 32)Joystick1.setButton(ButtonBox.key[i].kchar, 0); //value will set to 0 = OFF in binary
            else Joystick2.setButton(ButtonBox.key[i].kchar - 32, 0);
            break;
        }
      }
    }
  }
}


void initializeRotaryEncoders() {        //create and initial rotary
  for (int i = 0; i < numOfRotaries; i++) {
    pinMode(rotariesEncoders[i].pin1, INPUT);  //set pins to input
    pinMode(rotariesEncoders[i].pin2, INPUT);
#ifdef enablePullUps
    digitalWrite(rotariesEncoders[i].pin1, HIGH);   //set pins value to high
    digitalWrite(rotariesEncoders[i].pin2, HIGH);
#endif
  }
}

//Create and check pin state
unsigned char rotaryProcess(int i) {
  unsigned char pinState = (digitalRead(rotariesEncoders[i].pin2) << 1)
                           | digitalRead(rotariesEncoders[i].pin1);  //get the pins state
  rotariesEncoders[i].state = rotaryTable[rotariesEncoders[i].state     //determine a new state
                                          & 0xf][pinState];
  return (rotariesEncoders[i].state & 0x30);    //return the created event
}

//check all rotaries encoder
void CheckingRotaryEncoder() {
  for (int i = 0; i < numOfRotaries; i++) {
    unsigned char result = rotaryProcess(i);
    if (result == DIR_CCW) {         //if the rotary has been turned to left
      Joystick2.setButton(rotariesEncoders[i].cClockWise-32, 1); //value will be set to 1
      delay(250);    //waiting 250ms = 1/4 second before set the value to 0
      Joystick2.setButton(rotariesEncoders[i].cClockWise-32, 0);
    }
    if (result == DIR_CW) {  //if  the rotary is turned to the right
      Joystick2.setButton(rotariesEncoders[i].clockWise-32, 1);
      delay(250);
      Joystick2.setButton(rotariesEncoders[i].clockWise-32, 0);
    }
  }
}

Thanks. I'll test this code..
and share the results.

Is there any 'pull down' on the 6 input lines?
Also are these buttons or rotary encoders?

None. Should I install a 10k ohm resistor?

I uploaded the code you sent to my Arduino Micro Pro.
But I still get 10 complaints.
The button is pressed 16 times..
image

image

image
No more than 10 lights will come on.

Would it be possible to solve this problem by attaching a resistor as shown here?

no, you need pull-down resistors ( 10k is ok ), connect the common of the resistors to gnd.
You could also use pull-ups ( the microcontroller should have internal selectable pullups ), but in that case you should reverse the diodes ( and the logic?! ).
The rationale is never leave an input floating.

1 Like

Thank you for your reply.
If I use a pull-down resistor, do I need to connect 5v to the input?
Or can I just use a pull-down resistor like in the picture?

while scaning Keypad():

  1. switch all ROW to INPUT_PULLUP,
  2. then set one COL to OUTPUT and LOW
  3. then store states of ROW into array
  4. then this COL back to INPUT_PULLUP
  5. next COL (go to 2)
void Keypad::scanKeys() {
	// Re-intialize the row pins. Allows sharing these pins with other hardware.
	for (byte r=0; r<sizeKpd.rows; r++) {
		pin_mode(rowPins[r],INPUT_PULLUP);
	}

	// bitMap stores ALL the keys that are being pressed.
	for (byte c=0; c<sizeKpd.columns; c++) {
		pin_mode(columnPins[c],OUTPUT);
		pin_write(columnPins[c], LOW);	// Begin column pulse output.
		for (byte r=0; r<sizeKpd.rows; r++) {
			bitWrite(bitMap[r], c, !pin_read(rowPins[r]));  // keypress is active low so invert to high.
		}
		// Set pin to high impedance input. Effectively ends column pulse.
		pin_write(columnPins[c],HIGH);
		pin_mode(columnPins[c],INPUT);
	}
}

this means only PULLUP resistors may be connected only to COL pins.

1 Like

Sorry, a step back ( maybe I misinterpreted the inputs and outputs ).

If the inputs are the pins 6-10 and 16 then you only need pull ups in these inputs ( enable the internal one )

1 Like

try this, only "buttons", 18 should be on each time.

/********** 36 Buttons and 3 Rotary Encoders button box by BaldEagle gaming **********/

/*
  This code is for creating a button box with 36 buttons with 3 rotaries and 0 axis
  This code is for Arduino pro micro
  The table below is showing how the buttons are connected to the board (pin)

  A3, A2, A1, A0, 15 and 14 Are the Row Pins for the Keypad 16 and 10-6 are the Column Pins
  the buttons are connected to each others according to this table

       : A3    A2    A1    A0    15    14
   ....................................................
   16  :  0     1     2     3     4     5           I
   10  :  6     7     8     9    10    11
    9  : 12    13    14    15    16    17
    8  : 18    19    20    21    22    23
    7  : 24    25    26    27    28    29
    6  : 30    31    32    33    34    35

  Pin 0, 1, 2, 3, 4, and 5 plus the GND are used for rotaries
*/

#include <Keypad.h>          //#include is used to include libraries from outside the code.
#include "Joystick.h"

//Creating an array with pins that are used
byte colPins[] = {A3, A2, A1, A0, 15, 14};
byte rowPins[] = {16, 10, 9, 8, 7, 6};

//define size of array
const int numOfColumns = sizeof(colPins) / sizeof(colPins[0]);
const int numOfRows = sizeof(rowPins) / sizeof(rowPins[0]);

// Creating a 2D array that contains the buttons and also symboling them
byte buttons[numOfRows][numOfColumns] = {
  {0, 1, 2, 3, 4, 5},
  {6, 7, 8, 9, 10, 11},
  {12, 13, 14, 15, 16, 17},
  {18, 19, 20, 21, 22, 23},
  {24, 25, 26, 27, 28, 29},
  {30, 31, 32, 33, 34, 35},
};

//Inislize new keypad class
Keypad ButtonBox( makeKeymap(buttons), rowPins, colPins, numOfRows, numOfColumns);

//create and define the joystick
Joystick_ Joystick(0x06, JOYSTICK_TYPE_GAMEPAD,
                    64, 0,                  // 36 atsButtons, 3x2 rotary encoder (each rotary is count as 2 buttons
                    //(clockwise (turn right) and counterclockwise (turn left)), 0 hat switch,
                    false, false, false,       // no X axis, Y axis, and/or Z axis
                    false, false, false,      // no Rx, Ry, Rz
                    false, false,             // no rudder and/or throttle
                    false, false, false);     // no accelerator, break, and/or steering

void setup() {      //setup() is a method called when the program start, and create the variabes and
  Joystick.begin(false);
}

void loop() {    
  if (ButtonBox.getKeys()) {
    for (int i = 0; i < LIST_MAX; i++) { //LIST_MAX is a variabe created in keypad.ccp and keypad.h
      if ( ButtonBox.key[i].stateChanged ) {  //this mean if the button has been pressed/hold or released
        switch (ButtonBox.key[i].kstate) {
          case PRESSED:     //if the button is pressed and/or hold
          case HOLD:
            Joystick.setButton(ButtonBox.key[i].kchar, 1); //value will be set to 1 = ON in binary
            break;
          case RELEASED:    //if the button is idle or released
          case IDLE:
            Joystick.setButton(ButtonBox.key[i].kchar, 0);
            break;
        }
      }
    }
  }
  Joystick.sendState();
  delay(10);
}