3*4 DIY Matrix for Buttons [Solved]

Hi, I am working on a claw machine project and I am trying to get the I/O pins reduced for the Arduino for the future. Basically, I am forming this matrix "keypad" to where it will, like I said, limit the number of I/O pins for the claw machine. Basically, what I am stuck on is how to set this schematic up on a breadboard and how to successfully control it with the Arduino. I have seemed to control it with the Arduino via the two pins on one button, but no luck with diodes to stop ghosting. Any help would be appreciated.


No, what I am wanting to know is how to connect my "keypad" to the Arduino via a breadboard.

The schematic that you posted seems to be labelled with pin numbers and the diodes are not necessary

Have you looked at the Keypad library examples ?

Oh, yeah. I forgot to post the code. I am using the diodes for the future to enable no ghosting for my joystick. What you see (up top) before you is a "simulation circuit." Maybe if I post the claw machine code it will make more sense:

Code for the "simulation circuit:"


/* @file CustomKeypad.pde
|| @version 1.0
|| @author Alexander Brevig
|| @contact alexanderbrevig@gmail.com
||
|| @description
|| | Demonstrates changing the keypad size and key values.
|| #
*/
#include <Keypad.h>

const byte ROWS = 4; //four rows
const byte COLS = 3; //four columns
//define the cymbols on the buttons of the keypads
char hexaKeys[ROWS][COLS] = {
  {'1','2','3'},
  {'4','5','6'},
  {'7','8','9'},
  {'!', '*', '#'},
};
byte rowPins[ROWS] = {2, 3, 4, 5}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {6, 7, 8}; //connect to the column pinouts of the keypad

//initialize an instance of class NewKeypad
Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS); 

void setup(){
  Serial.begin(9600);
  pinMode(6, INPUT_PULLUP);
  pinMode(7, INPUT_PULLUP);
  pinMode(8, INPUT_PULLUP);
}
  
void loop(){
  char customKey = customKeypad.getKey();
  
  if (customKey){
    Serial.println(customKey);
  }
}

Code for the claw machine:

/* (C) UptownKitten453 and Ryan Bates

  Code for the claw machine. Runs through by execution of steps.
  For instance, gameStatic runs first then it goes to runGame, if
  runGame doesn't have the laser on the photoresistor, or LDR,
  than runGameOver.

  Ryan Bates claw machine and code website: http://www.retrobuiltgames.com/the-build-page/arduino-claw-machine/
  More details about our dimensions: https://www.instructables.com/Arduino-Claw-Machine-Version-4/

  Revised: 1/15/2021

*/

#include <ezButton.h>

#include <JC_Button.h>

#include <LiquidCrystal_I2C.h>

#include <Stepper.h>

#include <Wire.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);

// Number of steps per output rotation and can be changed
// based on your stepper motor step angle
const byte stepsPerRevolution = 200;

//define the stepper pins
Stepper Xstepper(stepsPerRevolution, 22, 23, 24, 25);
Stepper Ystepper(stepsPerRevolution, 26, 27, 28, 29);
Stepper Zstepper(stepsPerRevolution, 30, 31, 32, 33);

// When the button is declared, it is already attached to the internal pull-up resistor
ezButton CLS        (34);     // Coin Limit Switch (for quarters

#define CLSL         35      // Coin Limit Switch LED (coin slot LED)

ezButton Forward    (36);   // setup joystick pins
ezButton Backward   (37);
ezButton Left       (38);
ezButton Right      (39);
ezButton CWB        (40);               // Setup the claw button

#define CLWL         41             // Claw Button LED

#define  X           42           // X Limit Switch
#define  X2          43          // Negative (-) X direction (Left)
#define  Y           44         // Y Limit Switch
#define  Y2          45        // -Y direction switch
#define  Z           46       // Z direction switch

#define Demo         47
#define Test         48

//Toggle button function to switch the state of the button (on and off)
ToggleButton
btn1(Demo, false, 50, true, true), //declare (button pin, state it's in at first, debounce time in milliseconds, input pullup resistor, and as low signal equals press)
     btn2(Test, false, 50, true, true);

#define CLW         49               //The actual claw of the claw machine (transistor)
#define Laser       50
#define Green       51             // Light strip color (transistors)
#define Red         52
#define Blue        53
#define LDRPin      A0           // pin where we connected the LDR (photoresistor) and the resistor

const byte LDRLimit = 100;
byte LDRValue = 0;             // result of reading the analog pin

void setup() {
  // put your setup code here, to run once:

  Serial.begin(9600);

  CLS.setDebounceTime(50); // set debounce time to 50 milliseconds
  Forward.setDebounceTime(50);
  Backward.setDebounceTime(50);
  Left.setDebounceTime(50);
  Right.setDebounceTime(50);
  CWB.setDebounceTime(50);

  pinMode(X, INPUT_PULLUP);   // Not using the ez library because of the limit switches with the high state
  pinMode(X2, INPUT_PULLUP);
  pinMode(Y, INPUT_PULLUP);
  pinMode(Y2, INPUT_PULLUP);
  pinMode(Z, INPUT_PULLUP);

  pinMode(CLSL, OUTPUT);
  pinMode(CLWL, OUTPUT);
  pinMode(CLW, OUTPUT);
  pinMode(Laser, OUTPUT);
  pinMode(Green, OUTPUT);
  pinMode(Red, OUTPUT);
  pinMode(Blue, OUTPUT);

  Xstepper.setSpeed(110);
  Ystepper.setSpeed(110);
  Zstepper.setSpeed(120);


  lcd.init();                      // initialize the lcd
  // Print a message to the LCD.
  lcd.backlight();
  // Print on first row
  lcd.print("Presenting...");
  // Wait 2 seconds
  delay(2000);
  lcd.clear();
  lcd.setCursor(0, 1);
  lcd.print("The Arduino Apparatus Lattice");
  for (int PositionCount = 0; PositionCount < 24; PositionCount++)

  {

    lcd.scrollDisplayLeft(); //builtin command to scroll right the text
    delay(500);//delay of 500 msec

  }
  delay(3000);
  lcd.clear();

}

void loop() {
  // put your main code here, to run repeatedly:

  CLS.loop();
  Forward.loop();
  Backward.loop();
  Left.loop();
  Right.loop();
  CWB.loop();

  gameStatic();            //When the machine is not moving

}

void gameStatic() {

  if (CLS.isPressed()) {

    digitalWrite(CLSL, LOW);
    lcd.clear();

    LDRValue = analogRead(LDRPin); // read the value from the LDR

    gameTime();

  }

  else {

    lcd.setCursor(0, 0);
    lcd.print("Please, insert");
    lcd.setCursor(0, 1);
    lcd.print("$0.25.");

  }

}

void gameTime() {

  while (LDRValue <= LDRLimit ) {

    LDRValue = analogRead(LDRPin);   // read the current state and decide what to do based on it

    lcd.setCursor(0, 0);
    lcd.print("Success!");

  }
  lcd.clear();
  gameCompleted();
}

void gameCompleted() {

  lcd.setCursor(0, 0);
  lcd.print("Game complete!");
  delay(3000);
  lcd.clear();
  lcd.setCursor(0, 1);
  lcd.print("Initiating...");
  delay(3000);
  lcd.clear();
  lcd.print("Returning Home!");
  delay(3000);

  while (digitalRead(Z) == HIGH) {

    Zstepper.step(stepsPerRevolution);

  }

  digitalWrite(30, LOW);
  digitalWrite(31, LOW);
  digitalWrite(32, LOW);
  digitalWrite(33, LOW);


}

Yes I have looked at the keypad examples, too.

Have you tried using them with your keypad ?

Why are the diodes there for the joystick to avoid ghosting ?
When the Keypad library is used, the row pins can be shared with other things.

Can someone help me out ?
It seems that as long as a key is being pressed, the others keys in the same row and the same column can not be detected. Is that normal or is it a bug ?

My test sketch:

// Proof that Keypad library does not have ghosting.
// Using: https://github.com/Chris--A/Keypad
//
// It turned out to be proof that when a button is being pressed,
// an other button on the same row or same column can not
// be detected.
//

#include <Keypad.h>

const byte ROWS = 4;
const byte COLS = 3;

// Binary numbers for the keys, this is not common !
char customKeys[ROWS][COLS] = 
{
  { 1, 2, 3},
  { 4, 5, 6},
  { 7, 8, 9},
  { 10, 11, 12}
};

byte rowPins[ROWS] = {2, 3, 4, 5};
byte colPins[COLS] = {6, 7, 8};

Keypad kpd = Keypad( makeKeymap(customKeys), rowPins, colPins, ROWS, COLS); 


void setup()
{
  Serial.begin( 9600);
  Serial.println( "The sketch has started");
}
  
void loop()
{
  // The .getKeys() function scans 
  // all the keys and checks for change.
  if( kpd.getKeys())    
  {
    for( int i=1; i<=12; i++)
    {
      // The .isPressed() function does not check
      // the state, but returns a true if that
      // key was just pressed.
      if( kpd.isPressed(i))
      {
        Serial.print( "KEY");
        Serial.println( i);
      }
    }
  }
}

My test sketch in Wokwi simulation (I used switches instead of buttons to allow to set a switch on).

Hi, @Koepel

That is not a bug, the library is a very simple single key press function.
As it says in the code.

It turned out to be proof that when a button is being pressed,
an other button on the same row or same column can not
be detected.

I have not tried this, but this library has popped up in Google;

It quotes that it can detect "multiple keydown".

Tom.... :smiley: :+1: :coffee: :australia:

Hi,

Have you tried them, what happens with your code in post #1, does it work?
What model Arduino are you using?

Thanks.. Tom... :smiley: :+1: :coffee: :australia:

Thanks, I didn't know that. The other library uses delay() for debouncing :cry:

Try the MultiKey example from the Keypad library. Does that not allow multiple keys?

Yes, I have looked at the examples and have tried some of them.

Yes, I have tried the example sketches and none of them work for me because of hardware issues. I have theorized that the diodes are "getting in my way." If I were to remove the diodes they work just fine, I know because I tested with one of the buttons by themselves. Oh, and that was my fault for not saying which Arduino I have. I have the Mega 2560 rev 3.

So why the need for the diodes ?

Hi,

The Mega has 54 I/O pins, what are they all being used for?

Thanks... Tom... :smiley: :+1: :coffee: :australia:

Same problem: a key in the row and column of a pressed key is not detected.
That scanning code does not test that.

The MultiKey example works fine for me (no diodes in place)

Sample output from pressing 3 separate keys in the same column at intervals, holding them and releasing them at intervals

Key 1 PRESSED.
Key 1 HOLD.
Key 4 PRESSED.
Key 4 HOLD.
Key 7 PRESSED.
Key 7 HOLD.
Key 1 RELEASED.
Key 1 IDLE.
Key 4 RELEASED.
Key 4 IDLE.
Key 7 RELEASED.
Key 7 IDLE.

2 keys in the same row pressed in quick succession, held and released in the reverse order

Key 2 PRESSED.
Key 3 PRESSED.
Key 2 HOLD.
Key 3 HOLD.
Key 3 RELEASED.
Key 3 IDLE.
Key 2 RELEASED.
Key 2 IDLE.

Thank you for testing. I don't know what is going on and I don't have a keyboard to check real hardware against the Wokwi simulation.

Well, it's not that I HAVE to limit the I/O pins, I mean, I am not using ALL the I/O pins anyway. They are not all being used. I would just hope that one day I could use a Uno with the kit I am trying to make for the claw machine. It's probably not possible because my project requires so much I/O pins, but, ya know, I am not so sure. Anyways, I can go back to the way I had it, I just was trying something new.

I count 35 pins in use (12 stepper pins, 11 input pins, 7 output pins, 1 analog pin, 2 Serial pins, 2 I2C/Wire pins). Even if you could move your 11 input pins to a 3x4 keypad (7 pins) you only reduce the pin use by 4. 31 pins is still way too many for an UNO.