learnelectronics

LCD Keypad Shield Menu System

Sep 19th, 2017
16,597
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.  * LCD Keypad Shield Menu System
  3.  *
  4.  * learnelectronics
  5.  * 18 Sept 2017
  6.  * adapted from an original sketch by Paul Siewert
  7.  *
  8.  * www.youtube.com/c/learnelectronics
  9.  * arduino0169@gmail.com
  10.  *
  11.  */
  12.  
  13. // 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
  14. // section of the operateMainMenu() function below. You will also have to add additional void functions (i.e. menuItem11, menuItem12, etc.) to the program.
  15. String menuItems[] = {"Yellow", "Green", "Red", "Purple"};
  16.  
  17. // Navigation button variables
  18. int readKey;
  19. int savedDistance = 0;
  20.  
  21. // Menu control variables
  22. int menuPage = 0;
  23. int maxMenuPages = round(((sizeof(menuItems) / sizeof(String)) / 2) + .5);
  24. int cursorPosition = 0;
  25.  
  26. // Creates 3 custom characters for the menu display
  27. byte downArrow[8] = {
  28.   0b00100, //   *
  29.   0b00100, //   *
  30.   0b00100, //   *
  31.   0b00100, //   *
  32.   0b00100, //   *
  33.   0b10101, // * * *
  34.   0b01110, //  ***
  35.   0b00100  //   *
  36. };
  37.  
  38. byte upArrow[8] = {
  39.   0b00100, //   *
  40.   0b01110, //  ***
  41.   0b10101, // * * *
  42.   0b00100, //   *
  43.   0b00100, //   *
  44.   0b00100, //   *
  45.   0b00100, //   *
  46.   0b00100  //   *
  47. };
  48.  
  49. byte menuCursor[8] = {
  50.   B01000, //  *
  51.   B00100, //   *
  52.   B00010, //    *
  53.   B00001, //     *
  54.   B00010, //    *
  55.   B00100, //   *
  56.   B01000, //  *
  57.   B00000  //
  58. };
  59.  
  60. #include <Wire.h>
  61. #include <LiquidCrystal.h>
  62.  
  63. // Setting the LCD shields pins
  64. LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
  65.  
  66. void setup() {
  67.  
  68.   // Initializes serial communication
  69.   Serial.begin(9600);
  70.  
  71.   // Initializes and clears the LCD screen
  72.   lcd.begin(16, 2);
  73.   lcd.clear();
  74.  
  75.   // Creates the byte for the 3 custom characters
  76.   lcd.createChar(0, menuCursor);
  77.   lcd.createChar(1, upArrow);
  78.   lcd.createChar(2, downArrow);
  79.  
  80.   pinMode(13,OUTPUT);
  81.   pinMode(12,OUTPUT);
  82.   pinMode(11,OUTPUT);
  83.   pinMode(3,OUTPUT);
  84.  
  85. }
  86.  
  87. void loop() {
  88.   mainMenuDraw();
  89.   drawCursor();
  90.   operateMainMenu();
  91. }
  92.  
  93. // 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.
  94. void mainMenuDraw() {
  95.   Serial.print(menuPage);
  96.   lcd.clear();
  97.   lcd.setCursor(1, 0);
  98.   lcd.print(menuItems[menuPage]);
  99.   lcd.setCursor(1, 1);
  100.   lcd.print(menuItems[menuPage + 1]);
  101.   if (menuPage == 0) {
  102.     lcd.setCursor(15, 1);
  103.     lcd.write(byte(2));
  104.   } else if (menuPage > 0 and menuPage < maxMenuPages) {
  105.     lcd.setCursor(15, 1);
  106.     lcd.write(byte(2));
  107.     lcd.setCursor(15, 0);
  108.     lcd.write(byte(1));
  109.   } else if (menuPage == maxMenuPages) {
  110.     lcd.setCursor(15, 0);
  111.     lcd.write(byte(1));
  112.   }
  113. }
  114.  
  115. // When called, this function will erase the current cursor and redraw it based on the cursorPosition and menuPage variables.
  116. void drawCursor() {
  117.   for (int x = 0; x < 2; x++) {     // Erases current cursor
  118.     lcd.setCursor(0, x);
  119.     lcd.print(" ");
  120.   }
  121.  
  122.   // 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
  123.   // 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.
  124.   if (menuPage % 2 == 0) {
  125.     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
  126.       lcd.setCursor(0, 0);
  127.       lcd.write(byte(0));
  128.     }
  129.     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
  130.       lcd.setCursor(0, 1);
  131.       lcd.write(byte(0));
  132.     }
  133.   }
  134.   if (menuPage % 2 != 0) {
  135.     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
  136.       lcd.setCursor(0, 1);
  137.       lcd.write(byte(0));
  138.     }
  139.     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
  140.       lcd.setCursor(0, 0);
  141.       lcd.write(byte(0));
  142.     }
  143.   }
  144. }
  145.  
  146.  
  147. void operateMainMenu() {
  148.   int activeButton = 0;
  149.   while (activeButton == 0) {
  150.     int button;
  151.     readKey = analogRead(0);
  152.     if (readKey < 790) {
  153.       delay(100);
  154.       readKey = analogRead(0);
  155.     }
  156.     button = evaluateButton(readKey);
  157.     switch (button) {
  158.       case 0: // When button returns as 0 there is no action taken
  159.         break;
  160.       case 1:  // This case will execute if the "forward" button is pressed
  161.         button = 0;
  162.         switch (cursorPosition) { // The case that is selected here is dependent on which menu page you are on and where the cursor is.
  163.           case 0:
  164.             menuItem1();
  165.             break;
  166.           case 1:
  167.             menuItem2();
  168.             break;
  169.           case 2:
  170.             menuItem3();
  171.             break;
  172.           case 3:
  173.             menuItem4();
  174.             break;
  175.          
  176.         }
  177.         activeButton = 1;
  178.         mainMenuDraw();
  179.         drawCursor();
  180.         break;
  181.       case 2:
  182.         button = 0;
  183.         if (menuPage == 0) {
  184.           cursorPosition = cursorPosition - 1;
  185.           cursorPosition = constrain(cursorPosition, 0, ((sizeof(menuItems) / sizeof(String)) - 1));
  186.         }
  187.         if (menuPage % 2 == 0 and cursorPosition % 2 == 0) {
  188.           menuPage = menuPage - 1;
  189.           menuPage = constrain(menuPage, 0, maxMenuPages);
  190.         }
  191.  
  192.         if (menuPage % 2 != 0 and cursorPosition % 2 != 0) {
  193.           menuPage = menuPage - 1;
  194.           menuPage = constrain(menuPage, 0, maxMenuPages);
  195.         }
  196.  
  197.         cursorPosition = cursorPosition - 1;
  198.         cursorPosition = constrain(cursorPosition, 0, ((sizeof(menuItems) / sizeof(String)) - 1));
  199.  
  200.         mainMenuDraw();
  201.         drawCursor();
  202.         activeButton = 1;
  203.         break;
  204.       case 3:
  205.         button = 0;
  206.         if (menuPage % 2 == 0 and cursorPosition % 2 != 0) {
  207.           menuPage = menuPage + 1;
  208.           menuPage = constrain(menuPage, 0, maxMenuPages);
  209.         }
  210.  
  211.         if (menuPage % 2 != 0 and cursorPosition % 2 == 0) {
  212.           menuPage = menuPage + 1;
  213.           menuPage = constrain(menuPage, 0, maxMenuPages);
  214.         }
  215.  
  216.         cursorPosition = cursorPosition + 1;
  217.         cursorPosition = constrain(cursorPosition, 0, ((sizeof(menuItems) / sizeof(String)) - 1));
  218.         mainMenuDraw();
  219.         drawCursor();
  220.         activeButton = 1;
  221.         break;
  222.     }
  223.   }
  224. }
  225.  
  226. // 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.
  227. int evaluateButton(int x) {
  228.   int result = 0;
  229.   if (x < 50) {
  230.     result = 1; // right
  231.   } else if (x < 195) {
  232.     result = 2; // up
  233.   } else if (x < 380) {
  234.     result = 3; // down
  235.   } else if (x < 790) {
  236.     result = 4; // left
  237.   }
  238.   return result;
  239. }
  240.  
  241. // If there are common usage instructions on more than 1 of your menu items you can call this function from the sub
  242. // menus to make things a little more simplified. If you don't have common instructions or verbage on multiple menus
  243. // I would just delete this void. You must also delete the drawInstructions()function calls from your sub menu functions.
  244. void drawInstructions() {
  245.   lcd.setCursor(0, 1); // Set cursor to the bottom line
  246.   lcd.print("Use ");
  247.   lcd.write(byte(1)); // Up arrow
  248.   lcd.print("/");
  249.   lcd.write(byte(2)); // Down arrow
  250.   lcd.print(" buttons");
  251. }
  252.  
  253. void menuItem1() { // Function executes when you select the Yellow item from main menu
  254.   int activeButton = 0;
  255.  
  256.   lcd.clear();
  257.   lcd.setCursor(3, 0);
  258.   lcd.print("Yellow On");
  259.  
  260.   digitalWrite(13,HIGH);
  261.  
  262.   while (activeButton == 0) {
  263.     int button;
  264.     readKey = analogRead(0);
  265.     if (readKey < 790) {
  266.       delay(100);
  267.       readKey = analogRead(0);
  268.     }
  269.     button = evaluateButton(readKey);
  270.     switch (button) {
  271.       case 4:  // This case will execute if the "back" button is pressed
  272.         button = 0;
  273.         activeButton = 1;
  274.         digitalWrite(13,LOW);
  275.         break;
  276.     }
  277.   }
  278. }
  279.  
  280. void menuItem2() { // Function executes when you select the Green item from main menu
  281.   int activeButton = 0;
  282.  
  283.   lcd.clear();
  284.   lcd.setCursor(3, 0);
  285.   lcd.print("Green On");
  286.  
  287.   digitalWrite(12,HIGH);
  288.  
  289.   while (activeButton == 0) {
  290.     int button;
  291.     readKey = analogRead(0);
  292.     if (readKey < 790) {
  293.       delay(100);
  294.       readKey = analogRead(0);
  295.     }
  296.     button = evaluateButton(readKey);
  297.     switch (button) {
  298.       case 4:  // This case will execute if the "back" button is pressed
  299.         button = 0;
  300.         activeButton = 1;
  301.         digitalWrite(12,LOW);
  302.         break;
  303.     }
  304.   }
  305. }
  306.  
  307. void menuItem3() { // Function executes when you select the Red item from main menu
  308.   int activeButton = 0;
  309.  
  310.   lcd.clear();
  311.   lcd.setCursor(3, 0);
  312.   lcd.print("Red On");
  313.  
  314.   digitalWrite(11,HIGH);
  315.  
  316.   while (activeButton == 0) {
  317.     int button;
  318.     readKey = analogRead(0);
  319.     if (readKey < 790) {
  320.       delay(100);
  321.       readKey = analogRead(0);
  322.     }
  323.     button = evaluateButton(readKey);
  324.     switch (button) {
  325.       case 4:  // This case will execute if the "back" button is pressed
  326.         button = 0;
  327.         activeButton = 1;
  328.         digitalWrite(11,LOW);
  329.         break;
  330.     }
  331.   }
  332. }
  333.  
  334. void menuItem4() { // Function executes when you select the Purple item from main menu
  335.   int activeButton = 0;
  336.  
  337.   lcd.clear();
  338.   lcd.setCursor(3, 0);
  339.   lcd.print("Purple On");
  340.  
  341.   digitalWrite(3,HIGH);
  342.  
  343.   while (activeButton == 0) {
  344.     int button;
  345.     readKey = analogRead(0);
  346.     if (readKey < 790) {
  347.       delay(100);
  348.       readKey = analogRead(0);
  349.     }
  350.     button = evaluateButton(readKey);
  351.     switch (button) {
  352.       case 4:  // This case will execute if the "back" button is pressed
  353.         button = 0;
  354.         activeButton = 1;
  355.         digitalWrite(3,LOW);
  356.         break;
  357.     }
  358.   }
  359. }
RAW Paste Data