MENWIZ: yet another character lcd menu wizard library

I'm considering to add a variable pinpointing method, that is: use EEPROM library to save actual values of the user defined variables in order to let settings be available even after an arduino restart.
It is not very clear to me if the 1024 bytes available on at328 are the same used by F() metafunction.
In this case I have to hand off or consider different implementation ways.

By the way ... floating points variables are now implemented and will be available on next prerelease.

Wow, long thread!

fm, brunialti, olikraus, just to side track this thread once more, I've done some improvement to my library and now it has these neat features. By no means can I support newbies with these features that can't even be turned into generic library function calls but to more experienced people trying to make money with their products, these features add values. Hope I can use fund I get from professional help to support the free end of my library (actually all library function calls are free to use but how you use them to make advanced features are not yet open).

http://arduino.cc/forum/index.php/topic,101503.0.html

I'll be adding more features including variable length of list (say you adjust one parameter and the list expands to show its details).

Liudr, I saw the video. Impressive.

My goal with MENWIZ is to return some to the community. I've got lot of support from the social and as far as I can I would like to give back my contribute. I have some ideas about new clever functionalities and cleaner code and architecture. If I had time I would even like to write a code generator.But I do'nt know if there are interested candidate users. With a little bit more powerfull platform I would be able to do really interesting things...

The point you arise about the balance between free and charged efforts is also a good point. I think it is easier on the hw side.
On my side (sw) i see very difficult to get money from. By now I'm surprised how short has been the learning curve in Arduino. Of course I've been helped by long programming experience.

Anyway, untill i'll get fun i'll develop menwiz and other libs... This is not o promise , it is a menace ... :slight_smile:

Great! I maintain half a dozen arduino libraries and this one (phi_prompt) gets most attention since it has practical use in products. I'm trying to support the beginners with simple function calls that needs not much programming skills. I'm also helping intermediate users with standard function calls. But I can't support advanced features freely since that would be too much work especially when someone "that doesn't know which end of the equal sign does what" wants fancy features with the advanced features but is not in the right coding skill level to do it.

I posted the version 0.4.0 at GitHub - brunialti/MENWIZ: ARDUINO LCD menu library: short user code to manage complex menu structures and here attached
Added support for float and byte variable data types.
Feedback are welcome.

MENWIZ_0_4_2.zip (517 KB)

I've just tried the menwiz library and I'm totally satisfied :slight_smile:
clean, concise code, support for New LiquidCrystalLibrary, plus it's easily hackable if you want to insert your own input routines (just replace the code of menwiz::scanNavButtons() with your own, in the .cpp file)

I have one question though: I see that the examples take about 16K of flash. Could this be lowered? For example, I'm using a 595 3-wire LCD so I suppose I don't need to include the Wire.h library(?). But when I don't include it I get an error. In general, could I further squeeze menwiz's footprint?

I'm happy it can be usefull for you.
Wire is not directly required by menwiz but isi called by LiquidCrystalLibrary (at least on the I2c version). I did'nt test with a 3wire lcd so i'm not 100% sure. The wire include is called not only by the sketch but also by MENWIZ.h. I frankly do'nt know if it is required by LiquidCrystalLibrary LCD.h (the virtualized lcd managemnt layer) inlcude.
I implemented a menwiz version using flash memory for menu item strings. it save some precious sram. About flash ram: I unfortunately do not think the total amount is significantly squeezable , due to the coding approach (preallocated objects vectors). I could save some memory with a more aggressive dynamic allocation, but it could increase small sketches (sketches with small menu structures) footprint due to the added pointer tables.
You can carefully tweak the following values inMENWIZ.h, provided you understand exactly what they mean (use menwiz::getErrorMessage while debugging)

// DIMENSIONS (DIMENSIONAL LIMITS OF STATICALLY ALLOCATED STRUCTURES)
// ---------------------------------------------------------------------------

#define MAX_MENU       15   //maximum number of nodes (absolute supported max number of addMenu calls)
#define MAX_OPTXMENU   5    //maximum number of options/submenus for each node (max number of addItem call for each menu item) 
#define MAX_BUFFER     84   //dimension=columns x rows + rows. CHANGE IT IF LCD IS BIGGER/SMALLER THAN 4X20 CHARS

The footprint in Leonardo board shoud be even worse: as it manage USB/serial directly you must add 4k more (but that is true for all sketches ...)

By the way I'm currently trying to network integrate a raspberrypi with arduino, using mqtt protocol. I can assure that arduino is really simple to use .... :slight_smile:

Hi brunialti,
I am also interested in your library for my solar tracker circuit, but i am also using ShiftRegLCD 3 wire 20x4 LCD. Is their any chance to use your library. Actually i am very thin in using more pins for LCD as my sun tracker almost consumed all the pins on 328PU IC.

The LCD is connected to DIY 3 wire 12x12 keypad..

Liuder, your lcd library is good but if you can post some very simple example it will be beneficial. one question, i am using 3 wire LCD using ShiftRegLCD library, do your library support it?

The current MENWIZ library is using the ¨New LiquidCrystal" library, a.k.a. "LCD library" you should be able to connect all the supported LCD drivers that it supports.

Currently the New LiquidCrystal library supports the following LCD drivers: I2C, SR latching and non-latching configurations 2 and 3 wires, 4 bit parallel and 8 bit parallel LCDs.

The way the New LiquidCrystal was developed makes adding new LCD drivers very easy. If you use LCD abstract class references in our project or other libraries, it is a trivial plug-and-play configuration.

Here is a link to its wiki: https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/Home. You will also find wiring schematics for all supported configurations.

I suggest to try the new LiquidCrystal lib alone with your lcd befor using MENWIZ.
By the way if you have lots of devices can I suggest to expore the I2C bus?

@straddlethemoon
If you want use your own input routine, instead of replacing menwiz::scanNavButtons() code (breaking the library compatibility) you can use the menwiz::addUsrNav to declare your own routine. After declaration the library will use your code instead of the built-in one ...

Hi,
Can i use this library with your Menu?
http://code.google.com/p/arduinoshiftreglcd/http://code.google.com/p/arduinoshiftreglcd/

In the url it is stated that the library is now included in the New LiquidCrystal library. As far as this statement is true, you should be able to use it with your LCD. I'm not able to test it directly.
I suggest at first to build some sort of "Hello World" sketch able to drive your LCD using the before mentioned library. When it works, you can add to your sketch the MENWIZ and the other required libs , with the same order suggested in the examples (this is a Arduino peculiarity I'll never be acquainted to...).

Ciao!

thank you for your reply
actually 32k of flash is plenty of space for most projects, and it's better to have good, reliable code at the expense of memory. It is only one particular project I'm working with which uses a ton of libraries (soft serial, tiny gps, lcd, keypad, SD card etc) and takes about 20k as it is now that made me think that I can't add menwiz although it would make things easier

Of course is up to you. I think it can be shrinked a little bit (say 1/2 k max). But I need time to work about. Consider that if menwiz will use flash memory for strings (in order to let some ram free for variables, parameters and so on) it will use flash memory and it could affect the available space.
Consider Mega board o other with same processor.

fm:
That's the nice thing about the "New LiquidCrystal" library, it already supports a wide range of LCD controllers:

  • I2C base on the PCF8574 or compatible
  • 4bit and 8bit parallel
  • ShiftRegister: 3wire, 2wire, 1wire (beta)

Your code would look something like this:

#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C myLCD (0x27);  // Base address of IO expander

void setup ()
{
   menu.begin ( &myLCD, 20, 4 );
   ...
}




Assuming that your menu class makes the following modification:


#include <LCD.h>

void menu::begin ( LCD *iLCD, uint8_t cols, uint8_t rows )




With this LCD library you will get almost 32 fps as opposed to the one you are currently using that barely does 10fps.

Now if you want to use for example a 4bit parallel interface, the only thing that would change in you code is the creation of the LCD object:



#include <LiquidCrystal_I2C.h>

LiquidCrystal myLCD ( 12, 11, 5, 4, 3, 2 ); // Rs, E, D4, D5, D6, D7

void setup ()
{
   menu.begin ( &myLCD, 20, 4 );
   ...
}



Not a lot to do in your code really.

You are kind enough for explaining the codes. I would be really very thankful if you please elaborate changes for ShiftRegLCD say 3-wire LCD example skecth like you posted above.
Regards

You can find the initialisation code in the project wiki for all supported LCD drivers, simple schematic and associated int code.

Thank You:) I am working on it.. Very good explanation there.. One more favour i need .. I am using 6-Buttons that are attached to single analoge pin with different resistors...Your NavigateButton command shows each button connected to digital pins which takes 4 minimum or 6 maximum number of digital pins:(...
I am using following code for getting the values of each button:

// ===================================================================
// Convert ADC value to key number
//read the keyboard routine
int get_key(unsigned int keyboardValue){
  int k;
   keyboardValue = analogRead(ANALOG_PIN); // read the value (0-1023)
   if (keyboardValue <25){k=0; return k;}
   if ((keyboardValue >25) && (keyboardValue < 67)){k = 1;return k;}
   if ((keyboardValue >67) && (keyboardValue < 108)){k = 2;return k;}
   if ((keyboardValue >108) && (keyboardValue < 162)){k = 3;return k;}
   if ((keyboardValue >162) && (keyboardValue < 253)){k = 4;return k;}
   if ((keyboardValue >253) && (keyboardValue < 361)){k = 5;return k;}
   if ((keyboardValue >361) && (keyboardValue < 479)){k = 6;return k;}
 
  //NOTE: the values used above are all halfway between the value obtained with each keypress in previous test sketch 
   
 //  while (keyboardValue > 25) {
   //  delay (100);
   //  keyboardValue = analogRead(ANALOG_PIN); // read the value (0-1023)
  // }//wait until key no longer being pressed before continuing
       
   
   //Serial.println(keypressed);      // print the value back to the Serial view window on your PC
   delay(100);                     // wait 100 milliseconds before the next loop
                     }
  //end of read the keyboard routine
// new key detection routine, without delays!

int     lastKeyEvent = 0;
int     curKeyEvent  = 0;
int     keyToReturn  = 0;
boolean keyToProcess = false;
int     adc_key_in   = 0;
int detectKey()
{
    keyToReturn = -1;
    adc_key_in = analogRead(ANALOG_PIN);       // read the value from the sensor  
    curKeyEvent = get_key(adc_key_in);	// convert into key press
    if (curKeyEvent != lastKeyEvent)
    {
        if (!keyToProcess)
        {
            lastKeyEvent = curKeyEvent;
            keyToProcess = true;
        }
        else
        {
            keyToReturn = lastKeyEvent;
            lastKeyEvent = -1;
            keyToProcess = false;
        }
    }
    return keyToReturn;
}

and this is in my Void loop() function:

int keyEvent = detectKey();
 Serial.println(keyEvent);
 if (keyEvent >= 0){
  switch (keyEvent){

Is it possible to use analog buttons in MENWIZ?..If yes then this shall be a wonderful Menu:)

Khalid,
I am not sure to understand your needs. I try to resume the procedure.
if you want to use your own device to replace the standards buttons managed by MENWIZ and Buttons libraries (and declared with navButtons functions) you need to write your own function and to declare it to MENWIZ library using addUsrNav method.
The user defined function will replace the following internal one:

int menwiz::scanNavButtons(){ 
  if(btx->BTU.check()==ON){
    return MW_BTU;}
  else if (btx->BTD.check()==ON){
    return MW_BTD;}
  else if (btx->BTL.check()==ON){
    return MW_BTL;}
  else if (btx->BTR.check()==ON){
    return MW_BTR;}
  else if (btx->BTE.check()==ON){
    return MW_BTE;}
  else if (btx->BTC.check()==ON){
    return MW_BTC;}
  else
    return MW_BTNULL;
  }

The user defined function must return one of the following integer values, defined in MENWIZ.h:

// BUTTON CODES
// ----------------------------------------------------------------------
#define MW_BTNULL      30   //NOBUTTON
#define MW_BTU         31   //UP
#define MW_BTD         32   //DOWN
#define MW_BTL         33   //RIGTH
#define MW_BTR         34   //LEFT
#define MW_BTE         35   //ESCAPE
#define MW_BTC         36   //CONFIRM

The returned integer code represent the last pushed button, if any, or MW_BTNULL if no button has been pushed since last call.
The user defined function, as the internal scanNavButtons, is called once for every time the method menwiz::draw is called.
The returned code will activate the behavior associated to the pushed button (or no behaviour if no button has been pushed).
Resuming
in case of any custom device (as analog button or any other) you must:

  • write your own function in the sketch (the name is up to the user)
  • the function must return one of the 7 values above, depending on the pushed button (or the simulated ones)
  • the function must be declared to MENWIZ with the method addUsrNav

WARNING: THE USER DEFINED FUNCTION SIMULATING BUTTONS HAVE TO RETURN PUSHED BUTTON CODES JUST ONCE, AS IT WOULD A STANDARD DIGITAL BUTTON! OTHERWISE THE LIBRARY ASSUME MULTIPLE BUTTON PUSHES, ONE FOR EACH TIME THE FUNCTION RETURNS THAT "BUTTON" CODE....

That should be all.
Does it make sense in your case?.

Here attached please find a tour guide to the library.
It can be usefull to decide if and how to use MENWIZ

QUICK TOUR.pdf (111 KB)