Building a menu system with 3 buttons (guidance)
#1
Posted 18 January 2012 - 10:37 PM
#2
Posted 19 January 2012 - 07:49 AM
I would use the interruptport class. So event driven.1) How to start in a loop that looks for the button presses on D0, D1 and D2. Only when the "Start Logging" choice has been made will this menu process stop and start logging loop. Should these be loops? Threaded? Event Driven?
It's the simplest way. As long as it's just 3 buttons, you'll be fine2) Is there a better way to handle the buttons than use 3 Inputs?
- JerseyTechGuy likes this
My .NETMF projects: .NETMF Toolbox / Gadgeteer Light / Some PCB designs
#3
Posted 19 January 2012 - 12:35 PM
#5
Posted 19 January 2012 - 01:24 PM
Are you in a hurry?
I've almost finished a demo of a LCD display, and the items displayed are selected via pushbuttons.
Which kind of display are you using?
Cheers
I am in the prototype stages, so I'm not in an extreme hurry. I am using a 16x2 LCD with an I2C LCD backpack..
#6
Posted 19 January 2012 - 04:23 PM
I did get an event driven prototype working last night. Used some code I found here for the menu items array. Got it working fine.
The only issue I am running into is having the program stop looking at those interrupts when you choose the menu item "Start Logging". Maybe I am misunderstanding the purpose of the DisableInterrupt. I'll play a little more and If I do / don't get it working, I'll post the code to share or critique.
It sounds like you simply need to call the ClearInterrupt() method after handling the OnInterrupt() event.
If you upload your code we can take a look at it and help you out.
Cheers!
- ErikN likes this
#7
Posted 19 January 2012 - 04:44 PM
It sounds like you simply need to call the ClearInterrupt() method after handling the OnInterrupt() event.
If you upload your code we can take a look at it and help you out.
Cheers!
You were right on the money Darrin. Forgot the ClearInterrupt call. I have it working perfectly now. You can scroll up and down and when you select an item, it either does a sub menu or runs another block of code and in this case the buttons are disabled until needed again.
#8
Posted 14 April 2012 - 10:34 PM
How did your LCD display demo end up? Is it available somewhere?
Thanks,
Are you in a hurry?
I've almost finished a demo of a LCD display, and the items displayed are selected via pushbuttons.
Which kind of display are you using?
Cheers
#9
Posted 15 April 2012 - 04:22 AM
Hi Mario,
How did your LCD display demo end up? Is it available somewhere?
Thanks,
Oh, sure! It's a been that I've posted the LCD library and the related circuit:
http://highfieldtale...y-for-netduino/
Cheers
- Ralim likes this
#10
Posted 24 October 2012 - 09:14 AM
You were right on the money Darrin. Forgot the ClearInterrupt call. I have it working perfectly now. You can scroll up and down and when you select an item, it either does a sub menu or runs another block of code and in this case the buttons are disabled until needed again.
Is the code you developed form the Menu screen available anywhere? thanks!
#11
Posted 24 October 2012 - 09:57 AM
Is the code you developed form the Menu screen available anywhere? thanks!
I can work on posting it. I'll have to pull out the the menu specific code from my program. I'll try to get it posted today.
#12
Posted 24 October 2012 - 11:53 AM
There may also be a few variable specific to the modes my product runs in like IsRunning, IsScanning, etc. You can remove those but thought they would be good to see as they are used to disable the buttons in certain cases.
using System; using System.Threading; using Microsoft.SPOT.Hardware; using SecretLabs.NETMF.Hardware.NetduinoPlus; using Toolbox.NETMF.Hardware; namespace Netduino.MenuExample { /// <summary> /// Menu Example /// </summary> public class Program { #region Constants // 5 Way Button Constants const Cpu.Pin BUTTON_ENTER = Pins.GPIO_PIN_D2; const Cpu.Pin BUTTON_UP = Pins.GPIO_PIN_D3; const Cpu.Pin BUTTON_DOWN = Pins.GPIO_PIN_D4; const Port.ResistorMode BUTTON_RESISTOR_MODE = Port.ResistorMode.PullUp; const bool BUTTON_ACTIVE_LEVEL = false; #endregion #region Static Members // The input port(s) for the 5 way button(s) AutoRepeatInputPort incEnterButton = new AutoRepeatInputPort(BUTTON_ENTER, BUTTON_RESISTOR_MODE, BUTTON_ACTIVE_LEVEL); AutoRepeatInputPort incUpButton = new AutoRepeatInputPort(BUTTON_UP, BUTTON_RESISTOR_MODE, BUTTON_ACTIVE_LEVEL); AutoRepeatInputPort incDownButton = new AutoRepeatInputPort(BUTTON_DOWN, BUTTON_RESISTOR_MODE, BUTTON_ACTIVE_LEVEL); // Menu Items private static menu[] myMenu = new menu[] { new menu() { menuTag = "StartProcess", menuText = "Start Process", parentTag="MyMenuSystem" }, new menu() { menuTag = "LightanLED", menuText = "Light an LED", parentTag="MyMenuSystem" }, new menu() { menuTag = "RunDiagnostics", menuText = "Run Diagnostics", parentTag="MyMenuSystem" }, new menu() { menuTag = "Reboot", menuText = "Reboot", parentTag="MyMenuSystem" }, }; // Set the current menu to the top element public menu currentMenu = myMenu[0]; // Application Variables // IsRunning is used when the program is running a dedicated function that shouldn't be interrupted. private bool IsRunning = false; private bool IsScanning = false; private bool IsDiagnosing = false; #endregion #region Structures // 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; } #endregion #region Public Methods public static void Main() { new Program().run(); } #endregion #region Private Methods private void run() { try { // Display the welcome splash screen DisplayWelcome(); // Give it some time to catch up Thread.Sleep(250); // Display the Menu DisplayMenu(currentMenu); // Start the wait loop WaitForInteractions(); } catch (Exception ex) { } } private void rerun() { try { // Clear the LCD LCD.Clear(); // Display the welcome splash screen DisplayWelcome(); // Display the Menu DisplayMenu(currentMenu); // Start the wait loop WaitForInteractions(); } catch (Exception ex) { } } private void WaitForInteractions() { while (true) { try { // Wait indefinitely or until button states have changed Thread.Sleep(Timeout.Infinite); } catch (Exception ex) { } } } private void DisplayWelcome() { try { // Clear LCD LCD.Clear(); // Write out messages LCD.Print(Lcd.Position.ROW_1, Lcd.Position.COLUMN_1, "My Menu System"); LCD.Print(Lcd.Position.ROW_2, Lcd.Position.COLUMN_1, "Starting Up... "); } catch (Exception ex) { } } #region Menu Methods 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); } private 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); } } private void cancelMenu() { // Go back up one level foreach (menu tempMenu in myMenu) { if (tempMenu.menuTag == currentMenu.parentTag) { currentMenu = tempMenu; break; } } // Display DisplayMenu(currentMenu); } private void DisplayMenu(menu thisMenu) { try { LCD.Print(Lcd.Position.ROW_1, Lcd.Position.COLUMN_1, "My Menu System"); String str = new string((char)32, (19 - (thisMenu.menuText.Length))); LCD.Print(Lcd.Position.ROW_2, Lcd.Position.COLUMN_1, ">" + thisMenu.menuText + str); } catch (Exception ex) { } } private void RunThisOption(string selectedItem) { try { switch (selectedItem) { case "StartLogging": IsRunning = true; StartLogging(); break; case "EraseSDCard": IsRunning = true; EraseSDCard(); break; case "RunDiagnostics": IsRunning = true; RunDiagnostics(); break; case "Reboot": IsRunning = true; Reboot(false); break; default: break; } } catch (Exception ex) { } } #endregion #endregion #region Event Handlers void incButton_OnStateChange(object sender, AutoRepeatEventArgs e) { try { AutoRepeatInputPort button = (AutoRepeatInputPort)sender; // up pressed if ((button.Id == Pins.GPIO_PIN_D4) && (IsRunning == false)) { switch (e.State) { case AutoRepeatInputPort.AutoRepeatState.Press: getPriorMenu(); return; case AutoRepeatInputPort.AutoRepeatState.Tick: if (IsRunning == true) { IsScanning = false; } return; case AutoRepeatInputPort.AutoRepeatState.Release: // ... return; } } // up special case of tick if ((button.Id == Pins.GPIO_PIN_D4) && (IsRunning == true) && (IsScanning == true)) { switch (e.State) { case AutoRepeatInputPort.AutoRepeatState.Tick: if (IsRunning == true) { IsScanning = false; } return; } } // up special case of tick if ((button.Id == Pins.GPIO_PIN_D4) && (IsRunning == true) && (IsDiagnosing == true)) { switch (e.State) { case AutoRepeatInputPort.AutoRepeatState.Tick: if (IsRunning == true) { IsDiagnosing = false; } return; } } // down pressed if ((button.Id == Pins.GPIO_PIN_D3) && (IsRunning == false)) { switch (e.State) { case AutoRepeatInputPort.AutoRepeatState.Press: getNextMenu(); return; case AutoRepeatInputPort.AutoRepeatState.Tick: // ... return; case AutoRepeatInputPort.AutoRepeatState.Release: // ... return; } } // enter pressed if (button.Id == Pins.GPIO_PIN_D2) { switch (e.State) { case AutoRepeatInputPort.AutoRepeatState.Press: selectMenu(); return; case AutoRepeatInputPort.AutoRepeatState.Tick: if (IsRunning == true) { IsScanning = false; } return; case AutoRepeatInputPort.AutoRepeatState.Release: // ... return; } } } catch (Exception ex) { } } #endregion } }
0 user(s) are reading this topic
0 members, 0 guests, 0 anonymous users