Go Down

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

brunialti

I am not sure the comparison make sense, as the two libs seems quite different (e.g. graphic vs character), but why not?
Menwiz has three main sets of funcs. One to define the structure (add***). One to check the device (i.e. buttons by now). One to draw the menu (draw***).
In theory it could be possible to deep the third layer abstraction in order to use graphic rendering.
I would like to keep menwiz as simple as possible. At this stage it is not really a full fledged lib and the code is poor (unclean, redundant unstyled) due to the short time I spent to build it up.

olikraus

Quote
MENWIZ requires LiquidCrystal_I2C

Will there be support for the standard Arduino LiquidCrytal lib?

Oliver

brunialti

Menwiz uses only the following methods, that are the same in the two libs:
  lcd->init();
  lcd->setBacklight(HIGH);
  lcd->setCursor(x, y);
  lcd->noCursor();
  lcd->createChar(0,z);
  lcd->print();
  lcd->write()
The lcd object is created in the sketch and not in the library (the labrary stores only the pointer to the object), therefore there should'nt be a problem. I did'nt test as I have not the lcd in my hand.
I made a small change in the menwiz.h file (the new version in github in minutes!). You will find the #define I2C. If you comment that line, the compiler include the standard LiquidCrystal lib instead of LiquidCrystal_I2C. I did'nt test it yet. If you can, please let me know.
Better solutions are welcome!



liudr

olikraus has library that works on both glcd and character lcds. There must be tricks to how that can be done ;)

I am thinking about expanding to different displays too. My first step was to expand to different input devices.

A competition or cross comparison is definitely welcome! I'm sure I can win the "easy to get started" award since my library can run one one-line function calls.

brunialti

Do you real want test such a young baby as menwiz against such a mature and wise counterparts ?  :)
My lib goals are: near asynchronous, simple coding, user defined screens (splash and default) and "overwrite callbacks" (input device scan, actions/triggers ...).
I have more work to do. If somebody is interested I am ready to go on.
I would be pleased if some could test the lib with standard LiquidCrytal.
I have noy 4/8 wires LCD available at the moment.

liudr


Do you real want test such a young baby as menwiz against such a mature and wise counterparts ?  :)
My lib goals are: near asynchronous, simple coding, user defined screens (splash and default) and "overwrite callbacks" (input device scan, actions/triggers ...).
I have more work to do. If somebody is interested I am ready to go on.
I would be pleased if some could test the lib with standard LiquidCrytal.
I have noy 4/8 wires LCD available at the moment.



Not to challenge you, just comparison as I suggested. So you are going into the dynamic and callbacks direction. You could get one of my shields to test out the library ;)

olikraus

I recently failed to support a user. It turned out that M2tklib is still too complicated (will i win the price for the most complicated lib?).

I would like to make M2tklib more simple. So I try to understand other approaches. And I like to see fresh libs like yours. For me a comparison about the programming interfaces would be useful (not about features). What would be the most easy approach for a beginner? What do others think about these different approches regading the programming API?

If we find something common which can be implemented by each of the libs, then i think i could get a better understanding of each programming model. And maybe other users can rate the programming effort for each API.

My idea was something about this: On a 16x4 (or 20x4) display 4 selectable lines. The user selects one line and the display shows the line number (0-3). No scrolling, just a cursor which is used to select one of four lines. Is this possible with MENWIZ?

Oliver


fm

Looking at the direction you are going with the MENWIZ library, I think it would be worth while looking at the New LiquidCrystal library. Since you are using a pointer to the LCD, you would benefit from it by using a pointer to its base class LCD (a pure abstract LCD class). This would give you support for a wide range of drivers controlling Hitachi based LCDs.

Not only is it 3.5 times faster than the original LIquidCrystal library, it also gives you the flexibility of being compatible with a wide range of LCDs out there without changing a single line of code.
   

liudr

Just FYI, I am thinking about a slightly different approach compared with a base class approach. For input devices, I totally did base class approach and built my library from ground up to support all possible input devices. For displays, I'm thinking about using ANSI escape codes to control everything. I will need to write support for every new type of display so all my UI command to the displays will be entirely string commands. :)

brunialti

#24
Apr 07, 2012, 10:50 am Last Edit: Apr 07, 2012, 11:30 am by brunialti Reason: 1
At this time MENWIZ needs only few methods of the LiquidCrystal class. It should work with any lib providing such methods. I cannot test it immediately as I have not a standard 4/8 wires lcd in my hand, but I'll do it after easter time.
I include the two different libraries depending on the #define I2C (first line in MENWIZ.h file). Another way could be difefrentiate MENWIZ.h in MENWIZ_I2C.h and MENWIZ.h.

The code needed to implememt the example Olikraus suggested is as following. Most part of the code is just to implement the screen showing selection choice.
An other usefull comparison could be done on a real request arose in this forum (see the GOLF code example here above).

Code: [Select]
     
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <buttons.h>
#include <MENWIZ.h>

menwiz menu;
LiquidCrystal_I2C lcd(0x27,20,4);

int choice=0;

void setup(){
 _menu *r;

 menu.begin(&lcd,20,4);
 menu.navButtons(9,10,7,8,12,11);

 r=menu.addMenu(MW_ROOT,NULL,"TEST MENU");          
   r->addVar(MW_LIST,&choice);                    
   r->addItem(MW_LIST,"Line 1");            
   r->addItem(MW_LIST,"Line 2");          
   r->addItem(MW_LIST,"Line 3");    
   r->addItem(MW_LIST,"Line 4");    
         
 menu.addUsrScreen(msc,3000);
 }

void loop(){
 menu.draw();
 }

//USER SCREEN SHOWED AFTER 3 SECS SINCE LAST BUTTON PUSH
void msc(){
 Serial.println(choice);
 lcd.setCursor(0, 0);
 lcd.print("Total uptime ");lcd.print(millis()/1000);
 lcd.setCursor(0, 1);
 lcd.print("Choice is ");lcd.print((int) choice);
 lcd.setCursor(0, 2);
 lcd.print("                    ");
 lcd.setCursor(0, 3);
 lcd.print("                    ");
 }



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:

Code: [Select]

#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:
Code: [Select]

#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:

Code: [Select]

#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.
   

brunialti

#26
Apr 07, 2012, 01:11 pm Last Edit: Apr 07, 2012, 01:39 pm by brunialti Reason: 1
It seems really easy. I'll try. It would be very nice to have a broad range of compatible devices.

backbone

I cant find the MENWIZ.h file on the web  :smiley-roll:
Did I missed something?
Github does not bring it either as was mentioned in oen of the previous posts.

Paco
Never to old to learn and I learn every day

brunialti

https://github.com/brunialti
Try this . I can see it on my mobile

olikraus

Quote
The code needed to implememt the example Olikraus suggested is as following.


So, here is the M2tklib version. You will see, that the menu is defined outside any procedure. It is placed directly in the data area (PROGMEM) of the controller. The other difference is the "choice" variable. In M2tklib, buttons only call a sub-procedure. The result must be assigned manually in this case.  In the MENWIZ example, it seems that choice is automatically connected to the line number.

Regarding the discussion about LiquidCrystal variants: M2tklib uses a message based interface to an "output handler". This is " m2_gh_lc" for LiquidCrystal (see below). Replacing this with  "m2_gh_glcd", will render the output for GLCD v3. By writing such a handler, any character or graphical output device could be used.

Oliver

Code: [Select]

//  Menu.pde
// http://arduino.cc/forum/index.php/topic,99693.15.html

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

//=========================================================
// fotward declaration
extern M2tk m2;

//=========================================================
// keys
uint8_t uiKeySelectPin = 10;
uint8_t uiKeyNextPin = 9;

//=========================================================
// global variable: selected line
uint8_t choice = 0;

//=========================================================
// display result
M2_U8NUM(result_menu, NULL, 0, 255, &choice);

//=========================================================
// line selection

// callbacks for the buttons
void fn_line1(m2_el_fnarg_p fnarg) { choice = 0;  m2.setRoot(&result_menu); }
void fn_line2(m2_el_fnarg_p fnarg) { choice = 1;  m2.setRoot(&result_menu); }
void fn_line3(m2_el_fnarg_p fnarg) { choice = 2;  m2.setRoot(&result_menu); }
void fn_line4(m2_el_fnarg_p fnarg) { choice = 3;  m2.setRoot(&result_menu); }

// layout of the menu
M2_BUTTON(el_line1, NULL, "Line 1", fn_line1);
M2_BUTTON(el_line2, NULL, "Line 2", fn_line2);
M2_BUTTON(el_line3, NULL, "Line 3", fn_line3);
M2_BUTTON(el_line4, NULL, "Line 4", fn_line4);
M2_LIST(list_lines) = { &el_line1, &el_line2, &el_line3, &el_line4 };
M2_VLIST(line_menu, NULL, list_lines);

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

//=========================================================
// M2tklib setup
// m2_es_arduino: Arduino event source
// m2_eh_2bs: Two button handler
// m2_gh_lc: Character subsystem
M2tk m2(&line_menu, m2_es_arduino, m2_eh_2bs, m2_gh_lc);


//=========================================================
// Arduino setup()
void setup() {
  // Connect M2tklib to LCD
  m2_SetLiquidCrystal(&lcd, 16, 4);
 
  // Apply keys
  m2.setPin(M2_KEY_SELECT, uiKeySelectPin);
  m2.setPin(M2_KEY_NEXT, uiKeyNextPin);
}

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



Go Up