Go Down

Topic: MENWIZ: yet another character lcd menu wizard library (Read 79 times) previous topic - next topic


Probably I packed the readme 1.0.0 in the MENWIZ_1_0_1.zip and uploaded the latter readme.txt file in latest commit source db ...
Github when you download by "Download as zip" features, gathers all the file of the latest code commit and create a new zip file with commit id in the file name.
Anyway use the MENWIZ_1_0_1.zip as this help me to be sure about the version you are using.


Hi Bruno,

Switched to 1.0 lib and needed to change some code first to get rid of error messages.
I looked in the manual ans saw the sample code for custom buttons.
Also looked at DANNIX his sample code.
Still not sure if I fully understand Dannix his code and if using interrupt is really needed.

If Dannix can explain I would be happy.


Sorry if this is too late to be of any help. You don't have to use an interrupt. My hardware handles debounce and when any button analog value is seen it triggers an interrupt to ensure I don't miss button presses. But you don't have to have an interrupt. As has been stated, I use 3 buttons and a EXIT menu item with custom function to trigger the ESCAPE button press.

Without over complicating, you need to write a function to read your buttons and pass the relevant answer to MENWIZ when it calls your nav function.


HI Dannix,

Never too late :)
I had some time shortage.
I could test after Bruno cleaned two code lines and now the display starts in the menu and not returns to the usermneu screen after 3 seconds.

For the software key calls I use this code, but not working in void loop.
Code: [Select]

// NAVIGATION MANAGEMENT & DRAWING ON LCD. NOT BLOCKING has to be the first in the void loop

// ++++ Buttons 10 in total ++++++
  buttonValue = analogRead(0);   // read the input pin 0
  // internal 20K ohm pullup is enabled on analog pin 0 (54).
  int navMenu(){ //called by menwiz.draw()
  if(buttonValue >= 920 and buttonValue <= 930 )
    MW_BTU //Up button
    //digitalWrite(led7Pin, HIGH);
    delay (200); // 910
    else if(buttonValue >= 820 and buttonValue <= 835)
    MW_BTC // Confirm button
    //digitalWrite(led7Pin, HIGH);
    delay (200);// 827
    else if(buttonValue >= 725 and buttonValue <= 740)
    MW_BTD //Down button
    //digitalWrite(led7Pin, HIGH);
    delay (200); // 731
    else if(buttonValue >= 630 and buttonValue <= 645)
    MW_BTE //Escape button
    //digitalWrite(led7Pin, HIGH);
    delay (200); // 637
    else if(buttonValue >= 535 and buttonValue <= 550)
    switchpointYValue = switchpointYValue - stepsQValue;
    delay (200); // 542
    else if(buttonValue >= 440 and buttonValue <= 455)
    switchpointXValue = switchpointXValue - stepsQValue;
    delay (200); //446
    else if(buttonValue >= 340 and buttonValue <= 355)
    speedstartValue = speedstartValue - stepsQValue;
    delay (200); //347
    else if(buttonValue >= 235 and buttonValue <= 250)
    speedstartValue = speedstartValue + stepsQValue;
    delay (200); //241
    else if(buttonValue >= 125 and buttonValue <= 140)
    switchpointXValue = switchpointXValue + stepsQValue;
    delay (200); //131
    else if(buttonValue >= 5 and buttonValue <= 20)
    switchpointYValue = switchpointYValue + stepsQValue;
    delay (200); //13

Never to old to learn and I learn every day



I had some little time to trouble shoot more on the menu.
When I reboot I first get the splashscreen but then the userscreen should pop up.
However the screen with the menu tree structure pop ups even though there is no button pressed as this still does not work! :-)

Any idea where to look for?

Never to old to learn and I learn every day


not enough infos.
Can you run the lib examples correctly?


Yes all variable sample runs fine.
Can not distinquish the difference.

Never to old to learn and I learn every day


send me the code, but please let it be runnable commenting all the calls to external devices I cannot provide.
I can test it only tomorrow or monday


Hi Bruno, recently found your menuwiz library, Its powerful, flexible, simple to use, and best of all is runs asyncronously letting other pgm code run.

I plan to use it with an i2C LCD display that has button inputs, it comes with its own LCD_I2C front end interface to the WIRE lib. Its called LCDI2Cw lib from web4robot.  The lcd display uses a Hitachi HD44780 chipset.  It has the following functions:
// available functions
  void clear();
  void home();                            // set cursor to row 0, col 0

  void noDisplay();
  void display();
  void noBlink();
  void blink();
  void noCursor();
  void cursor();
  void cursorLeft();
  void cursorRight();   
  void scrollDisplayLeft();
  void scrollDisplayRight();
  void createChar(uint8_t, uint8_t[]);
  void setCursor(uint8_t, uint8_t);         // col, row, rows 0 to 3, column 0 to 19

  unsigned int firmware();
  void keypadMode(uint8_t mode);            // 0 = 4x4 butron matrix, 1 = 8 separate buttons, default is 0
  unsigned int keypad ();
  unsigned int remoteCtr ();
  void backlight(uint8_t light);            // 0 to 250, default is 70
  void contrast(uint8_t contrast);          // 0 to 100, default is 20

Can I replace the following includes in your example pgms to this to use this i2clcd lib?
#include <Wire.h>
#include <LCDI2Cw.h>
#include <MENUWIZ.h>

unsigned char i2cAddress = 0x4C;  // LCD module I2C address
const int myrows = 4;
const int mycols = 20;
LCDI2Cw lcd(mycols, myrows, i2cAddress);  // this lcd object is used my menuwiz

1. Will I need to modify your MENUWIZ.h and cpp files to use my LCDI2Cw lib and remove references to LiquidCrytsal and buttons?

2. I also plan to add my own button handler (addUsrNav(navMenu), my question is where to I put my code to read the buttons so the button handler called from the menu.draw() function can process my button presses. It looks like I should add a call to my readButtons() function in the main loop just after the call to menu.draw().

Is this correct?




the lib use the following calls to the iquidcrystal library:


I cannot see the begin, write and createChar methods, therefore I have to say the tweeking is not so easy.
A part from the above (not secondary) problem the usage of the internal buttons of your device should be quite easy:

1 - create a function (say mydevice) returning an int value mapping the internal button code by calling your device functions
2 - declare mydevice as the new button "reader" using MENWIZ addUserNav using a call as following: menu.addUsrNav(mydevice);

If yo are using 4 buttons with a custom device you need also a patch (it will be fixed soon) as defined in the readme.txt


Hi Bruno, thanks for your reply.

It looks like the LCDI2C2 lib differs from the Liquidcrystal_I2c lib only in the begin and setBacklight and contrast routines

Here is my changes to your Test_all_variables example that I tried to use the LCDI2C2w lib

#include <Wire.h>
#include <LCDI2Cw.h>

//#include <LCD.h>
//#include <LiquidCrystal_I2C.h>
#include <buttons.h>
#include <MENWIZ.h>
//#include <EEPROM.h>    // to be included only if defined EEPROM_SUPPORT

#define UP_BUTTON_PIN       9
#define DOWN_BUTTON_PIN     10
#define LEFT_BUTTON_PIN     7
#define RIGHT_BUTTON_PIN    8
#define ESCAPE_BUTTON_PIN   11

//Create global object menu and lcd
menwiz menu;
//LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Addr, En, Rw, Rs, d4, d5, d6, d7, backlighpin, polarity

unsigned char i2cAddress = 0x4C;  // LCD module I2C address
const int myrows = 2;
const int mycols = 16;
// initialize the library with the number of columns and rows
LCDI2Cw lcd(mycols, myrows, i2cAddress);

//instantiate global variables to bind to menu
int      tp=0;
float    f=26.0;
boolean  bb=0;
byte     b=50;

void setup(){
  _menu *r,*s1,*s2;
  _var *v;
  int  mem;

  // have a look on memory before menu creation
  // inizialize the menu object (20 colums x 4 rows)

Here are my changes to Menuwiz.h
#ifndef MENWIZ_h
  #define MENWIZ_h

//#define EEPROM_SUPPORT     //uncomment if you want to use the readEeprom and writeEeprom methods!

#include <Wire.h>

//#include <LCD.h>
//#include <LiquidCrystal_I2C.h>

#include <buttons.h>

Here are my changes to Menuwiz.cpp
void menwiz::begin(void *l,int c, int r){


  // for liquidcrystal_i2c
  //lcd->begin(c,r);  //  LCD size
  // end for liquidcrystal_i2c

  //  for LCDI2Cw         // gives error: MENWIZ.h:196: error: ISO C++ forbids declaration of 'LCD' with no type
  // end for  LCDI2Cw

  // for both
  // end for both

  sbuf=(char*)malloc(r*c+r); if(sbuf==NULL) ERROR(900);
  buf =(char*)malloc(2*c);   if(buf==NULL) ERROR(900);

With these changes i get the following compile time errors:
E:\arduino-1.0.1\libraries\MENWIZ/MENWIZ.h:198: error: ISO C++ forbids declaration of 'LCD' with no type
E:\arduino-1.0.1\libraries\MENWIZ/MENWIZ.h:198: error: expected ';' before '*' token

The LCDI2cw lib backlight routine takes a value from 0 to 255
The LCDI2Cw lib contrast routine takes a value from 0 to 100
and the LCDI2Cw lib begin routine takes no parameters and only issues a Wire.begin() command and a lcd.clear command.

Can you suggest what I can try to clear the forbids declaration of 'LCD' with no type  error?

I can email you the LCDI2Cw library files if you would like. I just need your email or another way to send you the files.

I have many sketches that use this LCDI2Cw lib and would like to continue to use it with your menu system.




Aug 25, 2012, 09:19 pm Last Edit: Aug 25, 2012, 09:23 pm by brunialti Reason: 1
as far as I can see, you need to:
- include LCDI2Cw.h instead of LiquidCrystal.h both in MENWIZ.h and MENWIZ.cpp! ( or at least I cannot see that includes...).
- replace   "LCD*     lcd;"  declarations with "LCDI2Cw *lcd" in MENWIZ.h
- the write calls with print(s) in MENWIZ.cpp

please use # mark for code !


Thank you Bruno,

Sorry for not posting the code correctly, I will remember for next time.

The test sketch now compiles, I had to change a line in Menuwiz.cpp in the begin routine to say:
lcd=(LCDI2Cw*)1; rather than lcd=(LCD*)1;

I will test the code tonight and let you know how well it works.

Thanks again for your help.



Ok. Remember the patch, if you are using only 4 buttons:

The method addUsrNav allows only to replace the 6 buttons model, that is the actions performed are those expected by the 6 buttons model.
The next release of addUsrNav release will allows to explicitly set the replaced model (4 or 6 buttons mode).
With release 1.0.1 if you want to use addUsrNav you can patch with the following lines in the sketch code

Code: [Select]
extern byte MW_navbtn;


// in setup() after addUsrNav call

MW_navbtn=4;  // force 4 buttons mode



I found the cause but not the solution.
In my original code I use already your suggestion for 4 button call as you ammended the code for me.
I undressed my code step by step using the all variable sample.
At one point it was exactly the same except for 2 lines of code....................

This causes the screen not jump to userscreen.
When I // the line I get the userscreen to show. As soon as I remove the // then the userscreen does not show.
Code: [Select]
// initialize the menu object (20 colums x 4 rows LCD)
  menu.addUsrNav(navMenu); // @@@@@@@@@@@@@@@@@@@@@@ this causes the  userscreen not to show!!!!!!!!!!!!!1
  MW_navbtn=4;  // force 4 buttons mode

Never to old to learn and I learn every day


Update on using Menwiz library with the LCDI2cw library.

It Works.
2 edits to menwiz.h, 5 edits to menwiz.cpp and it works Great.
I have successfully run the menwiz example sketch Test_all_var_types using the standard 6 button menu.navButtons method.

Menwiz is a powerful, flexible, easy to use library. Many thanks to the author for writing it and especially for his help in identifying the needed code changes to work with a different LCD I2C library other than LiquidCrystal_I2C.


Go Up