Push button on a numeric keypad

Would like to make something to physically push buttons on a numeric keypad. Guess it could be mounted right on top of the flat keypad.

At least several different buttons on the keypad, so something like entering the code for a wireless garage door opener keypad.

Have read thru some posts of pneumatic solenoids, servos, actuators.
My thoughts are to go with pneumatic solenoids.
Cost isn't a concern, better to have a consistent & stable solution.

Considered about a finger bot, but the number of buttons and close proximity of the buttons probably won't work...as well as how often the buttons need be pressed and combination of buttons..

Would like to be able to control all the buttons using a script or a programming language...like python or something similar. I can run the script, when I want a specific sequence of buttons pressed.

Thoughts and suggestions are welcomed.

What are you actually trying to do?

There are often a lot smarter and more reliable ways to achieve this than mimicking a finger press.

ADDED:
Consider the keypad is likely a 4x3 matrix, so you could use 7 i/o pins to drive contacts (a matrix of ‘cross-points) to activate any key in any order. Look at how keypads are dcanned for an idea…

1 Like
  • If you're working with an existing keypad, integrating this feature could be quite cumbersome.
    OR
  • For a new design, consider using an IR keypad for manual input, while allowing the controller to send IR remote control commands for automated functions.

Are you able to open/modify the keypad in any way?

Mimicking finger presses is the preferred approach.
Can't open/modify/splice or connect electrically behind the buttons.

I picture it as a bunch of 'piston' hovering over a bunch of buttons in a 4x3 matrix...and each 'piston' will be able to push only 1 button & quickly retract itself.

I used 'keypad', as analogy of what each 'piston' will press...because the buttons are so close to each other.
It will be similar to me entering a garage code into a garage numerical keypad. And I want to able to re-arrange the position of each 'piston' to wherever a button may lie.

I would guess that each 'piston' would have it's own i/o pins to control it, as well as how hard to press the button.

If the fingerbot available on the market were much smaller and versatile, I would get a dozen of them and line them up to a 4x3 matrix. And use a script to control the sequence, of which button to press.

  • What exactly does your black box do once all the numbers are entered on the keypad ?

  • Why are you wanting to do this ? :thinking:

This project will transform into a more generic tool, that I can mount on top of any flat surface device that has buttons.

I want to save my fingers from the anguish, of navigating through the menu-system on an LCD display...just to get to where I want to be. And it would be used many times, not just a set it once & leave it. The other tidbit, is that it doesn't have ports for input...so no serial ports or ethernet port...or bluetooth for communication....so gotta mimic the key presses.

Which says to me your device will need a 'personality' change for each keypad you encounter.  Which means it will likely need a 'teach' mode to be adaptable to many keypads.  Have you thought about this?

I'm going to assume this is a testing rig, not a nefarious password brute-force entry tool, though it could serve for either.

There is no universal spacing for buttons on keypads, nor is any arrangement dominant. Let's say you arrange to place several solenoids above a keypad; while solving the problem for that particular keypad, the next one will need a different spacing, both X and Y. Impractical, I suspect.

How fast do you have to achieve the button presses? I'm thinking a single solenoid/actuator on an XY gantry might be a better approach, but speed may be a factor, you haven't said. For every unique keypad, all you need are the coordinates of every button to be pressed. However, you will require movement in 2 axes between each keypress. Knowing keypad routines, in many but not all cases you may need to keep the button/pad depressed for some finite period of time before moving on to the next press, as well.

Alternatively, perhaps a component pick-and-place robot could be repurposed for your task.

Sounds interesting! Keep us informed as to your progress, please.

To keep it simple, I think I'd go the route of manual repositioning of the 'pistons' above each key, if a different keypad is ever used. 1 'piston' over each button

Want to mimic an adult pressing the butotons, but not grandma speed. Just a normal button press.
Not trying to find out the durability of a button. Definitely don't want to break the button.

pretty amazing what you can do with a 12vdc push/pull..

fun stuff.. ~q

Seems like you already know what to do. I see nothing wrong with the idea.

Very inspiring, thank you for the link!
My idea is not a grand yet :star_struck:

Might be able to use one of the cheap arduino robot arms for this.

It, most definitely, is.

While in "timeout" I made a thing for you... with "re-positioning" controlled at the start...

// https://forum.arduino.cc/t/push-button-on-a-numeric-keypad/1409855/

/*
  Most DIY XY-plotter designs seem to use stepper motors with pulleys and belts, direct drive stepper motors,
  or servos with hinged arms, to move the pen around.  I opted not to suggest how to construct this movement,
  but the "plunger" should be at the intersection of the servo arm extensions.

  This sketch is untested mechanically other than a mock-up "on the bench" using a Nano-328P, a pushbutton,
  a relay, two servos  and two potentiometers.  It starts with asking for the number of keys on the keypad
  and is hard-coded for a maximum 3x4 (12 keys).  Then it waits for a pushbutton to store the two servo angles
  adjusted with potentiometers to align servo arms to intersect over each key.

  Improvements:
  - replace hard-coded combination example with random combination generator
  - OLED or LCD display for output
  - pause or pushbutton between storing the last angle pair entry and start of safecracking
  - sequential combination for brute force, from 0000 to 9999 (or FFFF for a hexadecimal keypad)
  - expand size of (key/angle) array to use with a full keyboard (105 keys) for passwords
  - more plungers for SHIFT, FN, CTRL
*/

#include <Servo.h>
Servo lsrv; // left servo
Servo rsrv; // right servo

byte lsrvpin = 6, rsrvpin = 5, buttonpin = 4, plungerpin = A2, lpot = A0, rpot = A1;
int lval, lvalx, lsrvang,  rval, rvalx, rsrvang; // potentiometer and servo values
int lhome = 65, rhome = 115; // home angles for servos point below bottom row of keys
byte keypadsize, keycount, lkeyang[16], rkeyang[16]; // max 4x4 keypad, store servo angles
bool allanglescollected = 0; // signal end of key/angle collection

void setup() {
  Serial.begin(115200);
  configureservos();
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(plungerpin, OUTPUT);
  pinMode(buttonpin, INPUT_PULLUP);

  getkeypadsize(); // get number of keys to map
  while (allanglescollected == 0) { // collect keypad servo angles
    adjustservoextensions(); // read potentiometers and move servo arms
    readbutton();
    if (keycount == keypadsize) {
      allanglescollected = 1;
    }
  }
  Serial.print("\n>> All ");
  Serial.print(keypadsize);
  Serial.println(" keys are mapped to servo angle pairs.");
  Serial.println(">> Press button to start safecracking. (Relay activates plunger)");
}

void loop() {
  while (digitalRead(buttonpin)) {};
  crackthiscombo();
  Serial.println(" Press button to re-start safecracking.");
}

void getkeypadsize() {
  Serial.print(">> Enter number of keys: ");
  while (Serial.available() == 0) {} // empty braces
  keypadsize = Serial.parseInt();
  Serial.println(keypadsize);
  Serial.println(">> Start with '0' key.");
  Serial.println(">> Adjust (L)pot/(R)pot so (L)servo/(R)servo arm extensions intersect.");
  Serial.println(">> Press button to store servo angle pair.");
}

void crackthiscombo() { // demonstrate pre-programmed combination
  byte comboarray[] = {8, 6, 7, 5, 3, 0, 9};
  byte comboarraysize = sizeof(comboarray) / sizeof(comboarray[0]);
  for (byte index = 0; index < comboarraysize; index++) {
    moveplungertokey(comboarray[index]);
    activateplunger();
  }
}

void moveplungertokey(byte key) {
  Serial.print(key);
  lsrv.write(lkeyang[key]);
  rsrv.write(rkeyang[key]);
}

void activateplunger() {
  delay(333); // 1/3 of a second between key presses seems human
  digitalWrite(plungerpin, HIGH); // actuate plunger
  delay(333); // 1/3 of a second press duration seems human
  digitalWrite(plungerpin, LOW); // raise plunger
}

void readbutton() {
  if (digitalRead(buttonpin) == 0) { // button pin is LOW when PRESSED
    delay(150); // my lazy button debounce
    storeservoangles();
    keycount++;
  }
}

void storeservoangles() {
  Serial.print("(");
  Serial.print(keycount);
  Serial.print(":");
  lkeyang[keycount] = lsrvang; // left servo angle
  Serial.print(lkeyang[keycount]);
  Serial.print(",");
  rkeyang[keycount] = rsrvang; // right servo angle
  Serial.print(rkeyang[keycount]);
  Serial.print(")");
}

void configureservos() {
  lsrv.write(lhome); // write servo angle before attaching servo
  rsrv.write(rhome); // write servo angle before attaching servo
  lsrv.attach(lsrvpin);
  rsrv.attach(rsrvpin);
}

void adjustservoextensions() {
  lval = analogRead(lpot);
  rval = analogRead(rpot);
  if ((lval != lvalx) || (rval != rvalx)) {
    lvalx = lval;
    rvalx = rval;
    lsrvang = map(lval, 0, 1023, 0, lhome);
    rsrvang = map(rval, 0, 1023, rhome, 180);
    lsrv.write(lsrvang);
    rsrv.write(rsrvang);
  }
  delay(15); // delay for servos to arrive
}
Click for diagram.json for the Wokwi nerds...

{
  "version": 1,
  "author": "suspended-again",
  "editor": "wokwi",
  "parts": [
    { "type": "wokwi-arduino-nano", "id": "nano", "top": 4.8, "left": -0.5, "attrs": {} },
    {
      "type": "wokwi-servo",
      "id": "servo1",
      "top": -117.2,
      "left": 115.2,
      "rotate": 180,
      "attrs": {}
    },
    { "type": "wokwi-servo", "id": "servo2", "top": -117.2, "left": -134.4, "attrs": {} },
    {
      "type": "wokwi-potentiometer",
      "id": "pot1",
      "top": -1.3,
      "left": 172.6,
      "attrs": { "value": "0" }
    },
    {
      "type": "wokwi-potentiometer",
      "id": "pot2",
      "top": -1.3,
      "left": -77,
      "attrs": { "value": "1023" }
    },
    { "type": "wokwi-vcc", "id": "vcc1", "top": -114.44, "left": -163.2, "attrs": {} },
    { "type": "wokwi-gnd", "id": "gnd1", "top": 144, "left": -154.2, "attrs": {} },
    { "type": "wokwi-text", "id": "text1", "top": -259.2, "left": 9.6, "attrs": { "text": "4" } },
    { "type": "wokwi-text", "id": "text2", "top": -259.2, "left": 67.2, "attrs": { "text": "5" } },
    {
      "type": "wokwi-text",
      "id": "text3",
      "top": -259.2,
      "left": 124.8,
      "attrs": { "text": "6" }
    },
    { "type": "wokwi-text", "id": "text4", "top": -211.2, "left": 9.6, "attrs": { "text": "7" } },
    { "type": "wokwi-text", "id": "text5", "top": -211.2, "left": 67.2, "attrs": { "text": "8" } },
    {
      "type": "wokwi-text",
      "id": "text6",
      "top": -211.2,
      "left": 124.8,
      "attrs": { "text": "9" }
    },
    { "type": "wokwi-text", "id": "text7", "top": -307.2, "left": 9.6, "attrs": { "text": "1" } },
    { "type": "wokwi-text", "id": "text8", "top": -307.2, "left": 67.2, "attrs": { "text": "2" } },
    {
      "type": "wokwi-text",
      "id": "text9",
      "top": -307.2,
      "left": 124.8,
      "attrs": { "text": "3" }
    },
    { "type": "wokwi-text", "id": "text10", "top": -163.2, "left": 9.6, "attrs": { "text": "*" } },
    {
      "type": "wokwi-text",
      "id": "text11",
      "top": -163.2,
      "left": 67.2,
      "attrs": { "text": "0" }
    },
    {
      "type": "wokwi-text",
      "id": "text12",
      "top": -163.2,
      "left": 124.8,
      "attrs": { "text": "#" }
    },
    {
      "type": "wokwi-pushbutton",
      "id": "btn1",
      "top": -105.7,
      "left": 41.9,
      "rotate": 90,
      "attrs": { "color": "blue", "xray": "1" }
    },
    { "type": "wokwi-relay-module", "id": "relay1", "top": 105.8, "left": 124.8, "attrs": {} },
    {
      "type": "wokwi-text",
      "id": "text13",
      "top": 163.2,
      "left": 144,
      "attrs": { "text": "PLUNGER" }
    },
    {
      "type": "wokwi-text",
      "id": "text14",
      "top": -345.6,
      "left": -67.2,
      "attrs": { "text": "Keypad of any SIZE, SHAPE and LOCATION." }
    }
  ],
  "connections": [
    [ "pot1:GND", "nano:GND.1", "black", [ "v9.6", "h-28.8" ] ],
    [ "pot2:GND", "nano:GND.1", "black", [ "v9.6", "h182.4" ] ],
    [ "pot2:SIG", "nano:A0", "green", [ "v19.2", "h86" ] ],
    [ "pot1:SIG", "nano:A1", "green", [ "v19.2", "h-144.4" ] ],
    [ "gnd1:GND", "pot2:GND", "black", [ "v-67.2", "h96" ] ],
    [ "vcc1:VCC", "servo2:V+", "red", [ "v0" ] ],
    [ "vcc1:VCC", "servo1:V+", "red", [ "v67.2", "h451.2", "v-38.4", "h-12.4" ] ],
    [ "gnd1:GND", "servo2:GND", "black", [ "v0" ] ],
    [ "gnd1:GND", "servo1:GND", "black", [ "v-172.8", "h429.2" ] ],
    [ "nano:5", "servo1:PWM", "green", [ "v-19.2", "h220.8", "v-56.6" ] ],
    [ "nano:6", "servo2:PWM", "green", [ "v-19.2", "h-240", "v-38.4" ] ],
    [ "nano:4", "btn1:1.r", "blue", [ "v-48", "h-9.6" ] ],
    [ "gnd1:GND", "btn1:2.r", "black", [ "v-172.8", "h211.4" ] ],
    [ "vcc1:VCC", "relay1:VCC", "red", [ "v0" ] ],
    [ "gnd1:GND", "relay1:GND", "black", [ "v0" ] ],
    [ "relay1:IN", "nano:A2", "green", [ "h0" ] ],
    [ "pot2:VCC", "nano:5V", "red", [ "v28.8", "h18.4" ] ],
    [ "pot1:VCC", "nano:5V", "red", [ "v28.8", "h-96.8" ] ]
  ],
  "dependencies": {}
}

Back in the 1990’s I saw such and operation at the Unisys plant in Plymouth Michigan, They were testing and ATM machine using a robot. It would insert a card, push the keypad buttons, remove the fake cash and the receipt. Wait a bit and repeat. Big pile of paper on the floor showed it was doing the job.

Seeing automation in action is exhilarating. From farming machinery videos to warehouse sorting machines. Amazing ideas in action.

I originally wanted this idea just to save my fingers. Whoever designed this gadget, didn't leave an easy way in for communication with it or to help test it...No telnet, no SSH, no serial port, no web interface, etc. Just finger pushing to get it to do some action.

That idea of reposition the plunger is interesting too.

I am still not understanding why someone would want something to push the keypad buttons for them.

Don’t get me wrong, if you want to make a robot project that walks up to the keypad and pushes the buttons, I do not care. I hope it works.

But do have debilitating finger pain? I am not trying to understand the project itself, but rather the “WHY?” behind it.

The design is from XY plotters without intricate articulation. The exact design is your oyster.

It certainly does. The sketch is modular. The physical size can be scaled from spread-out buttons to any size keyboard for password cracking. The crackthiscombo() function needs only a stream of characters, the design of which is your choice (not my failure to do it for you). I picked a static array that @DeltaG (pbuh @system) would like. Read the in-code comments for proposed improvements.

I was actually referring to the keypad gadget that I have, which doesn't have many way to communicate with it.
I do like your idea though :slight_smile:

As for why would someone want something to push the keypad buttons for them...I'm lazy like that :slight_smile:
If something can do MY work for me, and opens more time for other things that I need to do...I'm for it.
Imagine pushing the same buttons EVERY TIME there is a new firmware release for a product...so it needs to be tested...or better yet a daily/weekly regression test because software/code changes as features change in functionality.