Step 2
All the complicated part is already done !
Download the CircularMenuAdvanced example
Open menu.h and change the voice
#define MENUSIZE 26 //26 ELEMENTS
to your needs. In our example we have 26 elements.
Now all you have to do is to write your *.pde program.
In our case we did this :
//Made By TrustFm.net (for www.hw2sw.com) #include "Menu.h" Menu MyMenu; //The DOWN button const byte BtnDownPin = 7; byte BtnDownState = 0; byte BtnDownLastState = 0; //The RIGHT button const byte BtnRightPin = 6; byte BtnRightState = 0; byte BtnRightLastState = 0; //The ENTER button const byte BtnEnterPin = 5; byte BtnEnterState = 0; byte BtnEnterLastState = 0; void ClearScreen(){ int i; for (i = 0; i < 15; i = i + 1) { Serial.println(); } } void ShowHints() { //Right hint if ( (*(MyMenu.GetSelectedMenuCell())).GetTitle() != (*((*(MyMenu.GetSelectedMenuCell())).GetNextRight())).GetTitle() ) { Serial.print(" > "); Serial.println( (*((*(MyMenu.GetSelectedMenuCell())).GetNextRight())).GetTitle() ); } //Down hint if ( (*(MyMenu.GetSelectedMenuCell())).GetTitle() != (*((*(MyMenu.GetSelectedMenuCell())).GetNextDown())).GetTitle() ) { Serial.print(" V "); Serial.println( (*((*(MyMenu.GetSelectedMenuCell())).GetNextDown())).GetTitle() ); } } void setup() { Serial.begin(9600); //Menu definition (Title,Father,Down,Next) (*(MyMenu.GetMenuCell(0))).Set("Menu 1", MyMenu.GetMenuCell(0), MyMenu.GetMenuCell(1),MyMenu.GetMenuCell(0)); (*(MyMenu.GetMenuCell(1))).Set("Menu 2", MyMenu.GetMenuCell(1), MyMenu.GetMenuCell(6),MyMenu.GetMenuCell(2)); (*(MyMenu.GetMenuCell(2))).Set("Menu 2>Smenu 1", MyMenu.GetMenuCell(1), MyMenu.GetMenuCell(3),MyMenu.GetMenuCell(2)); (*(MyMenu.GetMenuCell(3))).Set("Menu 2>Smenu 2", MyMenu.GetMenuCell(1), MyMenu.GetMenuCell(4),MyMenu.GetMenuCell(3)); (*(MyMenu.GetMenuCell(4))).Set("Menu 2>Smenu 3", MyMenu.GetMenuCell(1), MyMenu.GetMenuCell(5),MyMenu.GetMenuCell(4)); (*(MyMenu.GetMenuCell(5))).Set("Menu 2>up one dir", MyMenu.GetMenuCell(1), MyMenu.GetMenuCell(2),MyMenu.GetMenuCell(5)); (*(MyMenu.GetMenuCell(6))).Set("Menu 3", MyMenu.GetMenuCell(6), MyMenu.GetMenuCell(14),MyMenu.GetMenuCell(7)); (*(MyMenu.GetMenuCell(7))).Set("Menu 3>Smenu 1", MyMenu.GetMenuCell(6), MyMenu.GetMenuCell(8),MyMenu.GetMenuCell(7)); (*(MyMenu.GetMenuCell(8))).Set("Menu 3>Smenu 2", MyMenu.GetMenuCell(6), MyMenu.GetMenuCell(12),MyMenu.GetMenuCell(9)); (*(MyMenu.GetMenuCell(9))).Set("Menu 3>Smenu 2>SSmenu 1", MyMenu.GetMenuCell(8), MyMenu.GetMenuCell(10),MyMenu.GetMenuCell(9)); (*(MyMenu.GetMenuCell(10))).Set("Menu 3>Smenu 2>SSmenu 2", MyMenu.GetMenuCell(8), MyMenu.GetMenuCell(11),MyMenu.GetMenuCell(10)); (*(MyMenu.GetMenuCell(11))).Set("Menu 3>Smenu 2>up one dir", MyMenu.GetMenuCell(8), MyMenu.GetMenuCell(9),MyMenu.GetMenuCell(11)); (*(MyMenu.GetMenuCell(12))).Set("Menu 3>Smenu 3", MyMenu.GetMenuCell(6), MyMenu.GetMenuCell(13),MyMenu.GetMenuCell(12)); (*(MyMenu.GetMenuCell(13))).Set("Menu 3>up one dir", MyMenu.GetMenuCell(6), MyMenu.GetMenuCell(7),MyMenu.GetMenuCell(13)); (*(MyMenu.GetMenuCell(14))).Set("Menu 4", MyMenu.GetMenuCell(14), MyMenu.GetMenuCell(0),MyMenu.GetMenuCell(15)); (*(MyMenu.GetMenuCell(15))).Set("Menu 4>Smenu 1", MyMenu.GetMenuCell(14), MyMenu.GetMenuCell(21),MyMenu.GetMenuCell(16)); (*(MyMenu.GetMenuCell(16))).Set("Menu 4>Smenu 1>SSmenu 1", MyMenu.GetMenuCell(15), MyMenu.GetMenuCell(20),MyMenu.GetMenuCell(17)); (*(MyMenu.GetMenuCell(17))).Set("Menu 4>Smenu 1>SSmenu 1>SSSmenu 1" , MyMenu.GetMenuCell(16), MyMenu.GetMenuCell(18),MyMenu.GetMenuCell(17)); (*(MyMenu.GetMenuCell(18))).Set("Menu 4>Smenu 1>SSmenu 1>SSSmenu 2", MyMenu.GetMenuCell(16), MyMenu.GetMenuCell(19),MyMenu.GetMenuCell(18)); (*(MyMenu.GetMenuCell(19))).Set("Menu 4>Smenu 1>SSmenu 1>up one dir", MyMenu.GetMenuCell(16), MyMenu.GetMenuCell(17),MyMenu.GetMenuCell(19)); (*(MyMenu.GetMenuCell(20))).Set("Menu 4>Smenu 1>up one dir", MyMenu.GetMenuCell(15), MyMenu.GetMenuCell(16),MyMenu.GetMenuCell(20)); (*(MyMenu.GetMenuCell(21))).Set("Menu 4>Smenu 2", MyMenu.GetMenuCell(14), MyMenu.GetMenuCell(22),MyMenu.GetMenuCell(21)); (*(MyMenu.GetMenuCell(22))).Set("Menu 4>Smenu 3", MyMenu.GetMenuCell(14), MyMenu.GetMenuCell(23),MyMenu.GetMenuCell(22)); (*(MyMenu.GetMenuCell(23))).Set("Menu 4>Smenu 4", MyMenu.GetMenuCell(14), MyMenu.GetMenuCell(24),MyMenu.GetMenuCell(23)); (*(MyMenu.GetMenuCell(24))).Set("Menu 4>Smenu 5", MyMenu.GetMenuCell(14), MyMenu.GetMenuCell(25),MyMenu.GetMenuCell(24)); (*(MyMenu.GetMenuCell(25))).Set("Menu 4>up one dir", MyMenu.GetMenuCell(14), MyMenu.GetMenuCell(15),MyMenu.GetMenuCell(25)); pinMode(BtnDownPin, INPUT); pinMode(BtnRightPin, INPUT); pinMode(BtnEnterPin, INPUT); ClearScreen(); Serial.print(">"); Serial.println( (*(MyMenu.GetSelectedMenuCell())).GetTitle() ); (*(MyMenu.GetSelectedMenuCell())).SetIsSelected(true); ShowHints(); } void loop() // The main loop (runs over and over again) { BtnDownState = digitalRead(BtnDownPin); BtnRightState = digitalRead(BtnRightPin); BtnEnterState = digitalRead(BtnEnterPin); //The DOWN button if (BtnDownState != BtnDownLastState) { if (BtnDownState == HIGH) { ClearScreen(); Serial.print(">"); Serial.println( (*(MyMenu.GetNextDownMenuCell(MyMenu.GetSelectedMenuCell()))).GetTitle() ); ShowHints(); } } BtnDownLastState = BtnDownState; //The RIGHT button if (BtnRightState != BtnRightLastState) { if (BtnRightState == HIGH) { ClearScreen(); Serial.print(">"); Serial.println( (*(MyMenu.GetNextRightMenuCell(MyMenu.GetSelectedMenuCell()))).GetTitle() ); ShowHints(); } } BtnRightLastState = BtnRightState; //The ENTER button if (BtnEnterState != BtnEnterLastState) { if (BtnEnterState == HIGH) { if ( (*(MyMenu.GetMenuCell(0))).GetIsSelected()==true ) { ClearScreen(); Serial.println("This is the Menu 1 info page"); } else if ( (*(MyMenu.GetMenuCell(1))).GetIsSelected()==true ) { ClearScreen(); Serial.println("This is the Menu 2 info page"); } else if ( (*(MyMenu.GetMenuCell(2))).GetIsSelected()==true ) { ClearScreen(); Serial.println("This is the Menu 2 Submenu 1 info page"); } else if ( (*(MyMenu.GetMenuCell(3))).GetIsSelected()==true ) { ClearScreen(); Serial.println("This is the Menu 2 Submenu 2 info page"); } else if ( (*(MyMenu.GetMenuCell(4))).GetIsSelected()==true ) { ClearScreen(); Serial.println("This is the Menu 2 Submenu 3 info page"); } else if ( (*(MyMenu.GetMenuCell(5))).GetIsSelected()==true ) { //UP ONE DIR ClearScreen(); Serial.print(">"); Serial.println( (*(MyMenu.GetFatherMenuCell(MyMenu.GetSelectedMenuCell()))).GetTitle() ); ShowHints(); } else if ( (*(MyMenu.GetMenuCell(6))).GetIsSelected()==true ) { ClearScreen(); Serial.println("This is the Menu 3 info page"); } else if ( (*(MyMenu.GetMenuCell(7))).GetIsSelected()==true ) { ClearScreen(); Serial.println("This is the Menu 3 submenu 1 info page"); } else if ( (*(MyMenu.GetMenuCell(8))).GetIsSelected()==true ) { ClearScreen(); Serial.println("This is the Menu 3 submenu 2 info page"); } else if ( (*(MyMenu.GetMenuCell(9))).GetIsSelected()==true ) { ClearScreen(); Serial.println("This is the Menu 3 sub sub menu 1 info page"); } else if ( (*(MyMenu.GetMenuCell(10))).GetIsSelected()==true ) { ClearScreen(); Serial.println("This is the Menu 3 sub sub menu 2 info page"); } else if ( (*(MyMenu.GetMenuCell(11))).GetIsSelected()==true ) { //UP ONE DIR ClearScreen(); Serial.print(">"); Serial.println( (*(MyMenu.GetFatherMenuCell(MyMenu.GetSelectedMenuCell()))).GetTitle() ); ShowHints(); } else if ( (*(MyMenu.GetMenuCell(12))).GetIsSelected()==true ) { ClearScreen(); Serial.println("This is the Menu 3 submenu 3 info page"); } else if ( (*(MyMenu.GetMenuCell(13))).GetIsSelected()==true ) { //UP ONE DIR ClearScreen(); Serial.print(">"); Serial.println( (*(MyMenu.GetFatherMenuCell(MyMenu.GetSelectedMenuCell()))).GetTitle() ); ShowHints(); } else if ( (*(MyMenu.GetMenuCell(14))).GetIsSelected()==true ) { ClearScreen(); Serial.println("This is the Menu 4 info page"); } else if ( (*(MyMenu.GetMenuCell(15))).GetIsSelected()==true ) { ClearScreen(); Serial.println("This is the Menu 4 submenu 1 info page"); } else if ( (*(MyMenu.GetMenuCell(16))).GetIsSelected()==true ) { ClearScreen(); Serial.println("This is the Menu 4 SUB SUB menu 1 info page"); } else if ( (*(MyMenu.GetMenuCell(17))).GetIsSelected()==true ) { ClearScreen(); Serial.println("This is the Menu 4 SUB SUB SUB menu 1 info page"); } else if ( (*(MyMenu.GetMenuCell(18))).GetIsSelected()==true ) { ClearScreen(); Serial.println("This is the Menu 4 SUB SUB SUB menu 2 info page"); } else if ( (*(MyMenu.GetMenuCell(19))).GetIsSelected()==true ) { //UP ONE DIR ClearScreen(); Serial.print(">"); Serial.println( (*(MyMenu.GetFatherMenuCell(MyMenu.GetSelectedMenuCell()))).GetTitle() ); ShowHints(); } else if ( (*(MyMenu.GetMenuCell(20))).GetIsSelected()==true ) { //UP ONE DIR ClearScreen(); Serial.print(">"); Serial.println( (*(MyMenu.GetFatherMenuCell(MyMenu.GetSelectedMenuCell()))).GetTitle() ); ShowHints(); } else if ( (*(MyMenu.GetMenuCell(21))).GetIsSelected()==true ) { ClearScreen(); Serial.println("This is the Menu 4 submenu 2 info page"); } else if ( (*(MyMenu.GetMenuCell(22))).GetIsSelected()==true ) { ClearScreen(); Serial.println("This is the Menu 4 submenu 3 info page"); } else if ( (*(MyMenu.GetMenuCell(23))).GetIsSelected()==true ) { ClearScreen(); Serial.println("This is the Menu 4 submenu 4 info page"); } else if ( (*(MyMenu.GetMenuCell(24))).GetIsSelected()==true ) { ClearScreen(); Serial.println("This is the Menu 4 submenu 5 info page"); } else if ( (*(MyMenu.GetMenuCell(25))).GetIsSelected()==true ) { //UP ONE DIR ClearScreen(); Serial.print(">"); Serial.println( (*(MyMenu.GetFatherMenuCell(MyMenu.GetSelectedMenuCell()))).GetTitle() ); ShowHints(); } } } BtnEnterLastState = BtnEnterState; }
In order to do your menu you should only change the menu definition part !
For example
(*(MyMenu.GetMenuCell(0))).Set("Menu 1", MyMenu.GetMenuCell(0), MyMenu.GetMenuCell(1),MyMenu.GetMenuCell(0));
means that the 0 cell element has a title "Title 1" with a father id 0, down id 1 and right id 0.
Another example :
(*(MyMenu.GetMenuCell(15))).Set("Menu 4>Smenu 1", MyMenu.GetMenuCell(14), MyMenu.GetMenuCell(21),MyMenu.GetMenuCell(16));
means that the 15 cell element has a name "Menu 4>Smenu 1" his father has id 14, down id 21 and right id 16
As you remember the id numbers are already known (look at your menu.txt) done in the step before.
Now change only the ENTER part in base at your needs . (What do you want to do in each case).
Step 3
Construct your circuit like the photo below :
The down button is on port 7 the right button on port 6 and the enter button at port 5.
So reassuming
- Download the CircularMenuAdvanced example
- Create your menu.txt (find father, down and right elements). This step is optional but helps a lot.
Rules :
Add to all sub-levels, except the first one, the voice "up one directory" for navigability reasons.
No father means that the father pointer points itself.
Bottom element means that the down pointer points at the top element of the same sub level.
Right edge element means that the right pointer points itself.
- Change from menu.h the total elements of your menu
- Edit the "definition part" and the "enter part" of the given .pde file
- Add the three buttons (down, right and enter) at the pins 7,6,5 look here to find out how to hook the push buttons at arduino
- You are ready to go
A video example is located below :
Last thing :
Of course you can select different approaches for the navigability.
For example you can decide that the right edge element points at the root element so you have vertical and horizontal circularity.
It is up to you to decide the way to link your cell elements but keep in mind the navigability of your menu.
By doing vertical and horizontal circularity then the voices "up one dir" are not needed but a mistake by the user can produce a much longer circle path.
Hope you liked this article.
Update: the above code works perfectly with Arduino IDE 0.22; due to very little incompatibilities, such as headers renomination, the Arduino IDE 1.0 requires modification described in this article.