Advertisement
skizziks_53

Generic 16x2 LCD+keypad shield menu v1.0

Apr 3rd, 2019
369
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.07 KB | None | 0 0
  1. /*********************
  2.  
  3.   Generic 16x2_LCD+keypad shield example.
  4.  
  5.   Note: this sketch ONLY works with the generic LCD + keypad shield that does not use the MPC23017 i2c expander chip. This sketch will not work with the Adafruit shield.
  6.   The LCD is connected in 4-bit parallel and the buttons are series resistance on pin A0.
  7.  
  8.   The shield fits on an Uno, which is what I tested it on. I don't know if it will work on a Mega.
  9.  
  10.   To set up the shield I used the info on this web page:
  11.   https://www.thomasclausen.net/en/walking-through-the-1602-lcd-keypad-shield-for-arduino/
  12.  
  13.   This sketch displays a two-level menu, and allows selecting choices from each sub-menu.
  14.   The sub-menu choices persist, because you can scroll left-and-right, and they remain where you left them (they are stored in the subMenu_selections[] array).
  15.  
  16.   When you press the [select] button, that re-sets all the menu choices back to the zero position, and displays the result (at the #zero menu, which is "cars").
  17.   It is kinda long due to the strings used.
  18.  
  19.  **********************/
  20.  
  21. // Libraries used:
  22. #include <Wire.h>
  23. #include <LiquidCrystal.h>
  24.  
  25. LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
  26.  
  27. // Below is defining values for the different buttons.
  28. #define btnRIGHT 0
  29. #define btnUP 1
  30. #define btnDOWN 2
  31. #define btnLEFT 3
  32. #define btnSELECT 4
  33. #define btnNONE 5
  34. #define btnUNKNOWN 6
  35.  
  36. String top_level_menu[] = {"cars", "trees", "countries", "colors"};
  37. int top_level_selection = 0; // This value is zero to 3, representing the four possible choices in top_level_menu[]
  38. int max_top_level_selection = 3; // This defines the maximum value that top_level_selection can be allowed to go to.
  39.  
  40. String secondary_menu_0[] = {"ford", "chevy", "mazda", "nissan", "saab"};
  41. String secondary_menu_1[] = {"oak", "elm", "walnut", "cherry"};
  42. String secondary_menu_2[] = {"canada", "brazil", "japan"};
  43. String secondary_menu_3[] = {"red", "yellow", "orange", "green", "blue", "purple", "brown", "black"};
  44.  
  45. int subMenu_selections[] = {0, 0, 0, 0}; // These are for storing the four sub-menu selections.
  46. int maximum_submenu_selections[] = {4, 3, 2, 7}; // This defines the maximum sub-menu level, based on what sub-menu menu is selected.
  47. // The value of top_level_selection will be used as an indice into these two arrays.
  48.  
  49.  
  50. void setup() {
  51.   Serial.begin(9600);
  52.   // set up the LCD's number of columns and rows:
  53.   lcd.begin(16, 2);
  54.  
  55.   show_menu_selection(); // Show where the menu is currently set (to group=zero and choice=zero).
  56.  
  57.   Serial.println("Exiting setup()");
  58. }
  59.  
  60. uint8_t i = 0; // I dunno why Adafruit used a short here to store the button ID in, but that's what they did.
  61.  
  62. void loop() {
  63.   int buttons = readkeypad();
  64.   if (buttons < btnNONE) {
  65.  
  66.     // The up and down buttons scroll through the sub-menu choices.
  67.     if (buttons == btnUP) {
  68.       if (subMenu_selections[top_level_selection] > 0) {
  69.         subMenu_selections[top_level_selection] = subMenu_selections[top_level_selection] - 1;
  70.       }
  71.       show_menu_selection();
  72.     }
  73.  
  74.     if (buttons == btnDOWN) {
  75.       if (subMenu_selections[top_level_selection] < maximum_submenu_selections[top_level_selection]) {
  76.         subMenu_selections[top_level_selection] = subMenu_selections[top_level_selection] + 1;
  77.       }
  78.       show_menu_selection();
  79.     }
  80.  
  81.  
  82.  
  83.     // The left and right buttons scroll through the top-level choices.
  84.     if (buttons == btnLEFT) {
  85.       if (top_level_selection > 0) {
  86.         top_level_selection = top_level_selection - 1;
  87.       }
  88.       show_menu_selection();
  89.     }
  90.  
  91.     if (buttons == btnRIGHT) {
  92.       if (top_level_selection < max_top_level_selection) {
  93.         top_level_selection = top_level_selection + 1;
  94.       }
  95.       show_menu_selection();
  96.     }
  97.  
  98.  
  99.     // The [select] button resets all the choices back to the first option.
  100.     if (buttons == btnSELECT) {
  101.       top_level_selection = 0;
  102.       subMenu_selections[0] = 0;
  103.       subMenu_selections[1] = 0;
  104.       subMenu_selections[2] = 0;
  105.       subMenu_selections[3] = 0;
  106.       show_menu_selection();
  107.     }
  108.  
  109.     buttons = btnUNKNOWN; // reset the button value, so it does not get re-used twice.
  110.     delay(300); // This is done to de-bounce the buttons as I was getting some repeating without it.
  111.   }
  112. }
  113.  
  114.  
  115. void show_menu_selection() {
  116.   // The four lines below print the top line of the LCD display.
  117.   clear_top_LCD_line();
  118.   lcd.setCursor(0, 0); // the first line is numbered zero, and first character spot is numbered zero.
  119.   lcd.print("group=");
  120.   lcd.setCursor(6, 0);
  121.   lcd.print(top_level_menu[top_level_selection]); // This prints the group that you are selecting from.
  122.  
  123.   // The lines below print the second line of the LCD display.
  124.   clear_button_LCD_line();
  125.   lcd.setCursor(0, 1);
  126.   lcd.print("choice=");
  127.   lcd.setCursor(7, 1);
  128.   switch (top_level_selection) {
  129.     case 0:
  130.       lcd.print(secondary_menu_0[subMenu_selections[top_level_selection]]);
  131.       break;
  132.     case 1:
  133.       lcd.print(secondary_menu_1[subMenu_selections[top_level_selection]]);
  134.       break;
  135.     case 2:
  136.       lcd.print(secondary_menu_2[subMenu_selections[top_level_selection]]);
  137.       break;
  138.     case 3:
  139.       lcd.print(secondary_menu_3[subMenu_selections[top_level_selection]]);
  140.       break;
  141.   }
  142. }
  143.  
  144. void clear_top_LCD_line() {
  145.   // This just prints spaces over the whole upper LCD line, to clear it out.
  146.   // With these LCDs, the character you put into any one spot stays there until you print a [space] over it.
  147.   lcd.setCursor(0, 0);
  148.   lcd.print("                "); // This is printing sixteen spaces in the first (top) LCD line.
  149. }
  150.  
  151. void clear_button_LCD_line() {
  152.   // This just prints spaces over the whole lower LCD line, to clear it out.
  153.   lcd.setCursor(0, 1);
  154.   lcd.print("                "); // This is printing sixteen spaces in the second (lower) LCD line.
  155. }
  156.  
  157. int readkeypad() {
  158.   // This function is for getting the button input, if any.
  159.   int adc_key_in = analogRead(0); //
  160.   int ret = btnUNKNOWN;
  161.   /*
  162.      The original code below (from the thomasclausen.net web page) didn't work for my shield.
  163.     if (adc_key_in < 50) ret = btnRIGHT;
  164.     if ((adc_key_in > 500) && (adc_key_in < 1150)) ret = btnNONE;
  165.     if ( (adc_key_in > 120) && (adc_key_in < 150) ) ret = btnUP;
  166.     if ( (adc_key_in > 250) && (adc_key_in < 350) ) ret = btnDOWN;
  167.     if ( (adc_key_in > 450) && (adc_key_in < 500) ) ret = btnLEFT;
  168.     if ( (adc_key_in > 700) && (adc_key_in < 750) ) ret = btnSELECT;
  169.   */
  170.   // I had to measure my shield with a sketch, using the analogRead() function, while pressing each of the buttons to see what value it would give.
  171.   // right = 0
  172.   // up = 99
  173.   // down = 256
  174.   // left = 408
  175.   // select = 639
  176.   // no buttons pressed = 1023
  177.  
  178.   // Below is the modified values that worked for my shield.
  179.   if (adc_key_in < 20) ret = btnRIGHT;
  180.   if ( (adc_key_in > 50) && (adc_key_in < 150) ) ret = btnUP;
  181.   if ( (adc_key_in > 200) && (adc_key_in < 300) ) ret = btnDOWN;
  182.   if ( (adc_key_in > 350) && (adc_key_in < 450) ) ret = btnLEFT;
  183.   if ( (adc_key_in > 550) && (adc_key_in < 750) ) ret = btnSELECT;
  184.   if ((adc_key_in > 1000) && (adc_key_in < 1100)) ret = btnNONE;
  185.  
  186.   return ret;
  187. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement