skizziks_53

Reddit menu #4 v.99

Apr 4th, 2019
106
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 17.00 KB | None | 0 0
  1. /*
  2.   April 4, 2019
  3.   Adafruit 16x2_LCD+keypad shield example.
  4.  
  5.   Note: this sketch ONLY works with the Adafruit LCD + keypad shield that uses the MPC23017 i2c expander chip.
  6.   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.
  7.  
  8.   It will not work with the generic parallel-LCD and series-resistance button generic shields sold elsewhere online.
  9.  
  10. */
  11.  
  12. // Original head comments below:
  13.  
  14. /***************************************************************************************
  15.     Name    : LCD Button Shield Menu
  16.     Author  : Paul Siewert
  17.     Created : June 14, 2016
  18.     Last Modified: June 14, 2016
  19.     Version : 1.0
  20.     Notes   : This code is for use with an Arduino Uno and LCD/button shield. The
  21.               intent is for anyone to use this program to give them a starting
  22.               program with a fully functional menu with minimal modifications
  23.               required by the user.
  24.     License : This program is free software. You can redistribute it and/or modify
  25.               it under the terms of the GNU General Public License as published by
  26.               the Free Software Foundation, either version 3 of the License, or
  27.               (at your option) any later version.
  28.               This program is distributed in the hope that it will be useful,
  29.               but WITHOUT ANY WARRANTY; without even the implied warranty of
  30.               MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  31.               GNU General Public License for more details.
  32.  ***************************************************************************************/
  33. /*
  34.    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
  35.    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.
  36. */
  37.  
  38.  
  39.  
  40. // --------------------------------------------------- I moved the library declarations to the top...
  41. #include <Wire.h>
  42. // #include <LiquidCrystal.h> ------------------------ don't need this for the Adafruit shield, you only need Wire and the two libs below.
  43. #include <Adafruit_MCP23017.h> //<-------------------- this is a library for the i2c chip that the Adafruit shield uses.
  44. #include <Adafruit_RGBLCDShield.h>
  45.  
  46.  
  47.  
  48.  
  49. // 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
  50. // section of the operateMainMenu() function below. You will also have to add additional void functions (i.e. menuItem11, menuItem12, etc.) to the program.
  51. String menuItems[] = {"ITEM 1", "ITEM 2", "ITEM 3", "ITEM 4", "ITEM 5", "ITEM 6"};
  52.  
  53. // Navigation button variables
  54. int readKey;
  55.  
  56. // Menu control variables
  57. int menuPage = 0;
  58. int maxMenuPages = round(((sizeof(menuItems) / sizeof(String)) / 2) + .5);
  59. int cursorPosition = 0;
  60.  
  61. // Creates 3 custom characters for the menu display
  62. byte downArrow[8] = {
  63.   0b00100, //   *
  64.   0b00100, //   *
  65.   0b00100, //   *
  66.   0b00100, //   *
  67.   0b00100, //   *
  68.   0b10101, // * * *
  69.   0b01110, //  ***
  70.   0b00100  //   *
  71. };
  72.  
  73. byte upArrow[8] = {
  74.   0b00100, //   *
  75.   0b01110, //  ***
  76.   0b10101, // * * *
  77.   0b00100, //   *
  78.   0b00100, //   *
  79.   0b00100, //   *
  80.   0b00100, //   *
  81.   0b00100  //   *
  82. };
  83.  
  84. byte menuCursor[8] = {
  85.   B01000, //  *
  86.   B00100, //   *
  87.   B00010, //    *
  88.   B00001, //     *
  89.   B00010, //    *
  90.   B00100, //   *
  91.   B01000, //  *
  92.   B00000  //
  93. };
  94.  
  95.  
  96. // Setting the LCD shields pins
  97. //LiquidCrystal lcd(8, 9, 4, 5, 6, 7); ------------------------------------------------------ removed.
  98.  
  99. Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield(); //<------------------------------------- This is the Adafruit way.
  100.  
  101.  
  102.  
  103. void setup() {
  104.  
  105.   // Initializes serial communication
  106.   Serial.begin(9600);
  107.  
  108.   // Initializes and clears the LCD screen
  109.   lcd.begin(16, 2);
  110.   lcd.clear();
  111.  
  112.   // Creates the byte for the 3 custom characters
  113.   lcd.createChar(0, menuCursor);
  114.   lcd.createChar(1, upArrow);
  115.   lcd.createChar(2, downArrow);
  116.  
  117.   Serial.println("Exiting setup()"); // ----------------- testing line.
  118. }
  119.  
  120. void loop() {
  121.   mainMenuDraw();
  122.   drawCursor();
  123.   operateMainMenu();
  124. }
  125.  
  126. // 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.
  127. void mainMenuDraw() {
  128.   Serial.print(menuPage);
  129.   lcd.clear();
  130.   lcd.setCursor(1, 0);
  131.   lcd.print(menuItems[menuPage]);
  132.   lcd.setCursor(1, 1);
  133.   lcd.print(menuItems[menuPage + 1]);
  134.   if (menuPage == 0) {
  135.     lcd.setCursor(15, 1);
  136.     lcd.write(byte(2));
  137.   } else if (menuPage > 0 and menuPage < maxMenuPages) {
  138.     lcd.setCursor(15, 1);
  139.     lcd.write(byte(2));
  140.     lcd.setCursor(15, 0);
  141.     lcd.write(byte(1));
  142.   } else if (menuPage == maxMenuPages) {
  143.     lcd.setCursor(15, 0);
  144.     lcd.write(byte(1));
  145.   }
  146. }
  147.  
  148. // When called, this function will erase the current cursor and redraw it based on the cursorPosition and menuPage variables.
  149. void drawCursor() {
  150.   for (int x = 0; x < 2; x++) {     // Erases current cursor
  151.     lcd.setCursor(0, x);
  152.     lcd.print(" ");
  153.   }
  154.  
  155.   // 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
  156.   // 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.
  157.   if (menuPage % 2 == 0) {
  158.     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
  159.       lcd.setCursor(0, 0);
  160.       lcd.write(byte(0));
  161.     }
  162.     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
  163.       lcd.setCursor(0, 1);
  164.       lcd.write(byte(0));
  165.     }
  166.   }
  167.   if (menuPage % 2 != 0) {
  168.     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
  169.       lcd.setCursor(0, 1);
  170.       lcd.write(byte(0));
  171.     }
  172.     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
  173.       lcd.setCursor(0, 0);
  174.       lcd.write(byte(0));
  175.     }
  176.   }
  177. }
  178.  
  179.  
  180. void operateMainMenu() {
  181.   int activeButton = 0; // <------------------------------------- I don't understand why this is put here.
  182.   //                                                              Since it is a local variable, it will get re-declared as value==zero every time this function is called.
  183.   //                                                              It looks like a mistake to me, but then I did not test this sketch on the generic LCD keypad shield.
  184.   while (activeButton == 0) {
  185.     int button;
  186.     //readKey = analogRead(0);
  187.     //if (readKey < 790) {
  188.     //  delay(100);
  189.     //  readKey = analogRead(0);
  190.     //}
  191.     button = evaluateButton(); //<------------------------------ The evaluateButton() function has been changed to get the button press from the Adafruit keypad.
  192.     switch (button) {
  193.       case 0: // When button returns as 0 there is no action taken
  194.         break;
  195.       case 1:  // This case will execute if the "forward" button is pressed
  196.         button = 0;
  197.         switch (cursorPosition) { // The case that is selected here is dependent on which menu page you are on and where the cursor is.
  198.           case 0:
  199.             menuItem1();
  200.             break;
  201.           case 1:
  202.             menuItem2();
  203.             break;
  204.           case 2:
  205.             menuItem3();
  206.             break;
  207.           case 3:
  208.             menuItem4();
  209.             break;
  210.           case 4:
  211.             menuItem5();
  212.             break;
  213.           case 5:
  214.             menuItem6();
  215.             break;
  216.           case 6:
  217.             menuItem7();
  218.             break;
  219.           case 7:
  220.             menuItem8();
  221.             break;
  222.           case 8:
  223.             menuItem9();
  224.             break;
  225.           case 9:
  226.             menuItem10();
  227.             break;
  228.         }
  229.         activeButton = 1;
  230.         mainMenuDraw();
  231.         drawCursor();
  232.         break;
  233.       case 2:
  234.         button = 0;
  235.         if (menuPage == 0) {
  236.           cursorPosition = cursorPosition - 1;
  237.           cursorPosition = constrain(cursorPosition, 0, ((sizeof(menuItems) / sizeof(String)) - 1));
  238.         }
  239.         if (menuPage % 2 == 0 and cursorPosition % 2 == 0) {
  240.           menuPage = menuPage - 1;
  241.           menuPage = constrain(menuPage, 0, maxMenuPages);
  242.         }
  243.  
  244.         if (menuPage % 2 != 0 and cursorPosition % 2 != 0) {
  245.           menuPage = menuPage - 1;
  246.           menuPage = constrain(menuPage, 0, maxMenuPages);
  247.         }
  248.  
  249.         cursorPosition = cursorPosition - 1;
  250.         cursorPosition = constrain(cursorPosition, 0, ((sizeof(menuItems) / sizeof(String)) - 1));
  251.  
  252.         mainMenuDraw();
  253.         drawCursor();
  254.         activeButton = 1;
  255.         break;
  256.       case 3:
  257.         button = 0;
  258.         if (menuPage % 2 == 0 and cursorPosition % 2 != 0) {
  259.           menuPage = menuPage + 1;
  260.           menuPage = constrain(menuPage, 0, maxMenuPages);
  261.         }
  262.  
  263.         if (menuPage % 2 != 0 and cursorPosition % 2 == 0) {
  264.           menuPage = menuPage + 1;
  265.           menuPage = constrain(menuPage, 0, maxMenuPages);
  266.         }
  267.  
  268.         cursorPosition = cursorPosition + 1;
  269.         cursorPosition = constrain(cursorPosition, 0, ((sizeof(menuItems) / sizeof(String)) - 1));
  270.         mainMenuDraw();
  271.         drawCursor();
  272.         activeButton = 1;
  273.         break;
  274.     }
  275.   }
  276. }
  277.  
  278. // This function is called whenever a button press is evaluated.
  279. int evaluateButton() { // The param is removed, since it isn't needed.
  280.   int result = 0;
  281.   /*
  282.      Old code below:
  283.     if (x < 50) {
  284.     result = 1; // right
  285.     } else if (x < 195) {
  286.     result = 2; // up
  287.     } else if (x < 380) {
  288.     result = 3; // down
  289.     } else if (x < 790) {
  290.     result = 4; // left
  291.     }
  292.   */
  293.  
  294.  
  295.   /*
  296.     The Adafruit LCD shield library defines named hex values for the button identification in the Adafruit_RGBLCDShield.h file.
  297.     These are the lines that do that:
  298.     #define BUTTON_UP 0x08
  299.     #define BUTTON_DOWN 0x04
  300.     #define BUTTON_LEFT 0x10
  301.     #define BUTTON_RIGHT 0x02
  302.     #define BUTTON_SELECT 0x01
  303.     You don't need to know numerically what these values are, you just need to compare the [button] value to the named constants above.
  304.   */
  305.   uint8_t x = lcd.readButtons(); // <------------------------------------ This reads the Adafruit LCD buttons.
  306.  
  307.   if (x == BUTTON_RIGHT) {
  308.     result = 1; // right
  309.   } else if (x == BUTTON_UP) {
  310.     result = 2; // up
  311.   } else if (x == BUTTON_DOWN) {
  312.     result = 3; // down
  313.   } else if (x == BUTTON_LEFT) {
  314.     result = 4; // left
  315.   }
  316.   return result;
  317. }
  318.  
  319. // If there are common usage instructions on more than 1 of your menu items you can call this function from the sub
  320. // menus to make things a little more simplified. If you don't have common instructions or verbage on multiple menus
  321. // I would just delete this void. You must also delete the drawInstructions()function calls from your sub menu functions.
  322. void drawInstructions() {
  323.   lcd.setCursor(0, 1); // Set cursor to the bottom line
  324.   lcd.print("Use ");
  325.   lcd.print(byte(1)); // Up arrow
  326.   lcd.print("/");
  327.   lcd.print(byte(2)); // Down arrow
  328.   lcd.print(" buttons");
  329. }
  330.  
  331. void menuItem1() { // Function executes when you select the 1st item from main menu
  332.   int activeButton = 0;
  333.  
  334.   lcd.clear();
  335.   lcd.setCursor(3, 0);
  336.   lcd.print("Sub Menu 1");
  337.  
  338.   while (activeButton == 0) {
  339.     int button;
  340.     //readKey = analogRead(0);
  341.     //if (readKey < 790) {
  342.     //  delay(100);
  343.     //  readKey = analogRead(0);
  344.     //}
  345.     button = evaluateButton();
  346.     switch (button) {
  347.       case 4:  // This case will execute if the "back" button is pressed
  348.         button = 0;
  349.         activeButton = 1;
  350.         break;
  351.     }
  352.   }
  353. }
  354.  
  355. void menuItem2() { // Function executes when you select the 2nd item from main menu
  356.   int activeButton = 0;
  357.  
  358.   lcd.clear();
  359.   lcd.setCursor(3, 0);
  360.   lcd.print("Sub Menu 2");
  361.  
  362.   while (activeButton == 0) {
  363.     int button;
  364.     //readKey = analogRead(0);
  365.     //if (readKey < 790) {
  366.     //  delay(100);
  367.     //  readKey = analogRead(0);
  368.     //}
  369.     button = evaluateButton();
  370.     switch (button) {
  371.       case 4:  // This case will execute if the "back" button is pressed
  372.         button = 0;
  373.         activeButton = 1;
  374.         break;
  375.     }
  376.   }
  377. }
  378.  
  379. void menuItem3() { // Function executes when you select the 3rd item from main menu
  380.   int activeButton = 0;
  381.  
  382.   lcd.clear();
  383.   lcd.setCursor(3, 0);
  384.   lcd.print("Sub Menu 3");
  385.  
  386.   while (activeButton == 0) {
  387.     int button;
  388.     //readKey = analogRead(0);
  389.     //if (readKey < 790) {
  390.     //  delay(100);
  391.     //  readKey = analogRead(0);
  392.     //}
  393.     button = evaluateButton();
  394.     switch (button) {
  395.       case 4:  // This case will execute if the "back" button is pressed
  396.         button = 0;
  397.         activeButton = 1;
  398.         break;
  399.     }
  400.   }
  401. }
  402.  
  403. void menuItem4() { // Function executes when you select the 4th item from main menu
  404.   int activeButton = 0;
  405.  
  406.   lcd.clear();
  407.   lcd.setCursor(3, 0);
  408.   lcd.print("Sub Menu 4");
  409.  
  410.   while (activeButton == 0) {
  411.     int button;
  412.     //readKey = analogRead(0);
  413.     //if (readKey < 790) {
  414.     //  delay(100);
  415.     //  readKey = analogRead(0);
  416.     //}
  417.     button = evaluateButton();
  418.     switch (button) {
  419.       case 4:  // This case will execute if the "back" button is pressed
  420.         button = 0;
  421.         activeButton = 1;
  422.         break;
  423.     }
  424.   }
  425. }
  426.  
  427. void menuItem5() { // Function executes when you select the 5th item from main menu
  428.   int activeButton = 0;
  429.  
  430.   lcd.clear();
  431.   lcd.setCursor(3, 0);
  432.   lcd.print("Sub Menu 5");
  433.  
  434.   while (activeButton == 0) {
  435.     int button;
  436.     //readKey = analogRead(0);
  437.     //if (readKey < 790) {
  438.     //  delay(100);
  439.     //  readKey = analogRead(0);
  440.     //}
  441.     button = evaluateButton();
  442.     switch (button) {
  443.       case 4:  // This case will execute if the "back" button is pressed
  444.         button = 0;
  445.         activeButton = 1;
  446.         break;
  447.     }
  448.   }
  449. }
  450.  
  451. void menuItem6() { // Function executes when you select the 6th item from main menu
  452.   int activeButton = 0;
  453.  
  454.   lcd.clear();
  455.   lcd.setCursor(3, 0);
  456.   lcd.print("Sub Menu 6");
  457.  
  458.   while (activeButton == 0) {
  459.     int button;
  460.     //readKey = analogRead(0);
  461.     //if (readKey < 790) {
  462.     //  delay(100);
  463.     //  readKey = analogRead(0);
  464.     //}
  465.     button = evaluateButton();
  466.     switch (button) {
  467.       case 4:  // This case will execute if the "back" button is pressed
  468.         button = 0;
  469.         activeButton = 1;
  470.         break;
  471.     }
  472.   }
  473. }
  474.  
  475. void menuItem7() { // Function executes when you select the 7th item from main menu
  476.   int activeButton = 0;
  477.  
  478.   lcd.clear();
  479.   lcd.setCursor(3, 0);
  480.   lcd.print("Sub Menu 7");
  481.  
  482.   while (activeButton == 0) {
  483.     int button;
  484.     //readKey = analogRead(0);
  485.     //if (readKey < 790) {
  486.     //  delay(100);
  487.     //  readKey = analogRead(0);
  488.     //}
  489.     button = evaluateButton();
  490.     switch (button) {
  491.       case 4:  // This case will execute if the "back" button is pressed
  492.         button = 0;
  493.         activeButton = 1;
  494.         break;
  495.     }
  496.   }
  497. }
  498.  
  499. void menuItem8() { // Function executes when you select the 8th item from main menu
  500.   int activeButton = 0;
  501.  
  502.   lcd.clear();
  503.   lcd.setCursor(3, 0);
  504.   lcd.print("Sub Menu 8");
  505.  
  506.   while (activeButton == 0) {
  507.     int button;
  508.     //readKey = analogRead(0);
  509.     //if (readKey < 790) {
  510.     //  delay(100);
  511.     //  readKey = analogRead(0);
  512.     //}
  513.     button = evaluateButton();
  514.     switch (button) {
  515.       case 4:  // This case will execute if the "back" button is pressed
  516.         button = 0;
  517.         activeButton = 1;
  518.         break;
  519.     }
  520.   }
  521. }
  522.  
  523. void menuItem9() { // Function executes when you select the 9th item from main menu
  524.   int activeButton = 0;
  525.  
  526.   lcd.clear();
  527.   lcd.setCursor(3, 0);
  528.   lcd.print("Sub Menu 9");
  529.  
  530.   while (activeButton == 0) {
  531.     int button;
  532.     //readKey = analogRead(0);
  533.     //if (readKey < 790) {
  534.     //  delay(100);
  535.     //  readKey = analogRead(0);
  536.     //}
  537.     button = evaluateButton();
  538.     switch (button) {
  539.       case 4:  // This case will execute if the "back" button is pressed
  540.         button = 0;
  541.         activeButton = 1;
  542.         break;
  543.     }
  544.   }
  545. }
  546.  
  547. void menuItem10() { // Function executes when you select the 10th item from main menu
  548.   int activeButton = 0;
  549.  
  550.   lcd.clear();
  551.   lcd.setCursor(3, 0);
  552.   lcd.print("Sub Menu 10");
  553.  
  554.   while (activeButton == 0) {
  555.     int button;
  556.     //readKey = analogRead(0);
  557.     //if (readKey < 790) {
  558.     //  delay(100);
  559.     //  readKey = analogRead(0);
  560.     //}
  561.     button = evaluateButton();
  562.     switch (button) {
  563.       case 4:  // This case will execute if the "back" button is pressed
  564.         button = 0;
  565.         activeButton = 1;
  566.         break;
  567.     }
  568.   }
  569. }
Add Comment
Please, Sign In to add comment