MENWIZ: yet another character lcd menu wizard library

brunialti:
Is the used lib one of the malpartida's libs?

Yes, that is right. The latest version for the LCD Version 3 - Marked "LCM1602 IIC A0 A1 A2"
David.

I think you are right, redrawing the display constantly with the same data in the main loop is a mistake, I'll amend my program to update the display less often. or only when the data changes.

Editing to redraw only the top line has made a huge improvement. I thought I'd checked for that already, doh.

Thanks for your help, David.

a more sophisticated version od drawusrscreen version could be easily implemented in order to avoid unusefull redrawing. Unfortunately it would require to save in a buffer the previous screen contents, wasting the sram pool...

If the execution time of the draw() method is critical for you consider also to use the other LCD interfaces: spi or, even better, 4 wire. They are much faster and probably you would'nt have noticed the difference until you measured it.
Both are supported by MENWIZ as far as you use the same fmalpartida library.

Hello,
I understand the memory concern of keeping a buffer to compare past and new screens I had to use a mega 256 for the previous project to gain extra memory, and yes, i2c always seems to be the slowest option although hugely convenient. Fortunately now I understand the reason for the delay a simple solution will be to limit the update rate of the display to give the PID calculation more time to execute. I may even hive off the display to a low priority function triggered by a timer and a flag set by the user function.
Best regards, David.

Hello to everyone !

I've got everything working - tank you brunialti ! :slight_smile:
But here comes another question - I need a two way "communication" for few variables : user can change them using buttons or remotely, using serial connection and they have to be "visible" on LCD and serial at the same time. But I know MENWIZ doesn't support this. Is there any solution for this ?

Hello, I came from spain , thank you for your library brunialti, it's very complete and usefull :wink:

I have a problem with the library... I use a menu with a lot of options and sometimes the options its no apears (the menu_index indicates "256/5" as the list is 256 elements but no appearns none. Can you help me?

The lines of code for create menu in the setup() are here:

void setup(){
  _menu *r,*s1,*s2;

  Serial.begin(115200);    
  
  Serial.println(sizeof(menwiz));
  tree.begin(&lcd,20,4); //declare lcd object and screen size to menwiz lib

  r=tree.addMenu(MW_ROOT,NULL,F("Settings"));
    s1=tree.addMenu(MW_SUBMENU,r,F("Cargas HB"));        //add a child (submenu) node to the root menu
      s2=tree.addMenu(MW_VAR,s1,F("HB D10"));
        s2->addVar(MW_LIST,&listb1);                          //create a variable of type "option list".. 
        s2->addItem(MW_VAR,F("HB 10/3000"));
        s2->addItem(MW_LIST,F("HB 10/1500"));
        s2->addItem(MW_LIST,F("HB 10/1000"));
        s2->addItem(MW_LIST,F("HB 10/500"));
        s2->addItem(MW_LIST,F("HB 10/250"));
        s2->addItem(MW_LIST,F("HB 10/100"));

  Serial.println(mem);
  mem=tree.freeRam();
  tree.getErrorMessage(true);

      s2=tree.addMenu(MW_VAR,s1,F("HB D5"));
        s2->addVar(MW_LIST,&listb2);                          //create a variable of type "option list".. 
        s2->addItem(MW_LIST,F("HB 5/750"));
        s2->addItem(MW_LIST,F("HB 5/250"));
        s2->addItem(MW_LIST, F("HB 5/125"));
        s2->addItem(MW_LIST,F("HB 5/62.5"));
        s2->addItem(MW_LIST,F("HB 5/25"));
  
  Serial.println(mem);
  mem=tree.freeRam();
  tree.getErrorMessage(true);
  
    s2=tree.addMenu(MW_VAR,s1,F("HB D2.5"));
      s2->addVar(MW_LIST,&listb3);                          //create a variable of type "option list"..       
      s2->addItem(MW_LIST,F("HB 2.5/187.5"));
      s2->addItem(MW_LIST,F("HB 2.5/62.5"));
      s2->addItem(MW_LIST,F("HB 2.5/31.25"));
      s2->addItem(MW_LIST,F("HB 2.5/15.625"));
      s2->addItem(MW_LIST,F("HB 2.5/6.25"));

  Serial.println(mem);
  mem=tree.freeRam();
  tree.getErrorMessage(true);


    s2=tree.addMenu(MW_VAR,s1,F("HB D1"));
      s2->addVar(MW_LIST,&listb4);                          //create a variable of type "option list"..       
      s2->addItem(MW_LIST,F("HB 1/30"));
      s2->addItem(MW_LIST,F("HB 1/10"));
      s2->addItem(MW_LIST,F("HB 1/5"));
      s2->addItem(MW_LIST,F("HB 1/2.5"));
      s2->addItem(MW_LIST,F("HB 1/1"));
  
  Serial.println(mem);
  mem=tree.freeRam();
  tree.getErrorMessage(true);
  
    s1=tree.addMenu(MW_VAR,r, F("Cargas HV"));
      s1->addVar(MW_LIST,&listv);                          //create a variable of type "option list".. 
      s1->addItem(MW_LIST,F("HV125"));          
      s1->addItem(MW_LIST,F("HV100"));          
      s1->addItem(MW_LIST,F("HV50"));          
      s1->addItem(MW_LIST,F("HV30"));          
      s1->addItem(MW_LIST,F("HV20"));          
      s1->addItem(MW_LIST,F("HV10"));          
      s1->addItem(MW_LIST,F("HV5"));          
      s1->addItem(MW_LIST,F("HV3"));          
      s1->addItem(MW_LIST,F("HV2"));          
      s1->addItem(MW_LIST,F("HV1"));          
  
  Serial.println(mem);
  mem=tree.freeRam();
  tree.getErrorMessage(true);
  
      s1=tree.addMenu(MW_VAR,r,F("Zooms"));            //add a terminal node (that is "variable");   
        s1->addVar(MW_LIST,&listz);                          //create a variable of type "option list".. 
        s1->addItem(MW_LIST,F("140x"));          
        s1->addItem(MW_LIST,F("70x"));          
        s1->addItem(MW_LIST,F("44x"));          
        s1->addItem(MW_LIST,F("40x"));          
        s1->addItem(MW_LIST,F("20x"));          
        s1->addItem(MW_LIST,F("14x"));          
  
  Serial.println(mem);
  mem=tree.freeRam();
  tree.getErrorMessage(true);
  
      s1=tree.addMenu(MW_VAR,r,F("Reads"));            //add a terminal node (that is "variable"); 
        s1->addVar(MW_LIST,&listl);                          //create a variable of type "option list".. 
        s1->addItem(MW_LIST,F("One reads"));          
        s1->addItem(MW_LIST,F("Two reads"));          

  Serial.println(mem);
  mem=tree.freeRam();
  tree.getErrorMessage(true);
  
tree.navButtons(UP_BOTTON_PIN,DOWN_BOTTON_PIN,LEFT_BOTTON_PIN,RIGHT_BOTTON_PIN,ESCAPE_BOTTON_PIN,CONFIRM_BOTTON_PIN);
  }

I use the last MENWIZ (1.2)

Sorry for my bad english... :cold_sweat:

Now It's Ok. My Mistake was on inicialcing variables... if the variable of the MW_LIST is not 0 not appear nothing in the menu...

By the way ... for the error 132 which gives me sometimes referred getErrorMessage?

Thanks :wink:

All:

Wonder if anyone is having issues with using MenWiz and Timer1. The following code in the setup routine chokes MenWiz and the LCD will not display anything.

// initialize Timer1
	cli();          // disable global interrupts
	TCCR1A = 0;     // set entire TCCR1A register to 0
	TCCR1B = 0;     // same for TCCR1B
	
	// set compare match register to desired timer count:
	OCR1A =  arrayRPM[rpm]; //t_output;
	// turn on CTC mode:
	TCCR1B |= (1 << WGM12);
	// Set CS10 and CS12 bits for 1024 prescaler:
	TCCR1B |= (1 << CS10);
	TCCR1B |= (1 << CS11);
	// enable timer compare interrupt:
	TIMSK1 |= (1 << OCIE1A);
	// enable global interrupts:
	sei();

Ok, look like I found the problem. It is this line which causes the problem. Not really sure how to fix. Suppose the value from the array needs to be cast.?

OCR1A =  arrayRPM[rpm]; //t_output;

brunialti:
EDIT 30 AUGUST 2013
Please find here attached the version 1.3_1 beta.
It contains the MW_MENU_INDEX error fixed.

I have finally got round to trying V1.3.1 and I seem to be struggling with the editable text field as there is no example of how to use it in the docs.

Can you just post an example of how you would use this. I'm declaring a char array as the variable and then passing it as (MW-EDIT_TEXT, &textVariable). Your notes state it only works with 6 button mode. I am using a custom callback to implement my 6 buttons via a matric keypad, so should that still work OK for the text entry?

I also found what could be a bug in MW_LIST. If I set my variable as a Byte then things go 'wonky' and I can't select the actual menu items to change. If I simply change my global variable to an int then it all works again. Where you only need a value of 0-255, such as a PWM brightness value for a LED, it means you are using 16 bits for each variable instead of just 8. Although not really an issue for me, as I am using 1284P with 16kB SRAM, it could make a difference to use on 328P with only 2Kb SRAM.

I'm using MW_LIST in order to define my own toggle selections, such as Off/On, Enabled/Disabled, rather than a Boolean as True/False. Also for where there is more than one selection. When I set a default value of 0 for an option I would expect Index 0 to be the default shown in the menu but I actually get nothing displayed at all until I press a left/right key to get to the options.

i.e. for 3 options of Red (0), Green (1), Blue (3), if I set the default to 0 I would expect Red to be the initial selection, but I get a blank row as if nothing is set.

MENWIZ also doesn't deal with Unsigned int or Longs at all. I seem have to use Signed Ints, which mean that you lose a range of values due to the +/1 nature. Any plans to add support for more number types?

One final thing that I am currently looking at. I am setting up a unit as an nRF to Ethernet/Wireless gateway. As part of this I need to be able to set IP Addresses. At the moment the only way I can see of doing it is to set 4 bytes and edit them as seperate MW_AUTO_BYTE items.It would be great to have a dedicated item for this kind of variable, but can you think of any better way to handle it than I have already thought of.

Sorry for all the questions but your help is appreciated, as this is a great library.

I have been thinking about the comment regarding MW_EDIT_TEXT in 4 button mode.

This should be possible as I have seen it before.

Now, I've not been able to try the text edit yet but I assume that left/right move through letter positions and up/down change the letter at each position (or vice versa; up/down move position and left/right change letter).

For 4 button mode you only have two navigation buttons, plus escape and confirm, so...

Enter the menu item and then you can move the letter positions with left/right. Flash the current position by inverting the character negative/positive at a particular speed. Press confirm to go into edit character and then make that position negative while you are in edit mode, then left/right to change the character. Press confirm to enter the chosen character and go back to slow flashing so you can move left/right to next character.

On a rotary encoder this would mean you turn left/right to select character position, press to edit character, left/right to change character, press to enter current character and go back to move position mode.

I was banking on just using a 17 element char array to hold a maximum 16 characters (16x2 LCD) but I guess you could have scrolling on that field (if you don't already) so you can edit longer strings than can fit on a 16 or 20 character width screen.

Hi all,

just a probably very stupid question.

Imagine, you want to create menus in multiple languages.
So I want to create files containing e.g. the menu items in English and one file containing the German menus.

I am not able to use variable menu texts like this:

const char* Root_Menu = "Main Menu";
const char* Sub_Menu1 = "Sub Menu1";

r=menu.addMenu(MW_ROOT,NULL,F(Root_Menu)); //create a root menu at first (required)
s1=menu.addMenu(MW_SUBMENU,r,F(Sub_Menu1));

I am getting following message:

MDK_Menu_sample.ino: In function ‘void setup()’:
MDK_Menu_sample:52: error: initializer fails to determine size of ‘__c’

Do you have an idea how to implement variable menu text?

Kind regards,
Kay

Thanks to brunialti for the wonderful menu library. I'm a beginner to the world of ardunio and working on a small sketch that can set the date/date/time function on a DS1307 RTC. Has anybody succeeded in setting the time using the menu functions ?

I'd appreciate any help on this.

Thanks
Ritzy

Hello,
first of all, I would like to thank you @brunialti for this great lib.
I am trying it and it is very simple to understand and to setup in comparison to others.

I encountered a problem I was not able to fix tough.

I have variables that can vary in a very big range. So I want to increase or decrease faster if I keep the button pressed.
In the way your lib is done (or by examples) I could not find a way to do this.
So I went to another button library (ClickButton) and set up in a way that the array butState[buttons] is set one or zero when I keep it pressed. This is working, but the display do not get it this way. If I have one pulse per second, the variable increases like 100 pulses per second.

Can you please explain how the timings will be understood if I do so? DO you see a way of doing what I want?

I will not attach the hole code, since it is too big (I can if you want). But here is the navMenu function:

//Start test codes for Button with ClickButton
int navMenu() // called from menu.draw
{
  /*
   As soon as a button is pushed the first time flag 1 is set to HIGH and if the buttonnumber is not 0 then a timer is started.
   The menu action then should only be performed once.
   After 2000 msecs the flag will be set to LOW and a new buttonpush can be processed.
   Menu action is blocked for 400 msec even if the same button is being kept pressed for 2000 msecs by flag2.
   */
  int buttonpressed = 0;

  if (butState[0] == 1){
	  return MW_BTU;
	  buttonpressed =1;
  }
  if (butState[1] == 1){
	  return MW_BTD;
	  buttonpressed =1;
  }
  
  if (butState[2] == 1){
	  return MW_BTC;
	  buttonpressed =1;
  }
  if (butState[3] == 1){
	  return MW_BTE;
	  buttonpressed =1;
  }
  
 
  if (buttonpressed == 0){
	  return MW_BTNULL;
	  Serial.println("null");
  }
}

I know for a fact that the butState is tougleling accordingly. I never receive the "null" tough. I do not know why.
I am kinda newbe, so maybe there is something obvious I am missing.
Thanks for any help.
Best regards

jnetode:
I have variables that can vary in a very big range. So I want to increase or decrease faster if I keep the button pressed.
In the way your lib is done (or by examples) I could not find a way to do this.
So I went to another button library (ClickButton) and set up in a way that the array butState[buttons] is set one or zero when I keep it pressed. This is working, but the display do not get it this way. If I have one pulse per second, the variable increases like 100 pulses per second.

OK, I managed to do this.
I realized I could increase or decrease the variables without the Menwiz library. SO I just had to figure, if I was in the menu screen I wanted to change, than the buttons should in/decrease the variables directly instead of passing the values to the menwiz navigation function.
So I used the menu.cur_menu->cod value to find this out and it worked flawlessly. 8) 8) 8)

jnetode:
So I used the menu.cur_menu->cod value to find this out and it worked flawlessly. 8) 8) 8)

Hi, could you please post some example code as to how you did it? I am working on a code for positioning an antenna and ideally I wouldn't like to step through 3600 and 900 positions... Alternatively I was thinking of using a rotaru=y encoder and some speed detection.
Very rough and not yet working, starting out with code from http://hifiduino.wordpress.com/2010/10/29/arduino-rotary-encoder-one-line-debounce-code/:

  while (rotating){
     delay(2);  // debounce by waiting 2 milliseconds
     duration = millis() - now;
       if(duration>50){
         increment = 0.1;
       } else {
         increment = 1.0;
       }
           // (Just one line of code for debouncing)
       if (digitalRead(RotEnc1) == digitalRead(RotEnc2)){  // CCW
         foo = foo - increment;
       } else {                          // If not CCW, then it is CW
         foo = foo + increment;
       }
       lcd.clear();
       rotating=false; // Reset the flag
       now=millis();
   }

Thank you very much

Hello!

Trying to make a menu for my brewing system. I have some problems when building the menu where only some parts of the menu
show when I do as in example2 but works in example1. I'm Arduino UNO with 16x2 LCD.

Example1 (this one works):

r = menu.addMenu(MW_ROOT, NULL, F("Main Menu"));
    s1 = menu.addMenu(MW_SUBMENU, r, F("Mash Menu"));

    s2 = menu.addMenu(MW_VAR, s1, F("Set Mash Temp"));
      s2->addVar(MW_AUTO_INT, &mashTemp, 0, 120, 1);

    s2 = menu.addMenu(MW_VAR, s1, F("Start Mashing"));
      s2->addVar(MW_ACTION, setStateMash);

   s1 = menu.addMenu(MW_VAR, r, F("Start Boil"));
    s1->addVar(MW_ACTION, setStateBoil);

Example 2 (does not work, only get Mash menu and only one submenu "Set Strike" and "Start to Strike"):

  r = menu.addMenu(MW_ROOT, NULL, F("Main Menu"));

  s1 = menu.addMenu(MW_SUBMENU, r, F("Mash Menu"));
    s2 = menu.addMenu(MW_VAR, s1, F("Set Strike Temp"));
      s2->addVar(MW_AUTO_INT, &strikeTemp, 0, 120, 1);

    s2 = menu.addMenu(MW_VAR, s1, F("Start to Strike"));
      s2->addVar(MW_ACTION, setStateStrike);

    s2 = menu.addMenu(MW_VAR, s1, F("Set Mash Temp"));
      s2->addVar(MW_AUTO_INT, &mashTemp, 0, 120, 1);

    s2 = menu.addMenu(MW_VAR, s1, F("Start Mashing"));
      s2->addVar(MW_ACTION, setStateMash);

   s1 = menu.addMenu(MW_VAR, r, F("Start Boil"));
    s1->addVar(MW_ACTION, setStateBoil);

Any tips or suggestions are very welcome..

Cheers, RKT

lnxrkthkr:
Hello!

Trying to make a menu for my brewing system. I have some problems when building the menu where only some parts of the menu
show when I do as in example2 but works in example1. I'm Arduino UNO with 16x2 LCD.

Example1 (this one works):

r = menu.addMenu(MW_ROOT, NULL, F("Main Menu"));

s1 = menu.addMenu(MW_SUBMENU, r, F("Mash Menu"));

s2 = menu.addMenu(MW_VAR, s1, F("Set Mash Temp"));
     s2->addVar(MW_AUTO_INT, &mashTemp, 0, 120, 1);

s2 = menu.addMenu(MW_VAR, s1, F("Start Mashing"));
     s2->addVar(MW_ACTION, setStateMash);

s1 = menu.addMenu(MW_VAR, r, F("Start Boil"));
   s1->addVar(MW_ACTION, setStateBoil);





Example 2 (does not work, only get Mash menu and only one submenu "Set Strike" and "Start to Strike"):


r = menu.addMenu(MW_ROOT, NULL, F("Main Menu"));

s1 = menu.addMenu(MW_SUBMENU, r, F("Mash Menu"));
   s2 = menu.addMenu(MW_VAR, s1, F("Set Strike Temp"));
     s2->addVar(MW_AUTO_INT, &strikeTemp, 0, 120, 1);

s2 = menu.addMenu(MW_VAR, s1, F("Start to Strike"));
     s2->addVar(MW_ACTION, setStateStrike);

s2 = menu.addMenu(MW_VAR, s1, F("Set Mash Temp"));
     s2->addVar(MW_AUTO_INT, &mashTemp, 0, 120, 1);

s2 = menu.addMenu(MW_VAR, s1, F("Start Mashing"));
     s2->addVar(MW_ACTION, setStateMash);

s1 = menu.addMenu(MW_VAR, r, F("Start Boil"));
   s1->addVar(MW_ACTION, setStateBoil);




Any tips or suggestions are very welcome.. 

Cheers, RKT

Got ERROR 132 and I had about 140 freeRam but when I shrunk my sketch
(removing a lot of debugging) it started to work! \o/

How can I get MENWIZ 1.2.0 to return to the root menu when exiting the UserScreen?
I treid adding "cur_menu=root;" in the if-loop on line 328 of MENWIZ.cpp ( if((cur_mode==MW_MODE_USRSCREEN)&&(ret!=MW_BTNULL)){ ) , which does return me to the root menu, but I can only navigate to the menu I was in before the UserScreen was displayed.