Create a "switch" key on a 4x4 keypad

Hello. I'm an Arduino beginner and I need to do a school project involving an arduino, a keypad and an LCD screen. Overall, I want to create a sort of "switch" key on my 4x4 keypad. I need like 7 or 8 extra characters. I investigated and found out it's called a "macro". I'm not too familiarized with macros in basically anything so I'd like to ask for examples in code on how to do this.

In a broader sense what I want is to press a Key and, while I press this key, press another and have a different character show up as a result. How can I achieve this?
Thanks in advance.

Maybe the MultiKey eample that comes with the keypad library can get you on the way; no experience with it.

You can install the keypad library via the menu -> sketch -> include library -> manage libraries.

If you talk about this keypad, then look at its few features listed below:
keypad.png

1. There are 16 different keys. You can put any labels on them whatever you like overriding the indicated labels.

2. If you operate this Keypad using Keypad.h Library, then the Keypad works in 2-key lockout system. In 2-key lockout system, you must release the present 'pressed down key' to get the action of the next pressed down key.

keypad.png

GolamMostafa:
If you talk about this keypad, then look at its few features listed below:
keypad.png

1. There are 16 different keys. You can put any labels on them whatever you like overriding the indicated labels.

2. If you operate this Keypad using Keypad.h Library, then the Keypad works in 2-key lockout system. In 2-key lockout system, you must release the present 'pressed down key' to get the action of the next pressed down key.

And how do I program that 2-key lockout system? This is how I programmed my keypad without the "shift" function

char teclado [filas][columnas]={
{'1','2','3','+'},
{'4','5','6','-'},
{'7','8','9','x'},
{'*','0','=','/'}
}; //variable teclado

If a ‘function’ key is pressed you can set a variable to a defined value, let’s say it is 13.
The next key press is the decoded, based on what function key was previously pressed ‘13’ you do a certain action.

larryd:
If a ‘function’ key is pressed you can set a variable to a defined value, let’s say it is 13.
The next key press is the decoded, based on what function key was previously pressed ‘13’ you do a certain action.

And how I can do that in code using the keypad library?
Thanks for the help.

You 'do not' do this in the keypad library.

The library is used to retrieve key presses from the matrix keypad.

You add this functionality to the sketch you are writing for this project.

We assume you have a sketch you are now working on now.

Please show us your current sketch/code.

Please show us the schematic of your circuit

larryd:
You 'do not' do this in the keypad library.

The library is used to retrieve key presses from the matrix keypad.

You add this functionality to the sketch you are writing for this project.

We assume you have a sketch you are now working on now.

Please show us your current sketch/code.

Please show us the schematic of your circuit

This is the implementation of my keypad. Pretty keypad standard stuff.

char keypad [rows][columns]={
{'1','2','3','+'},
{'4','5','6','-'},
{'7','8','9','x'},
{'*','0','=','/'}
}; //keypad array

byte rowPins[rows]={7,6,5,4}; //row configuration
byte columnPins[columns]={3,2,1,0}; //column configuration

Keypad calcu = Keypad (makeKeymap(keypad),rowPins, columnPins, rows, columns);

...

void loop()
{
  char key = calcu.getKey();
  
  if (key != NO_KEY && (key=='1' || key=='2' || key=='3' || key=='4' || key=='5' || key=='6' || key=='7' || key=='8' || key=='9' || key=='0'))
  {
    if(inicio == false)
      {num1 = num1 + key;
      int numLength = num1.length();
      lcd.setCursor(15-numLength,0);
      lcd.print(num1); 
  }
     else
     {num2 = num2 + key;
      int numLength = num2.length();
      lcd.setCursor(15-numLength,1);
      lcd.print(num2);
      final = true;
  }
}
if (inicio == false && key != NO_KEY && (key == '+' || key == '-' || key == 'x' || key == '/'))

{inicio = true;
 op = key;
 lcd.setCursor(15,0);
 lcd.print (op); 

}

As you can see, is a calculator. But I also need to be able to get the n-root of a number and the n-power of a number, and it also needs to make operations with hexadecimal and base 20 numbers, so I need to be able to input the letters A through J.

I don't have my circuit schematic in a graphic form but the keypad is conected through pins 0 to 7 (the digital ones) I also connected an LCD screen through pins 8 to 13. Everything works flawlessly so far, but I need to implement all that stuff I talked about.

byte columnPins[columns]={3,2,1,0}; //column configuration

Pins 0 and 1 are used for serial communications, not a good idea to use these for other things.

What Arduino are you using?

Always show us the complete sketch.

Edit
num1 = num1 + key;
Did you mean:
num1 = (num1 * 10) + (key - ‘0’);

For “n-root”
Maybe pressing / twice in a row could be defined as take the ‘n-root‘.
For “n-power”
Maybe pressing * twice in a row could be defined as take the ‘n-power‘.

For A-J things get messy, time to get a larger matrix keypad.

Maybe use this idea:

https://forum.arduino.cc/index.php?topic=317625.0

larryd:
byte columnPins[columns]={3,2,1,0}; //column configuration

Pins 0 and 1 are used for serial communications, not a good idea to use these for other things.

What Arduino are you using?

Always show us the complete sketch.

Edit
num1 = num1 + key;
Did you mean:
num1 = (num1 * 10) + (key - ‘0’);

For “n-root”
Maybe pressing / twice in a row could be defined as take the ‘n-root‘.
For “n-power”
Maybe pressing * twice in a row could be defined as take the ‘n-power‘.

For A-J things get messy, time to get a larger matrix keypad.

Maybe use this idea:

New Library for IR Remotes - Exhibition / Gallery - Arduino Forum

Well, the sketch as it is woks great. This is the sketch in its entirety:

#include <Keypad.h>
#include <LiquidCrystal.h> // Librería para el control del LCD


LiquidCrystal lcd(8, 9, 10, 11, 12, 13); // varible LCD y pines
const byte filas = 4; // número de filas '4'
const byte columnas = 4; // número de columnas '4'

char teclado [filas][columnas]={
{'1','2','3','+'},
{'4','5','6','-'},
{'7','8','9','x'},
{'*','0','=','/'}
}; //variable teclado

byte filaPines[filas]={7,6,5,4}; //configuración de filas
byte columnaPines[columnas]={3,2,1,0}; // configuración de columnas

Keypad calcu = Keypad (makeKeymap(teclado),filaPines, columnaPines, filas, columnas);

boolean inicio = false; 
boolean final = false; // variables de control

String num1, num2;
int ans;
char op;

void setup()
{
  lcd.begin(16,2);
  lcd.setCursor(0,0);
  lcd.print("Hola Mundo"); //Prendido de pantalla
  delay (2500);
  lcd.clear();
}

void loop(){
  char key = calcu.getKey();
  
  if (key != NO_KEY && (key=='1' || key=='2' || key=='3' || key=='4' || key=='5' || key=='6' || key=='7' || key=='8' || key=='9' || key=='0')){
    if(inicio == false)
      {num1 = num1 + key;
      int numLength = num1.length();
      lcd.setCursor(15-numLength,0);
      lcd.print(num1); 
  }
     else {
      num2 = num2 + key;
      int numLength = num2.length();
      lcd.setCursor(15-numLength,1);
      lcd.print(num2);
      final = true;
  }
}
if (inicio == false && key != NO_KEY && (key == '+' || key == '-' || key == 'x' || key == '/'))

{inicio = true;
 op = key;
 lcd.setCursor(15,0);
 lcd.print (op); 

}
if (final == true && key !=NO_KEY && key == '=')
{
    if (op == '+')
    {ans= num1.toInt() + num2.toInt();}
    if (op == '-')
    {ans= num1.toInt() - num2.toInt();}
    if (op == 'x')
    {ans= num1.toInt() * num2.toInt();}
    if (op == '/')
    {ans= num1.toInt() / num2.toInt();}
    
    lcd.clear();
    lcd.setCursor(15,0);
    lcd.autoscroll();
    lcd.print(ans);
    lcd.noAutoscroll();    
}
if(key !=NO_KEY && key == '*')
{
  lcd.clear();
  inicio = false;
  final = false;
  num1 = "";
  num2 = "";
  ans = 0;
  op = ' ';
}
}

Mmm, buying the IR remote you recommended is probably out of the question. I haven't seen them for sale here, and i'm currently residing in mexico, and this project is due in two weeks.
My professor told us that it was possible to make this shift key stuff i'm talking about, and the things you said about multi-key presses seemed like what i'm looking for. Isn't really a way to program a 4x4 keypad to hold more characters using this multi-key pressing functions?

Make your keys have multiple functions by setting a variable OR adding a switch to your circuit.
example:
0 thru 9 normally give you 0 - 9
Then pressing your separate switch (call it SHIFT) 0 thru 9 now give you A - J

Use an array, offset into the array by the amount represent by the matrix switch.
0 gives array index 0,0 = 0
1 gives array index 0,1 = 1
When your SHIFT switch is pressed, you use a different index.
0 gives array index 1,0 = 10 ten
1 gives array index 1,1 = 11 eleven
int myKeys[2][10] =
{
{ 0,1,2,3,4,5,6,7,8,9}, // new switch not pressed
{ 10,11,12,13,14,15,16,17,18,19 } //new switch pressed as needed A,B,C,D . . . J Base 20
};

OR
Maybe just add a constant to the key pressed ex. 10

larryd:
Make your keys have multiple functions by setting a variable OR adding a switch to your circuit.
example:
0 thru 9 normally give you 0 - 9
Then pressing your separate switch (call it SHIFT) 0 thru 9 now give you A - J

Use an array, offset into the array by the amount represent by the matrix switch.
0 gives array index 0,0 = 0
1 gives array index 0,1 = 1
When your SHIFT switch is pressed, you use a different index.
0 gives array index 1,0 = 10 ten
1 gives array index 1,1 = 11 eleven
int myKeys[2][10] =
{
{ 0,1,2,3,4,5,6,7,8,9}, // new switch not pressed
{ 10,11,12,13,14,15,16,17,18,19 } //new switch pressed as needed A,B,C,D . . . J Base 20
};

OR
Maybe just add a constant to the key pressed ex. 10

Hi, thanks for answering.
That seems like a solution, but i'm not really sure where the output of the OR gate should go.
This is more or less the circuit I made:

I should add, just like you said, a switch and an or gate, the first input of the OR gate should be my switch and the second one should be GND no? So if I don't turn my switch on the OR gate shall always be 0.

Looks like you have A0 thru A5 free. Same as D14 thru D19.

Use A0 for your Shift switch.

You can read A0 as follows:
myShiftSwitchState = digitalRead(14);

Suggest you move D1 and D0 to A1 and A2.

Gotcha. I will try it out.
So once I read my A0, how can I proceed to switch my keypad to another one in code? I'm imagining something like this:

if(myShiftSwitchState){
     //Initialization of my second keypad, with the extra characters
}else{
    //Initialization of my first keypad, with the normal characters
}

An important thing to consider:
1-. If the user turns the switch off, then the keypad must return to its original state, so, I guess I have to introduce everything in a loop? How can I do that?

Another way of doing it is, well, reading your first post where you recommended me the use of an OR gate, how can I apply the use of a different index to switch my keypads?

The Shift function can be handled in one of two ways.

  • You can write the sketch so the keypad is decoded as A-J as long as the Shift button is pressed.
    When the switch is released, the keypad is decoded as 0-9.

  • You can write the sketch so your Shift switch toggles a variable to true/false.
    Pressing the switch the first time the variable is set true, pressing the switch the second time you reset the variable to false.
    When true, the keypad is decoded one way, when false it is decoded another way.

Since you have some extra pins, why not add a LED to turn on when you are in Shift mode.

Hi, I tried using an OR gate and a switch to define my shift state, but now the arduino doesn't even turn on. The only way of making it turn on is to disconnect my gate, switch and LED or to upload the program while everything is connected and now the LCD prints odd random characters after my "Hello World" (the message it prints when it turns on).
I read my pin A0 (in analog in) as digitalRead(14) like you told me. My conditional sentence is written as it follows:

if(shiftSwitch = HIGH){
 //Etc.
   }

This what I do inside my if conditional:

if (key != NO_KEY && (key=='1' || key=='2' || key=='3' || key=='4' || key=='5' || key=='6' || key=='7' || key=='8' || key=='9' || key=='0'))
  { if(shiftSwitch = HIGH){
    if(inicio == false)
      {switch(key){
       /*Cambia el valor introducido de key por su
        equivalente en el modo shift*/
        case '1':
        key = 'A';
        break;
        case '2':
        key = 'B';
        break;
        case '3':
        key = 'C';
        break;
        case '4':
        key = 'D';
        break;
        case '5':
        key = 'E';
        break;
        case '6':
        key = 'F';
        break;
        case '7':
        key = 'G';
        break;
        case '8':
        key = 'H';
        break;
        case '9':
        key = 'I';
        break;
        case '0':
        key = 'J';
        break;
       }
      }
      num1 = num1 + key;
      int numLength = num1.length();
      lcd.setCursor(15-numLength,0);
      lcd.print(num1); 
  }
     else
     {switch(key){
       /*Cambia el valor introducido de key por su
        equivalente en el modo shift*/
        case '1':
        key = 'A';
        break;
        case '2':
        key = 'B';
        break;
        case '3':
        key = 'C';
        break;
        case '4':
        key = 'D';
        break;
        case '5':
        key = 'E';
        break;
        case '6':
        key = 'F';
        break;
        case '7':
        key = 'G';
        break;
        case '8':
        key = 'H';
        break;
        case '9':
        key = 'I';
        break;
        case '0':
        key = 'J';
        break;
       }
      num2 = num2 + key;
      int numLength = num2.length();
      lcd.setCursor(15-numLength,1);
      lcd.print(num2);
      final = true;
  }

Yeah, this code can be improved but I only wanted to see if it could work.
What did go wrong and what can I try to make it work?

if(shiftSwitch = HIGH){

The above is wrong, = is not the same as ==.

Use if(shiftSwitch == HIGH){

Read this:

Edit
“I tried using an OR gate ”
Always show us your current schematic so we can see what you have changed.

Posting images:
https://forum.arduino.cc/index.php?topic=519037.0

Use CTRL T to format your code.
Attach your ‘complete’ sketch between code tags, use the </> icon in the posting menu.
[code]Paste your sketch here[/code]

BTW
You have:
if (key != NO_KEY && (key=='1' || key=='2' || key=='3' || key=='4' || key=='5' || key=='6' || key=='7' || key=='8' || key=='9' || key=='0'))

All you need is if (key != NO_KEY) since your ‘switch/case’, lower down, will figure out the exact key pressed.

Thanks for your help Larry, I finally managed to get my shift key running as I intended. I'll post the solution here so anyone wanting to use a shift key in a project using keypad can use this method:

My project circuitry is arranged as the following schematic:

Just add a Switch, and an OR gate to yours as you normally would. One of the inputs of the OR gate must be the switch output and the other must be wired to GND. The output of the OR gate must be wired to any unused port in the arduino. In this case I used A0 just like Larry recommended me.

Having all the hardware out of the way, in the code we'll do the following:

Declare two keypads, one being the keypad in shift mode and the other the regular keypad:

/*Number of rows and columns of
   our keypad*/
const byte rows = 4; 
const byte columns = 4; 
const byte rows2 = 4;
const byte columns2 = 4; 

char keypad [rows][columns]={
{'1','2','3','+'},
{'4','5','6','-'},
{'7','8','9','x'},
{'*','0','=','/'}
}; //Our regular keypad

char keypadShift [rows2][columns2]={
{'A','B','C','+'},
{'D','E','F','-'},
{'G','H','I','^'},
{'*','J','=','|'}
}; //Our keypad in shift mode

byte rowPins[filas]={0,1,2,3}; //row configuration in regular keypad mode
byte columnPines[columnas]={4,5,6,7}; // column configuration in regular keypad mode
byte rowPins2[filas2]={0,1,2,3}; // row configuration in shift mode
byte columnPins2[columnas2]={4,5,6,7}; // column configuration in shift mode

Keypad calcu = Keypad (makeKeymap(keypad),filaPines, columnaPines, filas, columnas);
Keypad calcuShift = Keypad (makeKeymap(keypadShift),rowPins2, columnPins2, rows2, columns2);

Having done that, in our loop function we'll insert an if statement that'll check if our switch is on or off, and, according to that, will use the corresponding keypad:

char key;
  if(digitalRead(A0) == HIGH){ //What goes inside digitalRead is the pin we're using.
    key = calcuShift.getKey();
  }else{
    key = calcu.getKey();
   }

At least that's how I've done it in my sketch. It's probably going to depend on the way your sketch handles the keypad.

Well, thanks for the help Larry.

1 Like