Scrolling/Interacting with an LCD screen Menu using keypad as input

I've tried looking through youtube videos and other forum post, but I'm still unable to scroll through and select menus on my lcd screen using the keypad.

I'm using a Mega 2560 and all the pins are connected directly into the Arduino.

I also plan on adding submenus into the program just trying to solve this problem first.
Thank you in advance for the help!


#include<Keypad.h>
#include<Wire.h>
//#include<LCD.h>
#include<LiquidCrystal.h>


/************* LCD SCREEN PIN SETUPS ****************/

const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

/**************************************************KEYPAD SETUP**********************************************************************/

const byte numRows = 4; //number of rows on the keypad
const byte numCols = 4; //number of columns on the keypad
//keymap defines the key pressed according to the row and columns just as appears on the keypad

char keymap[numRows][numCols] =
{
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

byte rowPins[numRows] = {36, 34, 32, 30}; //Rows 0 to 3
byte colPins[numCols] = {28, 26, 24, 22}; //Columns 0 to 3

//initializes an instance of the Keypad class
Keypad myKeypad = Keypad(makeKeymap(keymap), rowPins, colPins, numRows, numCols);

char keypressed;

/*******DEBOUNCING**************/
int count = 0;
int dt = 20; //debounce time ins ms
int switch1Value;
int switch1OldValue;


/*************** MENU CONTROL **********************/
String menuItems[] = {"Intake", "Set Alarm", "Counters", "Random"};
int menuPage = 0;
int maxMenuPages = round(((sizeof(menuItems) / sizeof(String)) / 2) + .5);
int cursorPosition = 0;

// Creating custom characters for the menu display
byte downArrow[8] = {
  0b00100, //   *
  0b00100, //   *
  0b00100, //   *
  0b00100, //   *
  0b00100, //   *
  0b10101, // * * *
  0b01110, //  ***
  0b00100  //   *
};

byte upArrow[8] = {
  0b00100, //   *
  0b01110, //  ***
  0b10101, // * * *
  0b00100, //   *
  0b00100, //   *
  0b00100, //   *
  0b00100, //   *
  0b00100  //   *
};

byte menuCursor[8] = {
  B01000, //  *
  B00100, //   *
  B00010, //    *
  B00001, //     *
  B00010, //    *
  B00100, //   *
  B01000, //  *
  B00000  //
};

/*****************FUNCTION PROTOTYPE*******************/
void main_Menu();
void Cursor();
void main_Menu_Operation();
void menuItem1();
void menuItem2();
void menuItem3();
void menuItem4();
int CheckInput(int k); //checks keypad input

/*************************************************MAIN CODE *****************************/
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);

  //clearing and inititalizing lcd screen
  lcd.begin(16, 2);
  lcd.clear();
  // Creates the byte for the 3 custom characters
  lcd.createChar(0, menuCursor);
  lcd.createChar(1, upArrow);
  lcd.createChar(2, downArrow);

}

void loop() {
  // put your main code here, to run repeatedly:
  char keypressed = myKeypad.getKey();
  Serial.println(keypressed);

  main_Menu();
  Cursor();
  main_Menu_Operation();
  switch1Value = keypressed; // value will be 0 if pressed and 1 if not

  if ((switch1OldValue == NO_KEY) && (switch1Value != NO_KEY)) //detects falling edge -10
  {
    count++; //do your task on falling edge
    delay(dt); // delay to prevent unwanted readings
  }
  if ((switch1OldValue != NO_KEY) && (switch1Value == NO_KEY)) //rising edge
  {
    delay(dt); //adds delay to prevent undesirable readings

  }

  switch1OldValue = switch1Value;
  Serial.println(count);


}

void main_Menu()
{
  Serial.print(menuPage);
  lcd.clear();
  lcd.setCursor(1, 0);
  lcd.print(menuItems[menuPage]);
  lcd.setCursor(1, 1);
  lcd.print(menuItems[menuPage + 1]);
  if (menuPage == 0)
  {
    lcd.setCursor(15, 1);
    lcd.write(byte(2));
  }
  else if (menuPage > 0 and menuPage < maxMenuPages)
  {
    lcd.setCursor(15, 1);
    lcd.write(byte(2));
    lcd.setCursor(15, 0);
    lcd.write(byte(1));
  }
  else if (menuPage == maxMenuPages)
  {
    lcd.setCursor(15, 0);
    lcd.write(byte(1));
  }
}

//Function makes sure the cursor is in the correct position
void Cursor()
{
  for (int x = 0; x < 2; x++) //erasing current cursor
  {
    lcd.setCursor(0, x);
    lcd.print(" ");
  }
  if (menuPage % 2 == 0) //menu page is even
  {
    if (cursorPosition % 2 == 0) // cursor position is even
    {
      lcd.setCursor(0, 0);
      lcd.write(byte(0));
    }
    if (cursorPosition % 2 != 0) // cursor position is odd
    {
      lcd.setCursor(0, 1);
      lcd.write(byte(0));
    }
  }

  if (menuPage % 2 != 0) //menu page is odd
  {
    if (cursorPosition % 2 == 0) //cursor position is even
    {
      lcd.setCursor(0, 1);
      lcd.write(byte(0));
    }
    if (cursorPosition % 2 != 0) //cursor position is odd
    {
      lcd.setCursor(0, 0);
      lcd.write(byte(0));
    }
  }
}

void main_Menu_Operation()
{
  if (keypressed != NO_KEY)
  {
    switch (keypressed)
    {
      case 'A': // if A is pressed
        {
          switch (cursorPosition)
          {
            case 0:
              menuItem1();
              break;
            case 1:
              menuItem2();
              break;
            case 2:
              menuItem3();
              break;
            case 3:
              menuItem4();
              break;
          }
          //ButtonPressed = 1;
          main_Menu();
          Cursor();
          break;
        }
      case '2': // 2 on the keypad serves as the up button
        {
          //KEYPAD = 0;
          if (menuPage == 0) // start of menu page
          {
            cursorPosition = cursorPosition - 1;
            cursorPosition = constrain(cursorPosition, 0, ((sizeof(menuItems) / sizeof(String)) - 1));
          }
          if (menuPage % 2 == 0 && cursorPosition % 2 == 0) // even page even cursorPosition
          {
            menuPage = menuPage - 1;
            menuPage = constrain(menuPage, 0, maxMenuPages);
          }
          if (menuPage % 2 != 0 && cursorPosition % 2 != 0) // odd menu page and cursorPosition
          {
            menuPage = menuPage - 1;
            menuPage = constrain(menuPage, 0, maxMenuPages);
          }

          cursorPosition = cursorPosition - 1;
          cursorPosition = constrain(cursorPosition, 0, ((sizeof(menuItems) / sizeof(String)) - 1));

          main_Menu();
          Cursor();
          //ButtonPressed = 1;
          break;
        }
      case '8': // 8 on keypad is the downward button
        {
          //KEYPAD = 0;
          if (menuPage % 2 == 0 && cursorPosition % 2 != 0) //even menu page odd cursorPosition
          {
            menuPage = menuPage + 1;
            menuPage = constrain(menuPage, 0, maxMenuPages);
          }
          if (menuPage % 2 != 0 && cursorPosition % 2 == 0) // odd menuPage even cursorPosition
          {
            menuPage = menuPage + 1;
            menuPage = constrain(menuPage, 0, maxMenuPages);
          }

          cursorPosition = cursorPosition - 1;
          cursorPosition = constrain(cursorPosition, 0, ((sizeof(menuItems) / sizeof(String)) - 1));

          main_Menu();
          Cursor();
          //ButtonPressed = 1;
          break;
        }
      default:
        break;
    }
  }
}

/*
  int CheckInput(int k) //checks keypad input
  {
  int result = 0;
  if (k == 'A')
  {
    result = 1; //select
  }
  if (k == '2')
  {
    result = 2;// move up
  }
  if (k == '8') //move down
  {
    result = 3;
  }
  if (k == 'B') // move back
  {
    result = 4;
  }
  return (result);
  }

*/
void menuItem1() //Intake menu
{
  lcd.clear();
  lcd.setCursor(3, 0);
  lcd.print("Start Intake Process?");
  if (keypressed != NO_KEY)
  {
    switch (keypressed)
    {
      case 'B': //B will be used as a back button
        {
          break;
        }
      case 'A' :// something selected
        {
          //call intake function
          break;
        }
      default:
        break;
    }
  }
}


void menuItem2() //Setting dispensing schedule
{

  lcd.clear();
  lcd.setCursor(3, 0);
  lcd.print("Set Schedule");
  if (keypressed != NO_KEY)
  {
    switch (keypressed)
    {
      case 'B': //B will be used as a back button
        {
          break;
        }
      case 'A' :// something selected
        {
          //call the alarm function
          break;
        }
      default:
        break;
    }
  }
}


void menuItem3() //unassigned
{

  lcd.clear();
  lcd.setCursor(3, 0);
  lcd.print("Start Intake Process?");
  if (keypressed != NO_KEY)
  {
    switch (keypressed)
    {
      case 'B': //B will be used as a back button
        {
          break;
        }
      case 'A' :// something selected
        {
          //call the alarm function
          break;
        }
      default:
        break;
    }
  }
}

void menuItem4() //unassigned
{
  lcd.clear();
  lcd.setCursor(3, 0);
  lcd.print("Start Intake Process?");
  if (keypressed != NO_KEY)
  {
    switch (keypressed)
    {
      case 'B': //B will be used as a back button
        {
          break;
        }
      case 'A' :// something selected
        {
          //call the alarm function
          break;
        }
      default:
        break;
    }
  }
}```

Welcome to the forum

Where are you stuck ?

For a start, does the keypad work ?

Yes, the keypad does work I checked that, but when I go to press for example the 'A' button on the keypad it does not do what it is meant to do which is to select that menu option.

Break the problem down

Does the code ever call the main_Menu_Operation() function, for instance and, if so, what is the value of keypressed and cursorPosition when the function is entered ?

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.