Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- April 4, 2019
- Adafruit 16x2_LCD+keypad shield example.
- Note: this sketch ONLY works with the Adafruit LCD + keypad shield that uses the MPC23017 i2c expander chip.
- This sketch also is for a single-color PCD, so it doesn't try to change the LCD color. The same library is used for the single-color shields and the RGB-LCD shields.
- It will not work with the generic parallel-LCD and series-resistance button generic shields sold elsewhere online.
- */
- // Original head comments below:
- /***************************************************************************************
- 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.
- */
- // --------------------------------------------------- I moved the library declarations to the top...
- #include <Wire.h>
- // #include <LiquidCrystal.h> ------------------------ don't need this for the Adafruit shield, you only need Wire and the two libs below.
- #include <Adafruit_MCP23017.h> //<-------------------- this is a library for the i2c chip that the Adafruit shield uses.
- #include <Adafruit_RGBLCDShield.h>
- // 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", "ITEM 4", "ITEM 5", "ITEM 6"};
- // Navigation button variables
- int readKey;
- // Menu control variables
- int menuPage = 0;
- int maxMenuPages = round(((sizeof(menuItems) / sizeof(String)) / 2) + .5);
- int cursorPosition = 0;
- // 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 //
- };
- // Setting the LCD shields pins
- //LiquidCrystal lcd(8, 9, 4, 5, 6, 7); ------------------------------------------------------ removed.
- Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield(); //<------------------------------------- This is the Adafruit way.
- 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);
- Serial.println("Exiting setup()"); // ----------------- testing line.
- }
- void loop() {
- mainMenuDraw();
- drawCursor();
- operateMainMenu();
- }
- // 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; // <------------------------------------- I don't understand why this is put here.
- // Since it is a local variable, it will get re-declared as value==zero every time this function is called.
- // It looks like a mistake to me, but then I did not test this sketch on the generic LCD keypad shield.
- while (activeButton == 0) {
- int button;
- //readKey = analogRead(0);
- //if (readKey < 790) {
- // delay(100);
- // readKey = analogRead(0);
- //}
- button = evaluateButton(); //<------------------------------ The evaluateButton() function has been changed to get the button press from the Adafruit keypad.
- 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;
- case 3:
- menuItem4();
- break;
- case 4:
- menuItem5();
- break;
- case 5:
- menuItem6();
- break;
- case 6:
- menuItem7();
- break;
- case 7:
- menuItem8();
- break;
- case 8:
- menuItem9();
- break;
- case 9:
- menuItem10();
- break;
- }
- 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.
- int evaluateButton() { // The param is removed, since it isn't needed.
- int result = 0;
- /*
- Old code below:
- 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
- }
- */
- /*
- The Adafruit LCD shield library defines named hex values for the button identification in the Adafruit_RGBLCDShield.h file.
- These are the lines that do that:
- #define BUTTON_UP 0x08
- #define BUTTON_DOWN 0x04
- #define BUTTON_LEFT 0x10
- #define BUTTON_RIGHT 0x02
- #define BUTTON_SELECT 0x01
- You don't need to know numerically what these values are, you just need to compare the [button] value to the named constants above.
- */
- uint8_t x = lcd.readButtons(); // <------------------------------------ This reads the Adafruit LCD buttons.
- if (x == BUTTON_RIGHT) {
- result = 1; // right
- } else if (x == BUTTON_UP) {
- result = 2; // up
- } else if (x == BUTTON_DOWN) {
- result = 3; // down
- } else if (x == BUTTON_LEFT) {
- 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.print(byte(1)); // Up arrow
- lcd.print("/");
- lcd.print(byte(2)); // Down arrow
- lcd.print(" buttons");
- }
- void menuItem1() { // Function executes when you select the 1st item from main menu
- int activeButton = 0;
- lcd.clear();
- lcd.setCursor(3, 0);
- lcd.print("Sub Menu 1");
- while (activeButton == 0) {
- int button;
- //readKey = analogRead(0);
- //if (readKey < 790) {
- // delay(100);
- // readKey = analogRead(0);
- //}
- button = evaluateButton();
- 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();
- 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();
- switch (button) {
- case 4: // This case will execute if the "back" button is pressed
- button = 0;
- activeButton = 1;
- break;
- }
- }
- }
- void menuItem4() { // Function executes when you select the 4th item from main menu
- int activeButton = 0;
- lcd.clear();
- lcd.setCursor(3, 0);
- lcd.print("Sub Menu 4");
- while (activeButton == 0) {
- int button;
- //readKey = analogRead(0);
- //if (readKey < 790) {
- // delay(100);
- // readKey = analogRead(0);
- //}
- button = evaluateButton();
- switch (button) {
- case 4: // This case will execute if the "back" button is pressed
- button = 0;
- activeButton = 1;
- break;
- }
- }
- }
- void menuItem5() { // Function executes when you select the 5th item from main menu
- int activeButton = 0;
- lcd.clear();
- lcd.setCursor(3, 0);
- lcd.print("Sub Menu 5");
- while (activeButton == 0) {
- int button;
- //readKey = analogRead(0);
- //if (readKey < 790) {
- // delay(100);
- // readKey = analogRead(0);
- //}
- button = evaluateButton();
- switch (button) {
- case 4: // This case will execute if the "back" button is pressed
- button = 0;
- activeButton = 1;
- break;
- }
- }
- }
- void menuItem6() { // Function executes when you select the 6th item from main menu
- int activeButton = 0;
- lcd.clear();
- lcd.setCursor(3, 0);
- lcd.print("Sub Menu 6");
- while (activeButton == 0) {
- int button;
- //readKey = analogRead(0);
- //if (readKey < 790) {
- // delay(100);
- // readKey = analogRead(0);
- //}
- button = evaluateButton();
- switch (button) {
- case 4: // This case will execute if the "back" button is pressed
- button = 0;
- activeButton = 1;
- break;
- }
- }
- }
- void menuItem7() { // Function executes when you select the 7th item from main menu
- int activeButton = 0;
- lcd.clear();
- lcd.setCursor(3, 0);
- lcd.print("Sub Menu 7");
- while (activeButton == 0) {
- int button;
- //readKey = analogRead(0);
- //if (readKey < 790) {
- // delay(100);
- // readKey = analogRead(0);
- //}
- button = evaluateButton();
- switch (button) {
- case 4: // This case will execute if the "back" button is pressed
- button = 0;
- activeButton = 1;
- break;
- }
- }
- }
- void menuItem8() { // Function executes when you select the 8th item from main menu
- int activeButton = 0;
- lcd.clear();
- lcd.setCursor(3, 0);
- lcd.print("Sub Menu 8");
- while (activeButton == 0) {
- int button;
- //readKey = analogRead(0);
- //if (readKey < 790) {
- // delay(100);
- // readKey = analogRead(0);
- //}
- button = evaluateButton();
- switch (button) {
- case 4: // This case will execute if the "back" button is pressed
- button = 0;
- activeButton = 1;
- break;
- }
- }
- }
- void menuItem9() { // Function executes when you select the 9th item from main menu
- int activeButton = 0;
- lcd.clear();
- lcd.setCursor(3, 0);
- lcd.print("Sub Menu 9");
- while (activeButton == 0) {
- int button;
- //readKey = analogRead(0);
- //if (readKey < 790) {
- // delay(100);
- // readKey = analogRead(0);
- //}
- button = evaluateButton();
- switch (button) {
- case 4: // This case will execute if the "back" button is pressed
- button = 0;
- activeButton = 1;
- break;
- }
- }
- }
- void menuItem10() { // Function executes when you select the 10th item from main menu
- int activeButton = 0;
- lcd.clear();
- lcd.setCursor(3, 0);
- lcd.print("Sub Menu 10");
- while (activeButton == 0) {
- int button;
- //readKey = analogRead(0);
- //if (readKey < 790) {
- // delay(100);
- // readKey = analogRead(0);
- //}
- button = evaluateButton();
- switch (button) {
- case 4: // This case will execute if the "back" button is pressed
- button = 0;
- activeButton = 1;
- break;
- }
- }
- }
Add Comment
Please, Sign In to add comment