Arduino Keypad Menu design

Hello friends, I need your help in Keypad Menu design...

Objective: To design menu with submenus using 4x4 matrix keypad

Apparatus: Mega 2560, 4x4 Keypad and a LCD

#include <Password.h>
#include <Keypad.h>
#include "U8glib.h"
U8GLIB_ST7920_128X64_4X u8g(43,41,39);

Password password = Password( "1234" );
Password opt1 = Password( "1" );
Password opt2 = Password( "2" );
Password opt3 = Password( "3" );


const byte ROWS = 4; // Four rows
const byte COLS = 4; //  columns
// Define the Keymap
char keys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};

byte rowPins[ROWS] = {37,35,33,31};
byte colPins[COLS] = {29,27,25,23};

// Create the Keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

void setup(){
keypad.addEventListener(auth_pwd); //add an event listener for this keypad
authenticate();
}

void authenticate(){
    u8g.setFont(u8g_font_tpss);
    u8g.setColorIndex(1); 
    u8g.firstPage ();  
        do{
    u8g.setPrintPos(16, 25); 
    u8g.print("Please enter the");
    u8g.setPrintPos(37, 46); 
    u8g.print("PASSWORD");
          }while( u8g.nextPage () );
}



void loop(){
  keypad.getKey();
}

//take care of some special events
void auth_pwd(KeypadEvent aKey){
  switch (keypad.getState()){
    case PRESSED:
        u8g.setFont(u8g_font_unifont);
        u8g.setPrintPos(0, 20);
	switch (aKey){
	  case '*': checkPassword(); break;
	  case '#': password.reset(); break;
	  default: password.append(aKey);
     }
  }
}

void option1(KeypadEvent bKey){
  switch (keypad.getState()){
    case PRESSED:
        u8g.setFont(u8g_font_helvR08);
        u8g.setPrintPos(5, 20);
        u8g.firstPage();  
        do {
            u8g.print("You choosed option: ");
            u8g.print(bKey);
        } while( u8g.nextPage() );
	switch (bKey){
	  case '*': choose_menu_option1(); break;
	  case '#': opt1.reset(); break;
	  default: opt1.append(bKey);
     }
  }
}

void option2(KeypadEvent cKey){
  switch (keypad.getState()){
    case PRESSED:
        u8g.firstPage();  
        do {
        u8g.setFont(u8g_font_helvR08);
        u8g.setPrintPos(0, 20);
        u8g.print("You choosed option: ");
        u8g.print(cKey);
        } while( u8g.nextPage() );
	switch (cKey){
	  case '*': choose_menu_option2(); break;
	  case '#': opt2.reset(); break;
	  default: opt2.append(cKey);
     }
  }
}

void option3(KeypadEvent dKey){
  switch (keypad.getState()){
    case PRESSED:
        u8g.firstPage();  
        do {
        u8g.setFont(u8g_font_helvR08);
        u8g.setPrintPos(0, 20);
        u8g.print("You choosed option: ");
        u8g.print(dKey);
        } while( u8g.nextPage() );
	switch (dKey){
	  case '*': choose_menu_option3(); break;
	  case '#': opt3.reset(); break;
	  default: opt3.append(dKey);
     }
  }
}

void checkPassword(){
  if (password.evaluate()){
    u8g.setFont(u8g_font_unifont);
        u8g.setPrintPos(0, 20);
     u8g.firstPage();  
  do {
    u8g.setFont(u8g_font_fub17);
    u8g.setColorIndex(1);
    u8g.drawBox(0,0,128,64);  
    u8g.setColorIndex(0);   
    u8g.setPrintPos(16, 25); 
    u8g.print("Menu design");
    } while( u8g.nextPage() );
    delay(1000);
    u8g.firstPage();  
  do {
    u8g.setFont(u8g_font_helvR08);
    u8g.setColorIndex(1);
    u8g.setPrintPos(2, 5); 
    u8g.print("Choose the options below");
    u8g.setFont(u8g_font_unifont);
    u8g.setPrintPos(16, 15); 
    u8g.print(" 1. option1");
    u8g.setPrintPos(16, 30); 
    u8g.print(" 2. option2");
    u8g.setPrintPos(16, 45); 
    u8g.print(" 3. option3");
  } while( u8g.nextPage() );
keypad.addEventListener(option1); //add an event listener for this keypad
keypad.addEventListener(option2); //add an event listener for this keypad
keypad.addEventListener(option3); //add an event listener for this keypad
  }else{
     u8g.firstPage();  
  do {
    u8g.setFont(u8g_font_unifont);
    u8g.setPrintPos(0, 20);
    u8g.print("Wrong option!");
  } while( u8g.nextPage() );
    //add code to run if it did not work
  }
}

void choose_menu_option1(){
  
  if (opt1.evaluate()){
    u8g.firstPage();  
  do {
    u8g.setFont(u8g_font_helvR08);
    u8g.setColorIndex(1);
    u8g.setPrintPos(2, 15); 
    u8g.print("This is option 1");
  } while( u8g.nextPage() );
  }
}

void choose_menu_option2(){
    if (opt2.evaluate()){
    u8g.firstPage();  
  do {
    u8g.setFont(u8g_font_helvR08);
    u8g.setColorIndex(1);
    u8g.setPrintPos(2, 15); 
    u8g.print("This is option 2");
  } while( u8g.nextPage() );
  }
}

void choose_menu_option3(){
    if (opt3.evaluate()){
    u8g.firstPage();  
  do {
    u8g.setFont(u8g_font_helvR08);
    u8g.setColorIndex(1);
    u8g.setPrintPos(2, 15); 
    u8g.print("This is option 3");
  } while( u8g.nextPage() );
  }
}

In the sample code i have attached , the first password validation goes fine. It asks for a password, i entered '1234' and it went inside. After that When i entered 1,2,3 for options, nothing happens. Only the characters i entered appear. Not going inside the option! What am i doing wrong here???
I have also attached the setup and the output images for your reference.

Can somebody give me a menu design program using Keypad library with multiple choice selection???

Please help! My entire project is stuck in here! :frowning: :frowning: :frowning:

keypad.addEventListener(option1); //add an event listener for this keypad
keypad.addEventListener(option2); //add an event listener for this keypad
keypad.addEventListener(option3); //add an event listener for this keypad

You can have ONE event listener active at a time.

You should have ONE function that deals with key input. What that function does depends on a state variable, NOT on separate functions.

PaulS:

keypad.addEventListener(option1); //add an event listener for this keypad

keypad.addEventListener(option2); //add an event listener for this keypad
keypad.addEventListener(option3); //add an event listener for this keypad



You can have ONE event listener active at a time.

You should have ONE function that deals with key input. What that function does depends on a state variable, NOT on separate functions.

So, how should i use menu options with Keypad??? Example program will greatly help me!!!

So, how should i use menu options with Keypad?

In the callback, you collect data, as you do today. When the "use this data" key is pressed, how you use the data depends on the state of the program. You need some understanding of the states of the program (waiting for authorization password, waiting for menu selection, etc.) and a way to keep track of what state you are in.

Yes, i understand... But i don't have a knowledge on how to code for it... Please help me with an example code!!!

what is the general way of designing a menu with keypad??? How to define multiple keypad events? Is there any library for it?

irfanece:
what is the general way of designing a menu with keypad??? How to define multiple keypad events? Is there any library for it?

Do you remember the times when mobile phone were not smart and had no touch screen?
When mobile phones simply had a 10-digit keypad built from mechanical buttons?
Was there a "general way of designing a menu with keypad"?

Or was there a Motorola way designing a menu, a Nokia way designing a menu, an Alcatel way designing a menu, a Sony way designing a menu, and so on and so on? Even while nearly all mobile phones had similar functions like "dial a telephone number", "write an SMS" and "do some configuration settings", the menu systems of different mobile phones were different.

So I think there is no "general way" and you have either to mimic some existing menu, or invent your own.

When looking at your 4x4 keypad and what you have, then I might think about that menu logic:
A, B, C, D ==> activate different main menus
0, 1, 2, .... 9 ==> entering numeric (or perhaps alphanumeric) values

  • ==> Abort menu (or delete last digit while entering values)

==> Enter (finish entering value or confirm selected menu item)

So what details you are thinking about your menu?
How many main menu items (up to 4 would be no problem: A B C D)
How many sub menu items for each main menu?
Is a two-level menu logic with "main menu item" and "sub menu item" enough?
If you want to enter values: Just numeric values? Or also alphanumeric values?

I think that searching for some ready-to-use-menu that is "easy adaptable" to every kind of usage and uses "the same 4x4 matrix keypad" and is "easy usable" at the same time might not work.

Most likely it would be easier to:

  • think about what you need for the menu
  • then code a menu that fits the needs

jurs:
So what details you are thinking about your menu?
How many main menu items (up to 4 would be no problem: A B C D)
How many sub menu items for each main menu?
Is a two-level menu logic with "main menu item" and "sub menu item" enough?
If you want to enter values: Just numeric values? Or also alphanumeric values?

Can you give me a code with 4 items you mentioned???

Yes, It needs to be 2 level submenu( upto 4 level suggested )
A submenu within each menu
I want to enter numerical values.

irfanece:
Can you give me a code with 4 items you mentioned???

No, I have no such menu system code ready and would have develop such code the same as you.

If I find some spare time, I can perhaps try to do so.

First thing would be to think about suitable data structures. My first idea would be, that each menu item consists of a numerical 'identification number' and a 'menu item text'. Lets say the main menu items get the id numbers 10, 20, 30, and the sub menu items get the last digit. So perhaps:

Menu A
10 - Display
11 - Screen 1
12 - Screen 2
13 - Screen 3
14 - Screen 4

Menu B
20 - Sensors
21 - Min. Temperature
22 - Max. Temperature
23 - Min. Humidity
24 - Max. Humidity

Menu C
30 - Time
31 - Set Clock
32 - Set Alarm Time
33 - Light ON Time
34 - Light OFF Time

Next thing to think about what type of numeric input you want to enter:

  • positive integers only?
  • or also negative numbers?
  • floating point numbers with decimals?
  • clock times (hours/minutes)?
  • dates (year/month/day)?

The more details you know about what you actually want to do with the menu, the better suited and easier data structures and code algorithm you can use while coding the menu.

And the more you want a jack of all trades device the more complicated things may be going.

Do we need to use any libraries for menu design???

irfanece:
Do we need to use any libraries for menu design???

I think that "#include <Keypad.h>" will be very useful.

Here is something I tried today as a starting point:

#include <Keypad.h>

const byte ROWS = 4; // Four rows
const byte COLS = 4; //  columns
// Define the Keymap
char keys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};

byte rowPins[ROWS] = {5,4,3,2};
byte colPins[COLS] = {A0,A1,A2,A3};

// Create the Keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

enum {MENU_NN, MENU_NUM};
struct menuItem_t {byte id; char type; char* text;};

menuItem_t menu[]={
 {10, MENU_NN, "Display"},
 {11, MENU_NN, "Screen-1"},
 {12, MENU_NN, "Screen-2"},
 {13, MENU_NN, "Screen-3"},
 {14, MENU_NN, "Screen-4"},
 {20, MENU_NN, "Sensors"},
 {21, MENU_NN, "Min. Temperature"},
 {22, MENU_NN, "Max. Temperature"},
 {30, MENU_NN, "Time"},
 {31, MENU_NN, "Show Time"},
 {32, MENU_NN, "Set Time"},
 {33, MENU_NN, "Set Alarm Time ON"},
 {34, MENU_NN, "Set Alarm Time OFF"},
 {40, MENU_NN, "Enter Values"},
 {41, MENU_NUM, "Value 1"},
 {42, MENU_NUM, "Value 2"},
};

#define NUMMENUITEMS (sizeof(menu)/sizeof(menu[0]))

int findMenuIndex(byte id)
{
  for (int i=0;i<NUMMENUITEMS;i++) 
  {
    if (id==menu[i].id) return i;
  }
  return -1; // id not found
}

int currentMenuID;
int currentMenuIndex=-1;
boolean currentMenuChanged;

void handleMenuKey(char c)
{
  currentMenuChanged=false;
  if (c==0) return;
  int menuID=currentMenuID;
  
  if (c=='*' && currentMenuID>=0) 
  {
    currentMenuID=0; // Abort/Exit menu
    currentMenuIndex=-1;
    currentMenuChanged=true;
  }
  else if (c>='A' && c<='D') // key 'A'...'D' pressed
  {
    int i=c-'A';
    if (i!=menuID/10-1) menuID=10+i*10; // activate main menu
    else if (findMenuIndex(menuID+1)>=0) menuID++; // increase sub menu
    else menuID=10+i*10; // from last sub menu return to main menu
    if (menuID!=currentMenuID) // has menuID changed?
    {
      currentMenuChanged=true;
      currentMenuID=menuID;
      currentMenuIndex= findMenuIndex(menuID);
    }
    return;
  }
}

void setup(){
  Serial.begin(9600);
}

void loop(){
  handleMenuKey(keypad.getKey());

  if (currentMenuChanged)
  {
    if (currentMenuIndex>=0)
      Serial.println( menu[currentMenuIndex].text);
    else  
      Serial.println( "Exit from menu");
  }
}

This is just a start for menu handling and stepping through the menu.
Output on Serial for testing.

Currently only 5 keys are handled for selecting menu items (no numeric input yet):
A ==> Activate menu ID 10
B ==> Activate menu ID 20
C ==> Activate menu ID 30
D ==> Activate menu ID 40

  • ==> Exit/Abort from menu

Consecutive presses of the same letter key will step through the sub menus.

Next would be a numeric editor to support entering numeric values.

Any thoughts about the numeric values you would like to enter?
Bytes in the range 0 to 255?
Unsigned integers?
Signed integers?
Signed or unsigned long values?
Floating point numbers?

jurs:
I think that "#include <Keypad.h>" will be very useful.

Here is something I tried today as a starting point:

#include <Keypad.h>

const byte ROWS = 4; // Four rows
const byte COLS = 4; //  columns
// Define the Keymap
char keys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};

byte rowPins[ROWS] = {5,4,3,2};
byte colPins[COLS] = {A0,A1,A2,A3};

// Create the Keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

enum {MENU_NN, MENU_NUM};
struct menuItem_t {byte id; char type; char* text;};

menuItem_t menu[]={
{10, MENU_NN, "Display"},
{11, MENU_NN, "Screen-1"},
{12, MENU_NN, "Screen-2"},
{13, MENU_NN, "Screen-3"},
{14, MENU_NN, "Screen-4"},
{20, MENU_NN, "Sensors"},
{21, MENU_NN, "Min. Temperature"},
{22, MENU_NN, "Max. Temperature"},
{30, MENU_NN, "Time"},
{31, MENU_NN, "Show Time"},
{32, MENU_NN, "Set Time"},
{33, MENU_NN, "Set Alarm Time ON"},
{34, MENU_NN, "Set Alarm Time OFF"},
{40, MENU_NN, "Enter Values"},
{41, MENU_NUM, "Value 1"},
{42, MENU_NUM, "Value 2"},
};

#define NUMMENUITEMS (sizeof(menu)/sizeof(menu[0]))

int findMenuIndex(byte id)
{
  for (int i=0;i<NUMMENUITEMS;i++)
  {
    if (id==menu[i].id) return i;
  }
  return -1; // id not found
}

int currentMenuID;
int currentMenuIndex=-1;
boolean currentMenuChanged;

void handleMenuKey(char c)
{
  currentMenuChanged=false;
  if (c==0) return;
  int menuID=currentMenuID;
 
  if (c=='' && currentMenuID>=0)
  {
    currentMenuID=0; // Abort/Exit menu
    currentMenuIndex=-1;
    currentMenuChanged=true;
  }
  else if (c>='A' && c<='D') // key 'A'...'D' pressed
  {
    int i=c-'A';
    if (i!=menuID/10-1) menuID=10+i
10; // activate main menu
    else if (findMenuIndex(menuID+1)>=0) menuID++; // increase sub menu
    else menuID=10+i*10; // from last sub menu return to main menu
    if (menuID!=currentMenuID) // has menuID changed?
    {
      currentMenuChanged=true;
      currentMenuID=menuID;
      currentMenuIndex= findMenuIndex(menuID);
    }
    return;
  }
}

void setup(){
  Serial.begin(9600);
}

void loop(){
  handleMenuKey(keypad.getKey());

if (currentMenuChanged)
  {
    if (currentMenuIndex>=0)
      Serial.println( menu[currentMenuIndex].text);
    else 
      Serial.println( "Exit from menu");
  }
}




This is just a start for menu handling and stepping through the menu.
Output on Serial for testing.

Currently only 5 keys are handled for selecting menu items (no numeric input yet):
A ==> Activate menu ID 10
B ==> Activate menu ID 20
C ==> Activate menu ID 30
D ==> Activate menu ID 40
* ==> Exit/Abort from menu

Consecutive presses of the same letter key will step through the sub menus.

Next would be a numeric editor to support entering numeric values.

Any thoughts about the numeric values you would like to enter?
Bytes in the range 0 to 255?
Unsigned integers?
Signed integers?
Signed or unsigned long values?
Floating point numbers?

Thanks friend! I am going to try this really hard! The tricky part is that i should also focus on LCD at the same time!

irfanece:
The tricky part is that i should also focus on LCD at the same time!

Do you know how to print on your LCD?
Then there is nothing tricky.

The menu itself will be completely independent from the output device.

So whether the output will be sent to a LCD text display, a LCD graphics display, an OLED display, a VT52 serial terminal, some 7-segment displays, or a TV screen makes absolutely no difference.

There is just one trick: Use the IPO principle for programming your loop() function:

  • Input (read input from outer world outside the Arduino)
  • Processing (logical processing of input data to output values in RAM only)
  • Output (send output to the outer world outside the Arduino)

So the programming logic for the loop() function will always look like:

void loop()
{
  input();
  processing();
  output();
}

If you always do it strictly that way, it will make absolutely no difference where you send the output.

If you have fancy sensor handling, your loop function may be extended to:

void loop()
{
  sensorInput();
  keyPadInput();
  otherInput();
  sensorProcessing();
  keypadProcessing();
  otherProcessing();
  digitalOutput();
  pwmOutput();
  ledOutput();
  serialOutput();
  lcdOutput();
}

But the IPO principle always stays the same: Keep the logical steps of input/processing/output seperated from each others and you can replace each of them independent from the other. So if you want to change from "output on serial" or "output on LCD" the only thing to change will be the output() function you will use in your software.

Here is another example with some more features.
This one is ready for doing numeric values input:

#include <Keypad.h>

const byte ROWS = 4; // Four rows
const byte COLS = 4; //  columns
// Define the Keymap
char keys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};

byte rowPins[ROWS] = {5,4,3,2};
byte colPins[COLS] = {A0,A1,A2,A3};

// Create the Keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

enum {MENU_NN, MENU_NUM};
struct menuItem_t {byte id; char type; char* text;};

menuItem_t menu[]={
 {10, MENU_NN, "Display"},
 {11, MENU_NN, "Screen-1"},
 {12, MENU_NN, "Screen-2"},
 {13, MENU_NN, "Screen-3"},
 {14, MENU_NN, "Screen-4"},
 {20, MENU_NN, "Sensors"},
 {21, MENU_NN, "Min. Temperature"},
 {22, MENU_NN, "Max. Temperature"},
 {30, MENU_NN, "Time"},
 {31, MENU_NN, "Show Time"},
 {32, MENU_NN, "Set Time"},
 {33, MENU_NN, "Set Alarm Time ON"},
 {34, MENU_NN, "Set Alarm Time OFF"},
 {40, MENU_NN, "Enter Values"},
 {41, MENU_NUM, "Value 1"},
 {42, MENU_NUM, "Value 2"},
};

#define NUMMENUITEMS (sizeof(menu)/sizeof(menu[0]))

int findMenuIndex(byte id)
{
  for (int i=0;i<NUMMENUITEMS;i++) 
  {
    if (id==menu[i].id) return i;
  }
  return -1; // id not found
}

int currentMenuID;
int currentMenuIndex=-1;
boolean currentMenuChanged;
char menuInput[21]; 
boolean menuInputChanged;

int handleMenuKey(char c)
{ // return value is -1 if key has been handled by no value has been entered
  // return value is menuIndex of item for which a value has been entered
  int retVal=-1;  
  currentMenuChanged=false;
  menuInputChanged=false;
  if (c==0) return retVal;
  int menuID=currentMenuID;
  if (c=='#' && currentMenuID>=0 && strlen(menuInput)>0)
  {
    retVal=currentMenuIndex;
    currentMenuID=0; // Abort/Exit menu
    currentMenuIndex=-1;
    currentMenuChanged=true;
    return retVal; // we have finished entering a value
  }
  else if (c=='*' && strlen(menuInput)>0) 
  {
    menuInput[strlen(menuInput)-1]='\0'; // clear last input character
    menuInputChanged=true;
  }
  else if (c=='*' && currentMenuID>=0) 
  {
    currentMenuID=0; // Abort/Exit menu
    currentMenuIndex=-1;
    currentMenuChanged=true;
  }
  else if (c>='A' && c<='D') // key 'A'...'D' pressed
  {
    int i=c-'A';
    if (i!=menuID/10-1) menuID=10+i*10; // activate main menu
    else if (findMenuIndex(menuID+1)>=0) menuID++; // increase sub menu
    else menuID=10+i*10; // from last sub menu return to main menu
    if (menuID!=currentMenuID) // has menuID changed?
    {
      currentMenuChanged=true;
      currentMenuID=menuID;
      currentMenuIndex= findMenuIndex(menuID);
      memset(menuInput,0,sizeof(menuInput));
    }
  }
  else if (c>='0' && c<='9' && menu[currentMenuIndex].type==MENU_NUM) // key'0'...'9' pressed and numeric input
  {
    if (strlen(menuInput)<sizeof(menuInput)-1)
    {
      menuInput[strlen(menuInput)]=c;
      menuInputChanged=true;
    }
  }
  return retVal;
}

void outputMenuItem()
{
  // for LCD output: set output position here
  char buf[21];
  // Format buffer to fixed length
  if (currentMenuIndex>=0)
    snprintf(buf, sizeof(buf), "%-20s", menu[currentMenuIndex].text);
  else  
    snprintf(buf, sizeof(buf), "%-20s", "No menu active");
  Serial.println(buf);    
}

void outputMenuInput()
{
  // for LCD output: set output position here
  char buf[21];
  // Format buffer to fixed length
  snprintf(buf, sizeof(buf), "%20s", menuInput);
  Serial.println(buf);    
}


void setup(){
  Serial.begin(9600);
}

void loop()
{
  // input
  char c=keypad.getKey();
  
  // processing of input key
  int inputReady=handleMenuKey(c);
  
  // if we are finished with entering a value, we could do further processing
  if (inputReady>=0)
  { // in this case just show some serial debugging message
    Serial.print("Input ready: ");
    Serial.print(menuInput);
    Serial.print(" for menu index ");
    Serial.println(inputReady);
  } 

  // output functions (i.e. output to serial, output to lcd)
  if (currentMenuChanged) outputMenuItem();
  if (menuInputChanged)  outputMenuInput();
}

If you want output to print on a different device, you'd have to change the two functions:

  • outputMenuItem(); ==> prints the current menu item
  • outputMenuInput(); ==> prints the current input value

Numeric input is only possible with menu items that are of type MENU_NUM.
So the example has two items for numeric input in the 'D' menu ("Value 1" and "Value 2").

While doing numeric input there is limited editing possible: By entering '*' you can delete the last entered digit from the input.

For finishing numeric input, enter '#' key.

If you want to do your own processing of entered values, include it in the loop() function after checking if there is some input ready for you:

  if (inputReady>=0)
  {
  ...
  }

When printing to a graphics LCD, perhaps use a 'fixed pitch' font, so that every character prints the same width.

Alright, i got an overview from this program! You have used state variables... That's indeed a valuable point! I am going to use this idea.... Thanks Bro :slight_smile:

Hello! This is the code i have developed using state variables:

#include <Keypad.h>
#include "U8glib.h"

const byte ROWS = 4; // Four rows
const byte COLS = 4; //  columns
// Define the Keymap
char keys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};
byte rowPins[ROWS] = {37,35,33,31};
byte colPins[COLS] = {29,27,25,23};

int CurrentMenu=0;

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

void setup(){
  Serial.begin(9600);
  MainMenu();
}

void MainMenu(void)
{
Serial.println("Main Menu");
Serial.println("Menu - 1");
Serial.println("Menu - 2");
Serial.println("Menu - 3");
}

void loop(){
    char key = keypad.getKey();
    if(CurrentMenu==0 && key=='1')
  {
Serial.println("Submenu - 1");
Serial.println("*-back");
CurrentMenu=1;
  }
    else if(CurrentMenu==0 && key=='2')
    {
Serial.println("Submenu - 2");
Serial.println("*-back");
CurrentMenu=1;
  }
    else if(CurrentMenu==0 && key=='3')
    {
Serial.println("Submenu - 3");
Serial.println("*-back");
CurrentMenu=1;
  }
    else if(CurrentMenu==1 && key=='*')
    {
MainMenu();
CurrentMenu=0;
  }
}

This is the output:

Main Menu
Menu - 1
Menu - 2
Menu - 3

Submenu - 1
*-back

Main Menu
Menu - 1
Menu - 2
Menu - 3

Submenu - 2
*-back

Main Menu
Menu - 1
Menu - 2
Menu - 3

Submenu - 3
*-back

Main Menu
Menu - 1
Menu - 2
Menu - 3

My question: How to add a password authentication to this code? I want it to ask a one time password validation like this

Please enter Password:

if password is true, then output like this:

Main Menu
Menu - 1
Menu - 2
Menu - 3

Submenu - 1
*-back
........

if password is false, then output like this:

Please enter correct password!

I don't wanna use password library and use only keypad library only... Please help me with a code, Thanks :slight_smile:

Can i get some help over here??? :frowning: :frowning: :frowning: