Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*********************
- Generic 16x2_LCD+keypad shield example.
- 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.
- The LCD is connected in 4-bit parallel and the buttons are series resistance on pin A0.
- The shield fits on an Uno, which is what I tested it on. I don't know if it will work on a Mega.
- To set up the shield I used the info on this web page:
- https://www.thomasclausen.net/en/walking-through-the-1602-lcd-keypad-shield-for-arduino/
- This sketch displays a two-level menu, and allows selecting choices from each sub-menu.
- 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).
- 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").
- It is kinda long due to the strings used.
- **********************/
- // Libraries used:
- #include <Wire.h>
- #include <LiquidCrystal.h>
- LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
- // Below is defining values for the different buttons.
- #define btnRIGHT 0
- #define btnUP 1
- #define btnDOWN 2
- #define btnLEFT 3
- #define btnSELECT 4
- #define btnNONE 5
- #define btnUNKNOWN 6
- String top_level_menu[] = {"cars", "trees", "countries", "colors"};
- int top_level_selection = 0; // This value is zero to 3, representing the four possible choices in top_level_menu[]
- int max_top_level_selection = 3; // This defines the maximum value that top_level_selection can be allowed to go to.
- String secondary_menu_0[] = {"ford", "chevy", "mazda", "nissan", "saab"};
- String secondary_menu_1[] = {"oak", "elm", "walnut", "cherry"};
- String secondary_menu_2[] = {"canada", "brazil", "japan"};
- String secondary_menu_3[] = {"red", "yellow", "orange", "green", "blue", "purple", "brown", "black"};
- int subMenu_selections[] = {0, 0, 0, 0}; // These are for storing the four sub-menu selections.
- int maximum_submenu_selections[] = {4, 3, 2, 7}; // This defines the maximum sub-menu level, based on what sub-menu menu is selected.
- // The value of top_level_selection will be used as an indice into these two arrays.
- void setup() {
- Serial.begin(9600);
- // set up the LCD's number of columns and rows:
- lcd.begin(16, 2);
- show_menu_selection(); // Show where the menu is currently set (to group=zero and choice=zero).
- Serial.println("Exiting setup()");
- }
- uint8_t i = 0; // I dunno why Adafruit used a short here to store the button ID in, but that's what they did.
- void loop() {
- int buttons = readkeypad();
- if (buttons < btnNONE) {
- // The up and down buttons scroll through the sub-menu choices.
- if (buttons == btnUP) {
- if (subMenu_selections[top_level_selection] > 0) {
- subMenu_selections[top_level_selection] = subMenu_selections[top_level_selection] - 1;
- }
- show_menu_selection();
- }
- if (buttons == btnDOWN) {
- if (subMenu_selections[top_level_selection] < maximum_submenu_selections[top_level_selection]) {
- subMenu_selections[top_level_selection] = subMenu_selections[top_level_selection] + 1;
- }
- show_menu_selection();
- }
- // The left and right buttons scroll through the top-level choices.
- if (buttons == btnLEFT) {
- if (top_level_selection > 0) {
- top_level_selection = top_level_selection - 1;
- }
- show_menu_selection();
- }
- if (buttons == btnRIGHT) {
- if (top_level_selection < max_top_level_selection) {
- top_level_selection = top_level_selection + 1;
- }
- show_menu_selection();
- }
- // The [select] button resets all the choices back to the first option.
- if (buttons == btnSELECT) {
- top_level_selection = 0;
- subMenu_selections[0] = 0;
- subMenu_selections[1] = 0;
- subMenu_selections[2] = 0;
- subMenu_selections[3] = 0;
- show_menu_selection();
- }
- buttons = btnUNKNOWN; // reset the button value, so it does not get re-used twice.
- delay(300); // This is done to de-bounce the buttons as I was getting some repeating without it.
- }
- }
- void show_menu_selection() {
- // The four lines below print the top line of the LCD display.
- clear_top_LCD_line();
- lcd.setCursor(0, 0); // the first line is numbered zero, and first character spot is numbered zero.
- lcd.print("group=");
- lcd.setCursor(6, 0);
- lcd.print(top_level_menu[top_level_selection]); // This prints the group that you are selecting from.
- // The lines below print the second line of the LCD display.
- clear_button_LCD_line();
- lcd.setCursor(0, 1);
- lcd.print("choice=");
- lcd.setCursor(7, 1);
- switch (top_level_selection) {
- case 0:
- lcd.print(secondary_menu_0[subMenu_selections[top_level_selection]]);
- break;
- case 1:
- lcd.print(secondary_menu_1[subMenu_selections[top_level_selection]]);
- break;
- case 2:
- lcd.print(secondary_menu_2[subMenu_selections[top_level_selection]]);
- break;
- case 3:
- lcd.print(secondary_menu_3[subMenu_selections[top_level_selection]]);
- break;
- }
- }
- void clear_top_LCD_line() {
- // This just prints spaces over the whole upper LCD line, to clear it out.
- // With these LCDs, the character you put into any one spot stays there until you print a [space] over it.
- lcd.setCursor(0, 0);
- lcd.print(" "); // This is printing sixteen spaces in the first (top) LCD line.
- }
- void clear_button_LCD_line() {
- // This just prints spaces over the whole lower LCD line, to clear it out.
- lcd.setCursor(0, 1);
- lcd.print(" "); // This is printing sixteen spaces in the second (lower) LCD line.
- }
- int readkeypad() {
- // This function is for getting the button input, if any.
- int adc_key_in = analogRead(0); //
- int ret = btnUNKNOWN;
- /*
- The original code below (from the thomasclausen.net web page) didn't work for my shield.
- if (adc_key_in < 50) ret = btnRIGHT;
- if ((adc_key_in > 500) && (adc_key_in < 1150)) ret = btnNONE;
- if ( (adc_key_in > 120) && (adc_key_in < 150) ) ret = btnUP;
- if ( (adc_key_in > 250) && (adc_key_in < 350) ) ret = btnDOWN;
- if ( (adc_key_in > 450) && (adc_key_in < 500) ) ret = btnLEFT;
- if ( (adc_key_in > 700) && (adc_key_in < 750) ) ret = btnSELECT;
- */
- // 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.
- // right = 0
- // up = 99
- // down = 256
- // left = 408
- // select = 639
- // no buttons pressed = 1023
- // Below is the modified values that worked for my shield.
- if (adc_key_in < 20) ret = btnRIGHT;
- if ( (adc_key_in > 50) && (adc_key_in < 150) ) ret = btnUP;
- if ( (adc_key_in > 200) && (adc_key_in < 300) ) ret = btnDOWN;
- if ( (adc_key_in > 350) && (adc_key_in < 450) ) ret = btnLEFT;
- if ( (adc_key_in > 550) && (adc_key_in < 750) ) ret = btnSELECT;
- if ((adc_key_in > 1000) && (adc_key_in < 1100)) ret = btnNONE;
- return ret;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement