menubackend library submenus

Anyone worked out a neat way to have a second menu that is called from the first menu so that you dont have to repeat menuItems? but also be able to navigate back to the place you were in in the first menu?
i tried to adjust the library C++ file, but got in a right mess.
If anyone can help me with this I (and I think the community) would love this feature.

Perhaps the only way is to write it out? every single one? sounds inefficient.
this must be useful for somebody?

Hi

to my research, the author of MenuBackend has not been aktive since 4 months. Another problem is, that there are several menu libs out there. Several weeks ago, i collected some of them:

Library Name: LCDMenu2
Download: http://arduino.cc/forum/index.php/topic,73816.0.html

Library Name: LCDMenu
Download: http://arduino.cc/forum/index.php/topic,96104.0.html

Library Name: MenuBackend
Download: http://wiring.uniandes.edu.co/source/trunk/wiring/firmware/libraries/MenuBackend/

Library Name: LCDMenu
Download: http://www.metalgecko.com/arduino/LCDMenu.zip (does not exist any more)

Library Name: Arduino_LCD_Menu
Download: GitHub - DavidAndrews/Arduino_LCD_Menu: This library creates menu systems primarily useful for 16x2 or 16x4 LCD displays.

Library Name: MENWIZ
Download: GitHub - brunialti/MENWIZ: ARDUINO LCD menu library: short user code to manage complex menu structures

Library Name: phi_prompt
Download: Phi_prompt | LiuDr Electronic Solutions LLC Official Blog

Library Name: MenuSample
Download: Arduino WiFly Driver - Browse /MenuSample at SourceForge.net

Library Name: M2tklib
Download: Google Code Archive - Long-term storage for Google Code Project Hosting.

Not too many Arduino users add displays. And only some of them decide to use a menu lib.
Of course i would suggest to use "m2tklib" (as author of the lib :wink: )
"m2tklib" can call sub menues.

Oliver

Oliver your always helpful!
Ok yeah I managed to contact him via email once a few weeks ago and he said he reckoned his library was capable of it and would write me an example, but never did, so as you have been helpful in the past, and are available :D. I am going to download your library and have a look.
Just to be clear on what Im after,
if you have one menu that has, girl, boy, man, woman and for each option you want to then choose hair colour, I dont want to have to make menu items of hair colours for each option, so i want to have a menu of hair colours that can be called from the higher level menu, but also pass the lower level menu the information, so that it knows who called it, and then be able to go back to that place in the higher menu:

girl -> brown/blonde/red -> "You chose girl with red hair"
|
boy -> brown/blonde/red -> "You chose boy with brown hair"
|
man -> brown/blonde/red -> "You chose man with blonde hair"
...

EDIT:
Any chance you might be able to give me a (pseudo) on how you would go about this using your library?

Oliver your always helpful!

Hmm not so sure about my initial post to this thread.

Any chance you might be able to give me a (pseudo) on how you would go about this using your library?

There are several ways to implement your specification. The most flexible approach is described in tutorial 8:
Google Code Archive - Long-term storage for Google Code Project Hosting..
Tutorial 8 is more technical, but i am sure your are able to match your specification:

"The user can select one of the PWM pins (six for the Arduino Uno)." --> "girl, boy, man, woman"
"The user can modify the output state of each pin" --> hair colours

The code itself is here:
http://code.google.com/p/m2tklib/source/browse/arduino/LiquidCrystal/PWMPinList/PWMPinList.pde

There might be other (simpler) approaches, when there is only a single option to choose. For example you can write a single callback procedure for a M2_COMBO element which can be placed several times (one for girl, boy, man, ...) on a dialog, but uses the same callback procedure for the hair colours.

Let me know if you need another example...

Oliver

Hi Oliver,
I wonder if you could pull a slightly more basic example together, Ive been studying the code from the example, but it seems like setting pwm pins is hard coded into the class?
Is there any chance you could make a simple example possibly using the girl/boy example where it calls a second menu for the hair colour. Also is there any chance you could do it using serial.println() to display the menu so it is very bare bone as it were?
i know im asking quite a lot but it would be extremely handy if you could find the time
Thanks
A

ok, let me start with your last question:
Within the pwm example:
In line 67 replace
M2tk m2(&top_el_pin_list, m2_es_arduino, m2_eh_4bs, m2_gh_lc);
with
M2tk m2(&top_el_pin_list, m2_es_arduino_serial, m2_eh_4bs, m2_gh_arduino_serial);

This will use serial.print and you can see the menu on the serial monitor.
(hey, thats a really cool feature, isn't it... 8) )

I will answer the remaining questions in another post.

Oliver

ok, then, here is my boy, girl,... example. Very simplified and reduced to one screen.

#include <LiquidCrystal.h>
#include "M2tk.h"
#include "m2ghlc.h"

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

uint8_t uiKeySelectPin = 10;
uint8_t uiKeyNextPin = 9;

uint8_t girl_color = 0;
uint8_t boy_color = 0;
uint8_t man_color = 0;

void fn_ok(m2_el_fnarg_p fnarg) {
  /* do something */
}

const char *fn_idx_to_color(uint8_t idx)
{
  switch(idx)
  {
    case 0: return "brown";
    case 1: return "blonde";
    case 2: return "red";
  }
  return "";
}


M2_LABEL(el_label1, NULL, "Boy:");
M2_COMBO(el_combo1, NULL, &boy_color, 3, fn_idx_to_color);

M2_LABEL(el_label2, NULL, "Girl: ");
M2_COMBO(el_combo2, NULL, &girl_color, 3, fn_idx_to_color);

M2_LABEL(el_label3, NULL, "Man: ");
M2_COMBO(el_combo3, NULL, &man_color, 3, fn_idx_to_color);

M2_BUTTON(el_ok, NULL, " ok ", fn_ok);

M2_LIST(list) = { 
    &el_label1, &el_combo1, 
    &el_label2, &el_combo2,  
    &el_label3, &el_combo3,  
    &el_ok 
};

M2_GRIDLIST(list_element, "c2",list);
M2tk m2(&list_element, m2_es_arduino, m2_eh_4bs, m2_gh_lc);

void setup() {
  m2_SetLiquidCrystal(&lcd, 16, 4);
  m2.setPin(M2_KEY_SELECT, uiKeySelectPin);
  m2.setPin(M2_KEY_NEXT, uiKeyNextPin);
}

void loop() {
  m2.checkKey();
  if ( m2.handleKey() )
    m2.draw();
  m2.checkKey();
}

The result will be stored in the three variables:

uint8_t girl_color = 0;
uint8_t boy_color = 0;
uint8_t man_color = 0;

I am not sure if i should repeat what is written in the reference manual. Maybe you should have a look at M2_GRIDLIST, which arranges the element into a matrix and M2_COMBO which does most of the work here.
So please let me know if there is something i can explain into more detail.

Remember: You can still use the serial monitor by replacing the event handler (eh) and the graphics handler (eh) as described in my last post.

Oliver

so, finally, here is the example with submenu:

#include <LiquidCrystal.h>
#include "M2tk.h"
#include "m2ghlc.h"

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

uint8_t uiKeySelectPin = 10;
uint8_t uiKeyNextPin = 9;

uint8_t girl_color = 0;
uint8_t boy_color = 0;
uint8_t man_color = 0;

M2_EXTERN_GRIDLIST(el_main_menu);
M2tk m2(&el_main_menu, m2_es_arduino, m2_eh_4bs, m2_gh_lc);

void fn_ok(m2_el_fnarg_p fnarg) {
  /* color changed, do something */
  
  /* then jump back to the main menu */
  m2.setRoot(&el_main_menu);
}

const char *fn_idx_to_color(uint8_t idx)
{
  switch(idx)
  {
    case 0: return "brown";
    case 1: return "blonde";
    case 2: return "red";
  }
  return "";
}

/* boy submenu */
M2_LABEL(el_label1, NULL, "Boy:");
M2_COMBO(el_combo1, NULL, &boy_color, 3, fn_idx_to_color);
M2_BUTTON(el_ok1, NULL, " ok ", fn_ok);
M2_LIST(list1) = { 
    &el_label1, &el_combo1, 
    &el_ok1 
};
M2_GRIDLIST(el_grid1, "c2",list1);

/* girl submenu */
M2_LABEL(el_label2, NULL, "Girl:");
M2_COMBO(el_combo2, NULL, &girl_color, 3, fn_idx_to_color);
M2_BUTTON(el_ok2, NULL, " ok ", fn_ok);
M2_LIST(list2) = { 
    &el_label2, &el_combo2, 
    &el_ok2 
};
M2_GRIDLIST(el_grid2, "c2",list2);

/* man submenu */
M2_LABEL(el_label3, NULL, "Man:");
M2_COMBO(el_combo3, NULL, &man_color, 3, fn_idx_to_color);
M2_BUTTON(el_ok3, NULL, " ok ", fn_ok);
M2_LIST(list3) = { 
    &el_label3, &el_combo3, 
    &el_ok3 
};
M2_GRIDLIST(el_grid3, "c2",list3);

/* main menu */
M2_ROOT(el_boy_button, NULL, "Boy", &el_grid1);
M2_ROOT(el_girl_button, NULL, "Girl", &el_grid2);
M2_ROOT(el_man_button, NULL, "Man", &el_grid3);
M2_LIST(list_main_menu) = { 
    &el_boy_button,  
    &el_girl_button,   
    &el_man_button,  
};
M2_GRIDLIST(el_main_menu, "c1",list_main_menu);

void setup() {
  m2_SetLiquidCrystal(&lcd, 16, 4);
  m2.setPin(M2_KEY_SELECT, uiKeySelectPin);
  m2.setPin(M2_KEY_NEXT, uiKeyNextPin);
}

void loop() {
  m2.checkKey();
  if ( m2.handleKey() )
    m2.draw();
  m2.checkKey();
}

This example defines four different menus (or dialog boxes). You can switch between these dialog boxes by using the M2_ROOT button or the m2.setRoot procedure. Calling a sub menu is nothing else than assigning a new dialog box with M2_ROOT. For the jump back to the main menu, the callback procedure of the ok button uses "m2.setRoot()".

hope this helps... again, let me know if you need more examples.

Oliver

Great Oliver, thanks I'll give that a go.
So I can change easily to serial from you lcd, however what if I want to use a different lcd to the one in your library.
I declare my lcd here:

Adafruit_PCD8544 display = Adafruit_PCD8544(52, 51, 50, 48, 49);

So I need to replace:

m2_gh_lc

but Im not sure with what... it isnt declared anywhere else in your code, and I assume

m2_es_arduino

can stay the same if I change the lcd?
And lastly:

m2_SetLiquidCrystal(&lcd, 16, 4);
[code]
?

[/code]

ooooohhhhhhh

To my knowledge menubackend only supports character lcds via LiquidCrystal, so i assumed, that your display is a character display. I mean, as far as i know, menubackend will also not work with the Adafruit PCD8455 lib for graphics lcd. So far M2tklib is the only menu lib which supports graphics lcds. However, m2tklib does not support the Adafruit PCD8455 library. The reason is simple: There are a large number of graphics libs out there and I can not write interfaces to all of them. Instead: M2tklib supports U8glib, which supports your PCD8455 display. So, to use m2tklib (again: which is probably the only Arduino menu lib for graphics displays) you probably need to download and use u8glib (Google Code Archive - Long-term storage for Google Code Project Hosting.) instead of the Adafruit PCD8455 library.
Other option is to write the interface for the Adafruit lib, but this is a little bit complicated and poorly documented.

After this, you have to modify setup() and loop() procedures of the examples:

// Arduino setup procedure (called only once)
void setup() {
  // Connect u8glib with m2tklib
  m2_SetU8g(u8g.getU8g(), m2_u8g_box_icon);

  // Assign u8g font to index 0
  m2.setFont(0, u8g_font_7x13);

  // Setup keys
  m2.setPin(M2_KEY_SELECT, uiKeySelectPin);
  m2.setPin(M2_KEY_NEXT, uiKeyDownPin);
}

// Arduino loop procedure
void loop() {
  m2.checkKey();
  if ( m2.handleKey() ) {
    u8g.firstPage();  
    do {
      draw();
    } while( u8g.nextPage() );
  }
}

See also the tutorial here:
http://code.google.com/p/m2tklib/wiki/t02u8g

And the reference page for the u8glib binding for m2tklib:
http://code.google.com/p/m2tklib/wiki/u8gref

And finally, you need to choose a font for your display from here:
http://code.google.com/p/u8glib/wiki/fontsize

well... let me conclude this:

  • you own a graphics display
  • m2tklib supports graphics libs
  • m2tklib does not support the specific Adafruit GFX lib
  • m2tklib supports PCD8455 based displays via u8glib

Oliver

Haha! Oliver you are monopolizing the graphic lcd/menu industry with your libraries!
OK so I am using the nokia 5510 display from sparkfun, and you say that your u8_glib library supports that, then I have no issue using your library if it will work with your menu system. I have used menuBackend with that adafruit library, so it does seem to support it - I was doing it like this:

void menuChangeEvent(MenuChangeEvent changed)
{
  char string[30];
  string[0] = '\0';
  strcat(string, ">");
  strcat(string, changed.to.getLeft()->getName());
  strcat(string, ">");
  strcat(string, changed.to.getName()); 
  display.clearDisplay();   // clears the screen and buffer
  display.setCursor(0,0);
  display.println(string);
  display.display();

}

However thats just for info... I thought there may have been an equivelent for your menu library, but not bothered to use yours, because yours supports using a sub menu system.
i already have u8_glib downloaded and in my set of libraries, so I will set up my lcd to work with u8_glib then and then try out your boy/girl example.
In terms of that then, if I take your girl/boy example and adjust it to your newest setup()/loop() functions then it should work for my lcd...?

To initialize the lcd with u8_glib, the only line I can see that is close is:

U8GLIB_PCD8544 u8g(13, 11, 10, 9, 8);                    // SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, Reset = 8

which seems like the right one, so i just change the pin numbers, use your setup/loop and bingo, I can see how your boy/girl example works... I'll get on with that then
Cheers
A

EDIT:
I notice you use .checkKey() to see if one of the two buttons has been pressed, can I use a potentiometer/rotary encoder to go up and down, rather than a button?

To initialize the lcd with u8_glib, the only line I can see that is close is:
Code:

U8GLIB_PCD8544 u8g(13, 11, 10, 9, 8);                    // SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, Reset = 8

which seems like the right one, so i just change the pin numbers, use your setup/loop and bingo, I can see how your boy/girl example works...

Yes, ... hopefully

I notice you use .checkKey() to see if one of the two buttons has been pressed, can I use a potentiometer/rotary encoder to go up and down, rather than a button?

checkKey() calls an event source, which could analyse digital pins or a rotary encoder. However, I have not yet written the event source for a rotary encoder, but i added an enhancement request on the m2tklib project.

Oliver

Edit: Ensure to use m2tklib for u8glib. Also delete any other version before installing m2tklib for u8glib.

olikraus:
Hi

to my research, the author of MenuBackend has not been aktive since 4 months. Another problem is, that there are several menu libs out there. Several weeks ago, i collected some of them:

Library Name: LCDMenu2
Download: http://arduino.cc/forum/index.php/topic,73816.0.html

Library Name: LCDMenu
Download: http://arduino.cc/forum/index.php/topic,96104.0.html

Library Name: MenuBackend
Download: http://wiring.uniandes.edu.co/source/trunk/wiring/firmware/libraries/MenuBackend/

Library Name: LCDMenu
Download: http://www.metalgecko.com/arduino/LCDMenu.zip (does not exist any more)

Library Name: Arduino_LCD_Menu
Download: GitHub - DavidAndrews/Arduino_LCD_Menu: This library creates menu systems primarily useful for 16x2 or 16x4 LCD displays.

Library Name: MENWIZ
Download: GitHub - brunialti/MENWIZ: ARDUINO LCD menu library: short user code to manage complex menu structures

Library Name: phi_prompt
Download: Phi_prompt | Liudr's Blog

Library Name: MenuSample
Download: Arduino WiFly Driver - Browse /MenuSample at SourceForge.net

Library Name: M2tklib
Download: Google Code Archive - Long-term storage for Google Code Project Hosting.

Not too many Arduino users add displays. And only some of them decide to use a menu lib.
Of course i would suggest to use "m2tklib" (as author of the lib :wink: )
"m2tklib" can call sub menues.

Oliver

Wish I had this before I started out with menubackend!

Anyway in case it's of use I have created a menu using menubackend, not without problems using menubackend getBefore() in fact all getX() option won't compile but I did create a menu like so:

CONFIGURE (0)
CONFIG HEATER (1)
HEATER ON (2)
HEATER OFF (2)
HEATER DISABLE (2)
EXIT (2)
EXIT (1)
EXIT (0)

My problem was telling it to MoveToLevel(0) when I wanted to reset the position in the menu but it resets the board so I wrote a while loop to work it's wya back testing each element for an up or left option, if left that's leaving a submenu if up cycling through the current menus options. I link the 1st to the last menu element to create a loop.

Link is: menubackend moveToLevel(lvl) resets uno - #5 by system - Programming Questions - Arduino Forum

Oliver, does this line need replacing for u8_glib?

M2tk m2(&el_main_menu, m2_es_arduino, m2_eh_4bs, m2_gh_lc);

I have my program like this, and I downloaded the latest library for m2 with u8_glib, but I get an error

#include "M2tk.h"
#include "m2ghu8g.h"
#include "U8glib.h"
U8GLIB_PCD8544 u8g(13, 11, 10, 9, 8);                    // SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, Reset = 8
//Adafruit_PCD8544 display = Adafruit_PCD8544(52, 51, 50, 48, 49);

uint8_t uiKeySelectPin = 10;
uint8_t uiKeyNextPin = 9;

uint8_t girl_color = 0;
uint8_t boy_color = 0;
uint8_t man_color = 0;

M2_EXTERN_GRIDLIST(el_main_menu);
M2tk m2(&el_main_menu, m2_es_arduino, m2_eh_4bs, m2_gh_u8g_bf);

void fn_ok(m2_el_fnarg_p fnarg) {
  /* color changed, do something */
  
  /* then jump back to the main menu */
  m2.setRoot(&el_main_menu);
}

const char *fn_idx_to_color(uint8_t idx)
{
  switch(idx)
  {
    case 0: return "brown";
    case 1: return "blonde";
    case 2: return "red";
  }
  return "";
}

/* boy submenu */
M2_LABEL(el_label1, NULL, "Boy:");
M2_COMBO(el_combo1, NULL, &boy_color, 3, fn_idx_to_color);
M2_BUTTON(el_ok1, NULL, " ok ", fn_ok);
M2_LIST(list1) = { 
    &el_label1, &el_combo1, 
    &el_ok1 
};
M2_GRIDLIST(el_grid1, "c2",list1);

/* girl submenu */
M2_LABEL(el_label2, NULL, "Girl:");
M2_COMBO(el_combo2, NULL, &girl_color, 3, fn_idx_to_color);
M2_BUTTON(el_ok2, NULL, " ok ", fn_ok);
M2_LIST(list2) = { 
    &el_label2, &el_combo2, 
    &el_ok2 
};
M2_GRIDLIST(el_grid2, "c2",list2);

/* man submenu */
M2_LABEL(el_label3, NULL, "Man:");
M2_COMBO(el_combo3, NULL, &man_color, 3, fn_idx_to_color);
M2_BUTTON(el_ok3, NULL, " ok ", fn_ok);
M2_LIST(list3) = { 
    &el_label3, &el_combo3, 
    &el_ok3 
};
M2_GRIDLIST(el_grid3, "c2",list3);

/* main menu */
M2_ROOT(el_boy_button, NULL, "Boy", &el_grid1);
M2_ROOT(el_girl_button, NULL, "Girl", &el_grid2);
M2_ROOT(el_man_button, NULL, "Man", &el_grid3);
M2_LIST(list_main_menu) = { 
    &el_boy_button,  
    &el_girl_button,   
    &el_man_button,  
};
M2_GRIDLIST(el_main_menu, "c1",list_main_menu);

// Arduino setup procedure (called only once)
void setup() {
  // Connect u8glib with m2tklib
  m2_SetU8g(u8g.getU8g(), m2_u8g_box_icon);

  // Assign u8g font to index 0
  m2.setFont(0, u8g_font_7x13);

  // Setup keys
  m2.setPin(M2_KEY_SELECT, uiKeySelectPin);
  m2.setPin(M2_KEY_NEXT, uiKeyDownPin);
}

// Arduino loop procedure
void loop() {
  m2.checkKey();
  if ( m2.handleKey() ) {
    u8g.firstPage();  
    do {
      draw();
    } while( u8g.nextPage() );
  }
}

sketch_jul17a.cpp:2:21: error: m2ghu8g.h: No such file or directory
sketch_jul17a:14: error: 'm2_gh_u8g_bf' was not declared in this scope
sketch_jul17a.cpp: In function 'void setup()':
sketch_jul17a:78: error: 'm2_u8g_box_icon' was not declared in this scope
sketch_jul17a:78: error: 'm2_SetU8g' was not declared in this scope
sketch_jul17a:85: error: 'uiKeyDownPin' was not declared in this scope
sketch_jul17a.cpp: In function 'void loop()':
sketch_jul17a:94: error: 'draw' was not declared in this scope

i.e i dont think it can find the libraries?

a.mlw.walker:
Oliver, does this line need replacing for u8_glib?

M2tk m2(&el_main_menu, m2_es_arduino, m2_eh_4bs, m2_gh_lc);

Yes: Please replace m2_gh_lc with m2_gh_u8g_bf (or one of the other u8g graphics handler)

Regarding the compile problem:
The latest version of m2tklib for u8glib is here:
http://code.google.com/p/m2tklib/downloads/detail?name=m2tklib_arduino_u8g_1.08.zip
U8glib requires another download (only for AVR - none Arduino - there is a combined zip)

Usually the best is to remove the old m2tklib folder and unzip the version above.

Oliver

Ah yes, new library means everything has compiled.
nice...

Time for me to kick menubackend out of my prog. I'm not convinced it's working properly given the problems I've had with it.

Time to read up on m2tklib at Google Code Archive - Long-term storage for Google Code Project Hosting.

Time to read up on m2tklib at Google Code Archive - Long-term storage for Google Code Project Hosting.

After all the threads, i see that a menu lib is difficult to handle (also i think it has a simple concept). I did my best to add tutorial pages to the wiki, but i also see that there is still a lot of discussion required. I am not sure how to improve this. Let me know if something is missing... and do not hestitate to ask directly...

Oliver

dannix, I had the same problem, built a huge menu, couldnt get it to work, and now turning to this option. Seems like it has much more functionality just trying to learn how to use its features