Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /***************************************************************************************
- Name : LCD Button Shield Menu
- Author : Paul Siewert
- Created : June 14, 2016
- Last Modified: June 14, 2016
- Version : 1.0
- Notes : This code is for use with an Arduino Uno and LCD/button shield. The
- intent is for anyone to use this program to give them a starting
- program with a fully functional menu with minimal modifications
- required by the user.
- License : This program is free software. You can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- ***************************************************************************************/
- /*
- This program is designed to get you as close as possible to a finished menu for the standard Arduino Uno LCD/button shield. The only required modifications
- are to add as menu items to the master menu (menuItems array) and then modify/adjust the void functions below for each of those selections.
- */
- // You can have up to 10 menu items in the menuItems[] array below without having to change the base programming at all. Name them however you'd like. Beyond 10 items, you will have to add additional "cases" in the switch/case
- // section of the operateMainMenu() function below. You will also have to add additional void functions (i.e. menuItem11, menuItem12, etc.) to the program.
- String menuItems[] = {"ITEM 1", "ITEM 2", "ITEM 3"};
- String subMenuItems[][] = {
- {"I1 Sub1", "I1 Sub2"},
- {"I2 Sub1", "I2 Sub2"},
- {"I3 Sub1", "I3 Sub2"}
- };
- // Navigation button variables
- int readKey;
- int savedDistance = 0;
- // Menu control variables
- int menuPage = 0;
- int maxMenuPages = round(((sizeof(menuItems) / sizeof(String)) / 2) + .5);
- int cursorPosition = 0;
- int subMenuPage = 0;
- int maxSubMenuPages(menu) {
- return round(((sizeof(subMenuItems[menu]) / sizeof(String)) / 2) + .5);
- }
- int subCursorPosition = 0;
- int subMenu = -1;
- // Creates 3 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 //
- };
- #include <Wire.h>
- #include <LiquidCrystal.h>
- // Setting the LCD shields pins
- LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
- void setup() {
- // Initializes serial communication
- Serial.begin(9600);
- // Initializes and clears the 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() {
- if(subMenu == -1) {
- mainMenuDraw();
- drawCursor();
- operateMainMenu();
- } else {
- subMenuDraw(subMenu);
- drawCursor();
- operateSubMenu();
- }
- }
- // This function will generate the 2 menu items that can fit on the screen. They will change as you scroll through your menu. Up and down arrows will indicate your current menu position.
- void mainMenuDraw() {
- 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));
- }
- }
- // When called, this function will erase the current cursor and redraw it based on the cursorPosition and menuPage variables.
- void drawCursor() {
- for (int x = 0; x < 2; x++) { // Erases current cursor
- lcd.setCursor(0, x);
- lcd.print(" ");
- }
- // The menu is set up to be progressive (menuPage 0 = Item 1 & Item 2, menuPage 1 = Item 2 & Item 3, menuPage 2 = Item 3 & Item 4), so
- // in order to determine where the cursor should be you need to see if you are at an odd or even menu page and an odd or even cursor position.
- if (menuPage % 2 == 0) {
- if (cursorPosition % 2 == 0) { // If the menu page is even and the cursor position is even that means the cursor should be on line 1
- lcd.setCursor(0, 0);
- lcd.write(byte(0));
- }
- if (cursorPosition % 2 != 0) { // If the menu page is even and the cursor position is odd that means the cursor should be on line 2
- lcd.setCursor(0, 1);
- lcd.write(byte(0));
- }
- }
- if (menuPage % 2 != 0) {
- if (cursorPosition % 2 == 0) { // If the menu page is odd and the cursor position is even that means the cursor should be on line 2
- lcd.setCursor(0, 1);
- lcd.write(byte(0));
- }
- if (cursorPosition % 2 != 0) { // If the menu page is odd and the cursor position is odd that means the cursor should be on line 1
- lcd.setCursor(0, 0);
- lcd.write(byte(0));
- }
- }
- }
- void operateMainMenu() {
- int activeButton = 0;
- while (activeButton == 0) {
- int button;
- readKey = analogRead(0);
- if (readKey < 790) {
- delay(100);
- readKey = analogRead(0);
- }
- button = evaluateButton(readKey);
- switch (button) {
- case 0: // When button returns as 0 there is no action taken
- break;
- case 1: // This case will execute if the "forward" button is pressed
- button = 0;
- switch (cursorPosition) { // The case that is selected here is dependent on which menu page you are on and where the cursor is.
- case 0:
- subMenu = 0;
- break;
- case 1:
- subMenu = 1;
- break;
- case 2:
- subMenu = 2;
- break;
- case 3:
- }
- activeButton = 1;
- mainMenuDraw();
- drawCursor();
- break;
- case 2:
- button = 0;
- if (menuPage == 0) {
- cursorPosition = cursorPosition - 1;
- cursorPosition = constrain(cursorPosition, 0, ((sizeof(menuItems) / sizeof(String)) - 1));
- }
- if (menuPage % 2 == 0 and cursorPosition % 2 == 0) {
- menuPage = menuPage - 1;
- menuPage = constrain(menuPage, 0, maxMenuPages);
- }
- if (menuPage % 2 != 0 and cursorPosition % 2 != 0) {
- menuPage = menuPage - 1;
- menuPage = constrain(menuPage, 0, maxMenuPages);
- }
- cursorPosition = cursorPosition - 1;
- cursorPosition = constrain(cursorPosition, 0, ((sizeof(menuItems) / sizeof(String)) - 1));
- mainMenuDraw();
- drawCursor();
- activeButton = 1;
- break;
- case 3:
- button = 0;
- if (menuPage % 2 == 0 and cursorPosition % 2 != 0) {
- menuPage = menuPage + 1;
- menuPage = constrain(menuPage, 0, maxMenuPages);
- }
- if (menuPage % 2 != 0 and cursorPosition % 2 == 0) {
- menuPage = menuPage + 1;
- menuPage = constrain(menuPage, 0, maxMenuPages);
- }
- cursorPosition = cursorPosition + 1;
- cursorPosition = constrain(cursorPosition, 0, ((sizeof(menuItems) / sizeof(String)) - 1));
- mainMenuDraw();
- drawCursor();
- activeButton = 1;
- break;
- }
- }
- }
- // This function is called whenever a button press is evaluated. The LCD shield works by observing a voltage drop across the buttons all hooked up to A0.
- int evaluateButton(int x) {
- int result = 0;
- if (x < 50) {
- result = 1; // right
- } else if (x < 195) {
- result = 2; // up
- } else if (x < 380) {
- result = 3; // down
- } else if (x < 790) {
- result = 4; // left
- }
- return result;
- }
- // If there are common usage instructions on more than 1 of your menu items you can call this function from the sub
- // menus to make things a little more simplified. If you don't have common instructions or verbage on multiple menus
- // I would just delete this void. You must also delete the drawInstructions()function calls from your sub menu functions.
- void drawInstructions() {
- lcd.setCursor(0, 1); // Set cursor to the bottom line
- lcd.print("Use ");
- lcd.write(byte(1)); // Up arrow
- lcd.print("/");
- lcd.write(byte(2)); // Down arrow
- lcd.print(" buttons");
- }
- void menuItem1() { // Function executes when you select the 2nd item from main menu
- int activeButton = 0;
- lcd.clear();
- lcd.setCursor(3, 0);
- lcd.print("Sub Menu 2");
- while (activeButton == 0) {
- int button;
- readKey = analogRead(0);
- if (readKey < 790) {
- delay(100);
- readKey = analogRead(0);
- }
- button = evaluateButton(readKey);
- switch (button) {
- case 4: // This case will execute if the "back" button is pressed
- button = 0;
- activeButton = 1;
- break;
- }
- }
- }
- void menuItem2() { // Function executes when you select the 2nd item from main menu
- int activeButton = 0;
- lcd.clear();
- lcd.setCursor(3, 0);
- lcd.print("Sub Menu 2");
- while (activeButton == 0) {
- int button;
- readKey = analogRead(0);
- if (readKey < 790) {
- delay(100);
- readKey = analogRead(0);
- }
- button = evaluateButton(readKey);
- switch (button) {
- case 4: // This case will execute if the "back" button is pressed
- button = 0;
- activeButton = 1;
- break;
- }
- }
- }
- void menuItem3() { // Function executes when you select the 3rd item from main menu
- int activeButton = 0;
- lcd.clear();
- lcd.setCursor(3, 0);
- lcd.print("Sub Menu 3");
- while (activeButton == 0) {
- int button;
- readKey = analogRead(0);
- if (readKey < 790) {
- delay(100);
- readKey = analogRead(0);
- }
- button = evaluateButton(readKey);
- switch (button) {
- case 4: // This case will execute if the "back" button is pressed
- button = 0;
- activeButton = 1;
- break;
- }
- }
- }
- void subMenuDraw() {
- Serial.print(subMenuPage);
- lcd.clear();
- lcd.setCursor(1, 0);
- lcd.print(menuItems[subMenu][subMenuPage]);
- lcd.setCursor(1, 1);
- lcd.print(menuItems[subMenu][subMenuPage + 1]);
- if (subMenuPage == 0) {
- lcd.setCursor(15, 1);
- lcd.write(byte(2));
- } else if (subMenuPage > 0 and subMenuPage < maxSubMenuPages) {
- lcd.setCursor(15, 1);
- lcd.write(byte(2));
- lcd.setCursor(15, 0);
- lcd.write(byte(1));
- } else if (subMenuPage == maxSubMenuPages) {
- lcd.setCursor(15, 0);
- lcd.write(byte(1));
- }
- }
- // When called, this function will erase the current cursor and redraw it based on the cursorPosition and subMenuPage variables.
- void drawCursor() {
- for (int x = 0; x < 2; x++) { // Erases current cursor
- lcd.setCursor(0, x);
- lcd.print(" ");
- }
- // The menu is set up to be progressive (subMenuPage 0 = Item 1 & Item 2, subMenuPage 1 = Item 2 & Item 3, subMenuPage 2 = Item 3 & Item 4), so
- // in order to determine where the cursor should be you need to see if you are at an odd or even menu page and an odd or even cursor position.
- if (subMenuPage % 2 == 0) {
- if (cursorPosition % 2 == 0) { // If the menu page is even and the cursor position is even that means the cursor should be on line 1
- lcd.setCursor(0, 0);
- lcd.write(byte(0));
- }
- if (cursorPosition % 2 != 0) { // If the menu page is even and the cursor position is odd that means the cursor should be on line 2
- lcd.setCursor(0, 1);
- lcd.write(byte(0));
- }
- }
- if (subMenuPage % 2 != 0) {
- if (cursorPosition % 2 == 0) { // If the menu page is odd and the cursor position is even that means the cursor should be on line 2
- lcd.setCursor(0, 1);
- lcd.write(byte(0));
- }
- if (cursorPosition % 2 != 0) { // If the menu page is odd and the cursor position is odd that means the cursor should be on line 1
- lcd.setCursor(0, 0);
- lcd.write(byte(0));
- }
- }
- }
- void operateSubMenu() {
- int activeButton = 0;
- while (activeButton == 0) {
- int button;
- readKey = analogRead(0);
- if (readKey < 790) {
- delay(100);
- readKey = analogRead(0);
- }
- button = evaluateButton(readKey);
- switch (button) {
- case 0: // When button returns as 0 there is no action taken
- break;
- case 1: // This case will execute if the "forward" button is pressed
- button = 0;
- switch (cursorPosition) { // The case that is selected here is dependent on which menu page you are on and where the cursor is.
- case 0:
- menuItem1();
- break;
- case 1:
- menuItem2();
- break;
- case 2:
- menuItem3();
- break;
- }
- activeButton = 1;
- mainMenuDraw();
- drawCursor();
- break;
- case 2:
- button = 0;
- if (subMenuPage == 0) {
- cursorPosition = cursorPosition - 1;
- cursorPosition = constrain(cursorPosition, 0, ((sizeof(menuItems) / sizeof(String)) - 1));
- }
- if (subMenuPage % 2 == 0 and cursorPosition % 2 == 0) {
- subMenuPage = subMenuPage - 1;
- subMenuPage = constrain(subMenuPage, 0, maxSubMenuPages);
- }
- if (subMenuPage % 2 != 0 and cursorPosition % 2 != 0) {
- subMenuPage = subMenuPage - 1;
- subMenuPage = constrain(subMenuPage, 0, maxSubMenuPages);
- }
- cursorPosition = cursorPosition - 1;
- cursorPosition = constrain(cursorPosition, 0, ((sizeof(menuItems) / sizeof(String)) - 1));
- subMenuDraw();
- drawCursor();
- activeButton = 1;
- break;
- case 3:
- button = 0;
- if (subMenuPage % 2 == 0 and cursorPosition % 2 != 0) {
- subMenuPage = subMenuPage + 1;
- subMenuPage = constrain(subMenuPage, 0, maxSubMenuPages);
- }
- if (subMenuPage % 2 != 0 and cursorPosition % 2 == 0) {
- subMenuPage = subMenuPage + 1;
- subMenuPage = constrain(subMenuPage, 0, maxSubMenuPages);
- }
- cursorPosition = cursorPosition + 1;
- cursorPosition = constrain(cursorPosition, 0, ((sizeof(menuItems) / sizeof(String)) - 1));
- subMenuDraw();
- drawCursor();
- activeButton = 1;
- break;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement