Netduino home hardware projects downloads community

Jump to content


The Netduino forums have been replaced by new forums at community.wildernesslabs.co. This site has been preserved for archival purposes only and the ability to make new accounts or posts has been turned off.
Photo

2x16 LCD Menu Class ?


  • Please log in to reply
6 replies to this topic

#1 Steve Hall

Steve Hall

    Member

  • Members
  • PipPip
  • 26 posts

Posted 09 February 2011 - 11:23 AM

Hi,

I've managed to get an DF Robot LCD Keypad working with the netduinoso I have a 2 x 16 LCD screen and 5 buttons (nominally Up, Down, Left, Right and Select).

I'm wondering if there already has been Menu system built for a 2x16 or one that can be adapted. (I've searched and found little).

I'm happy to have a go building one ... but I've can't recall any 2-line menu system that I'd like to emulate.

Any suggestions on style or good working examples greatly appreciated.

Thanks

#2 Thomas

Thomas

    Member

  • Members
  • PipPip
  • 15 posts
  • LocationDenmark

Posted 15 February 2011 - 01:31 PM

Hi Steve, One option to emulate or get inspiration from could be the menu system used in the older HP laser printers... I'm going to do something similar on a little Arduino based board (http://www.hackmeist...cd-io-backpack/), but with only up, down and select (http://www.sparkfun.com/products/8184). /Thomas

#3 Steve Hall

Steve Hall

    Member

  • Members
  • PipPip
  • 26 posts

Posted 17 February 2011 - 12:37 AM

Hi Steve,

One option to emulate or get inspiration from could be the menu system used in the older HP laser printers...

I'm going to do something similar on a little Arduino based board (http://www.hackmeist...cd-io-backpack/), but with only up, down and select (http://www.sparkfun.com/products/8184).

/Thomas

Thomas ... I recall the old HP printers. Seem to remember that they had Up, Down, Select and a Cancel button as well.

Anyhow, I think I'll be implementing a very similar thing.

If I use a menu structure that contains

<MenuTag>
<Menutext>
<ParentTag>

and store these in an array. Then have the buttons do the following:
[Left] or [Right] Move along the array for next item with same ParentTag
[Up] or [Down] Move back to the array item that is in ParentTag (Top menu has no ParentTag so stay there)

[Select] Move to 1st menu item that has MenuTag as it's ParentTag. If not found then you are at the bottom level of the menu so Raise a menuSelectedEvent passing back MenuTag

So the menus can be as deep and wide as you want. All that is required in your own code is to handle the menSelectedEvent where you have a Switch statement that can be used to call the appropriate process based on the menuReturned evant args.

Here is the 1st cut of the code
class Winder :IDisposable
    {
        // Constants for timer operations
        const int KEY_TIMEOUT = 200; // Milliseconds between menu operations
        const int TURN_OFF = -1;
        const int TURN_ON_NOW = 0;
        const int TURN_ON_SOON = 100;

        // Control Timers
        Timer keyTimer;

        // For Haydon motor there are 2 axis
        EasyStepper HaydonRotate = new EasyStepper();
        EasyStepper HaydonLinear = new EasyStepper();

        // Menu elements: create the structure
        public struct menu
        {
            public menu(string menuTag, string menuText, string parentTag)
            {
                this.menuTag = menuTag;
                this.menuText = menuText;
                this.parentTag = parentTag;
            }

            public string menuTag;
            public string menuText;
            public string parentTag;
        }

        // Fill the menu
        static menu[] myMenu = new menu[] { new menu() { menuTag = "MainMenu", menuText = "Main Menu", parentTag="MainMenu" }, 
                                            new menu() { menuTag = "JogMenu", menuText = "Jog Menu", parentTag="MainMenu" }, 
                                            new menu() { menuTag = "Jog2Menu", menuText = "Jog2 Menu", parentTag="JogMenu" } ,
                                            new menu() { menuTag = "Jog3Menu", menuText = "Jog3 Menu", parentTag="JogMenu" } ,
                                            new menu() { menuTag = "Jog4Menu", menuText = "Jog4 Menu", parentTag="JogMenu" } ,
                                            new menu() { menuTag = "SetupMenu", menuText = "Setup Menu", parentTag="MainMenu" },
                                            new menu() { menuTag = "Setup2Menu", menuText = "Setup2 Menu", parentTag="SetupMenu" } ,
                                            new menu() { menuTag = "Setup3Menu", menuText = "Setup3 Menu", parentTag="SetupMenu" } ,
                                            new menu() { menuTag = "Setup4Menu", menuText = "Setup4 Menu", parentTag="SetupMenu" } ,
                                           };

        // Set the current menu to the top element
        public menu currentMenu = myMenu[0];


        public void Run()
        {
            // Initialize LCD Keypad
            LCDKeypad.Initialize();

            // Display the welcome splash screen
            DisplayWelcome();
            DisplayMenu(currentMenu);


            // Initialize rotating motor and linear motor
            HaydonRotate.Initialize(200, Pins.GPIO_PIN_D3, Pins.GPIO_PIN_D4, Pins.GPIO_PIN_D0, Pins.GPIO_PIN_D1);
            HaydonLinear.Initialize(200, Pins.GPIO_PIN_D8, Pins.GPIO_PIN_D9, Pins.GPIO_PIN_D5, Pins.GPIO_PIN_D6);
       
            // Set up timer to check for Keys
            keyTimer = new Timer(on_keyTimerTick, null, TURN_ON_NOW, KEY_TIMEOUT);


        }

        public void Dispose()
        {
            keyTimer.Dispose();
        }

        #region Menu Handling

        private void DisplayWelcome()
        {
            // const byte ARROW_RIGHT = 126;
            // const byte ARROW_LEFT = 127;


            LCDKeypad.SetCustomChars(1, new byte[] { 0, 2, 6, 14, 6, 2, 0 });     // Left
            LCDKeypad.SetCustomChars(2, new byte[] { 0, 8, 12, 14, 12, 8, 0 });   // Right
            LCDKeypad.SetCustomChars(3, new byte[] { 0, 0, 4, 14, 31, 0, 0 });    // Up
            LCDKeypad.SetCustomChars(4, new byte[] { 0, 0, 31, 14, 4, 0, 0 });    // Down
            LCDKeypad.SetCustomChars(5, new byte[] { 14, 1, 1, 29, 25, 22, 0 });  // Clockwise
            LCDKeypad.SetCustomChars(6, new byte[] { 14, 16, 16, 23, 19, 13, 0 });// AntiClockwise
            LCDKeypad.SetCustomChars(7, new byte[] { 4, 14, 31, 4, 4, 31, 31 });  // Out
            LCDKeypad.SetCustomChars(0, new byte[] { 4, 4, 31, 14, 4, 31, 31 });  // In

            LCDKeypad.Clear();
            LCDKeypad.ModeForwardStatic();
            LCDKeypad.CursorInvisible();

            LCDKeypad.Print(0, 0, Resources.GetString(Resources.StringResources.WelcomeMsg1));
            LCDKeypad.Print(1, 1, Resources.GetString(Resources.StringResources.WelcomeMsg2));

            Thread.Sleep(2000);

            LCDKeypad.Clear();
 
       }
      

        public void on_keyTimerTick(object state)
        {
            doMenuStuff();
        }


        private void doMenuStuff()
        {
            switch (LCDKeypad.GetKey())
                    {
                         case LCDKeypad.Keys.None:
                            break;       

                         case LCDKeypad.Keys.Up:
                            cancelMenu();
                            break;

                        case LCDKeypad.Keys.Down:
                            cancelMenu();
                            break;

                        case LCDKeypad.Keys.Right:
                            getNextMenu();
                            break;

                        case LCDKeypad.Keys.Left:
                            getPriorMenu();
                            break;
                        
                        case LCDKeypad.Keys.Select:
                            selectMenu();
                            break;
                    

                        default:
                            break;
                    }
            }
         
        #endregion  
      
        private void getNextMenu()
        {
            bool foundFlag = false;
            bool endFlag = true;

            // Set current Position
            foreach (menu tempMenu in myMenu)
            {
                // Loop to the current item
                if (tempMenu.menuTag == currentMenu.menuTag)
                {
                    foundFlag = true;
                    continue;  // jump to next item
                }
                if (foundFlag)
                {
                    if (tempMenu.parentTag == currentMenu.parentTag)
                    {
                        // If next item is same parent, set as current
                        currentMenu = tempMenu;
                        endFlag = false;
                        break; // stop looking
                    }
                 }
            }
            
            // If we get to the end, loop back to the top
            if (!endFlag)
            {
                DisplayMenu(currentMenu);
            }
            else
            {
                // Couldn't find next menu so loop back to top
                foreach (menu tempMenu in myMenu)
                {
                   if (tempMenu.parentTag == currentMenu.parentTag)
                        {
                            currentMenu = tempMenu;
                            break;
                        }
                 }
                 DisplayMenu(currentMenu);
             }
        }



        private void getPriorMenu()
        {
            menu priorMenu = currentMenu;

            // Set current Position
            foreach (menu tempMenu in myMenu)
            {
                if (tempMenu.parentTag == currentMenu.parentTag )
                {
                    // If next item is same parent and not the current item, set as current
                    if (tempMenu.menuTag != currentMenu.menuTag)
                    {
                        priorMenu = tempMenu;
                    }
                }
                
                // Loop to the current item
                if (tempMenu.menuTag == currentMenu.menuTag)
                {
                    currentMenu = priorMenu;
                    break;
                }            
            }


                DisplayMenu(currentMenu);
          
        }



        public void selectMenu()
        {
            bool isMenu = false;

            // Check if this is a menu or option
            foreach (menu tempMenu in myMenu)
            {
                if (tempMenu.parentTag == currentMenu.menuTag)
                {
                    currentMenu = tempMenu;
                    isMenu = true;
                    break;
                }
            }

            // If menu item then display
            if (isMenu)
            {
                DisplayMenu(currentMenu);

            }
            else
            {
                RunThisOption(currentMenu.menuTag);
            }   
        }

        public void cancelMenu()
        {
            // Go back up one level
            foreach (menu tempMenu in myMenu)
            {
                if (tempMenu.menuTag == currentMenu.parentTag)
                {
                    currentMenu = tempMenu;
                    break;
                }
            }
            // Display
            DisplayMenu(currentMenu);
        }

        public void RunThisOption(string selectedItem)
        {
            switch (selectedItem)
            {
                case "Setup4Menu":
                    Debug.Print("Setup4Menu selected");
                    break;
                default:
                    Debug.Print("Unknown item selected");
                    break;
            }
        }


        public void DisplayMenu(menu thisMenu)
        {
            
                LCDKeypad.Print(0, 0, "                ");
                LCDKeypad.Print(0, 0, thisMenu.parentTag);
                LCDKeypad.Print(1, 0, "                ");
                LCDKeypad.Print(1, 0, thisMenu.menuText);
         

        }

    }
}


#4 Netd

Netd

    New Member

  • Members
  • Pip
  • 4 posts

Posted 11 February 2012 - 02:29 PM

Hi Steve! I'm just looking for a menu system for a heating system, but unfortunately have not yet found. How does work, your menu? We wanted a main menu with four sub-menus which again have a submenu. In the submenu you can then adjust parameters or, for example: set the time. Is this possible with your menu? We use this display with the keyboard! http://www.robot-ele...m/Lcd03tech.htm Yours sincerely, Hubert

#5 JerseyTechGuy

JerseyTechGuy

    Advanced Member

  • Members
  • PipPipPip
  • 870 posts

Posted 11 February 2012 - 03:31 PM

I've used this code as a basis for my menu system... While it will support main, sub and sub-sub menu's and execution (selection of the menu item) you will need to build out custom code for changing of the settings.

#6 Netd

Netd

    New Member

  • Members
  • Pip
  • 4 posts

Posted 11 February 2012 - 04:31 PM

So your menu system also has sub-menus? Can you describe to me how the menu works basically? static menu [] = new menu myMenu [] {new menu () {menuTag = "MainMenu" MenuText = "Main Menu" parentTag = "MainMenu"}, parentTag, menuTag, MenuText What is running in DisplayWelcome() ? When the keyTimer is called? What do you mean by build out custom code? I am only a beginner! Thank you for your help! Yours sincerely, Hubert Reisinger

#7 Netd

Netd

    New Member

  • Members
  • Pip
  • 4 posts

Posted 13 February 2012 - 01:46 PM

So basically I now understand the structure of the menus, but how can I set values ​​is still unclear to me!




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

home    hardware    projects    downloads    community    where to buy    contact Copyright © 2016 Wilderness Labs Inc.  |  Legal   |   CC BY-SA
This webpage is licensed under a Creative Commons Attribution-ShareAlike License.