Go Down

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

waski

If I knew how, I wouldn't be asking  ;) I found calls in the end of .cpp file. I'll try to change them somehow ... someday.

brunialti

That is up to you!
It has nothing to do with the menus and it is dependent from the external device.
Be carefull to add more libraries, if you are using an UNO, as MENWIZ requires quite a lot of space, as many, if not all, ther menu managers...
Sorry  :)

waski

I'll try to manage this somehow. I'm using custom board with two ATmega2560 and external EEPROM so I've plenty of room for libraries ;)

Petertje

I am having trouble with the startup screen, if I use it then my Arduino will not start any further then the startup screen.

brunialti

check the memory.
which version are you using?

Petertje


check the memory.

Did not check yet, it runs without the splashscreen, just one of your demo's.


which version are you using?


It happens in menwiz 1.2 and 1.3, I see no difference

brunialti

Ok. I'll check asap (not before end of week) as i'm abroad.
Thanks

djrm

#457
Oct 23, 2013, 08:37 pm Last Edit: Oct 23, 2013, 08:45 pm by djrm Reason: 1
Greetings brunialti and other Menwiz users,

I'm using Menwiz as a front end for a time critical application and may have discovered an unexpected problem.

The execution time of the menu.draw() function is usually quite quick but when the user defined callback is executed then it takes very much longer. I have verified this with a minimal user function and the result is the same.

For example when the menu is being displayed the main loop cycle time is several milliseconds but during the time when the user function is executed the main loop cycle time is about 100 mS.

Is this a known problem? Is some function blocking which should not be? Perhaps it is one of the libraries used not working as expected. I dont know the answer, I'll be having a look myself in a day or two when I have time.

I'm testing with TestAllVarTypes example modified to use the LiquidCrystal_I2C library, The problem is seen in library 1.2 and 1.3 beta versions.

My timing is done by calling a led flash statement in the main loop like this:

Code: [Select]

int  timerPin = 8;
...
  pinMode(timerPin, OUTPUT);              //Setup the pin
...
void loop(){
  digitalWrite(timerPin, digitalRead(timerPin) ^ 1);
  menu.draw();
  //PUT APPLICATION CODE HERE (if any)
  }


When the menu is being shown the LED flashes faster than can be seen by the naked eye,  when the user function is executed the led blinks on and off several times per second.

One more thing, The slow cycle time is present immediately after a reboot until a menu key has been pressed.

I'd be glad to hear your thoughts on this matter.
Best regards, David.

brunialti

The elapsed timefor each draw() call depends from the content of the user function, if any.
The call time of the user function itself is minimal.
So let me see the code...

djrm

Hello, thanks for answering.

The application changes are just what I have listed above. The LCD library is different however - it is the I2C version.
I have added a few defines to mnap the buttons onto my Mega256 board etc. Otherwis the code is the example code.

Code: [Select]
//MENWIZ ESAMPLE
#include <Wire.h>
//INSERT ALL THE FOLLOWING 5 INCLUDES AFTER INCLUDING WIRE LIB
#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 ARDUINO PINS FOR THE NAVIGATION BUTTONS
//#define UP_BUTTON_PIN       9
//#define DOWN_BUTTON_PIN     10
//#define LEFT_BUTTON_PIN     7
//#define RIGHT_BUTTON_PIN    8
//#define CONFIRM_BUTTON_PIN  12
//#define ESCAPE_BUTTON_PIN   11
#define UP_BUTTON_PIN       42
#define DOWN_BUTTON_PIN     46
#define LEFT_BUTTON_PIN     50
#define RIGHT_BUTTON_PIN    34
#define CONFIRM_BUTTON_PIN  26
#define ESCAPE_BUTTON_PIN   30

//Create global object menu and lcd
//menwiz menu;
//LiquidCrystal_I2C lcd(0x20, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Addr, En, Rw, Rs, d4, d5, d6, d7, backlighpin, polarity
/*-----( Declare Constants )-----*/
#define I2C_ADDR    0x20  // Define I2C Address for the PCF8574T
//---(Following are the PCF8574 pin assignments to LCD connections )----
// This are different than earlier/different I2C LCD displays
#define BACKLIGHT_PIN  3
#define En_pin  2
#define Rw_pin  1
#define Rs_pin  0
#define D4_pin  4
#define D5_pin  5
#define D6_pin  6
#define D7_pin  7

#define  LED_OFF  1
#define  LED_ON  0

menwiz menu;
/*-----( Declare objects )-----*/ 
LiquidCrystal_I2C  lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);

int  timerPin = 8;

//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;

  pinMode(timerPin, OUTPUT);              //Setup the pin to
  Serial.begin(19200); 
 
  // have a look on memory before menu creation
  Serial.println(sizeof(menwiz));
  mem=menu.freeRam();
 
  // inizialize the menu object (20 colums x 4 rows)
  menu.begin(&lcd,20,4);
  //menu.setBehaviour(MW_MENU_INDEX,false);   

  //create the menu tree
  r=menu.addMenu(MW_ROOT,NULL,F("MAIN MENU"));              //create a root menu at first (required)
    s1=menu.addMenu(MW_SUBMENU,r,F("MEASURE SUBMENU"));     //add a child (submenu) node to the root menu
    //s1->setBehaviour(MW_MENU_COLLAPSED,true);         
   
      s2=menu.addMenu(MW_VAR,s1,F("list"));            //add a terminal node (that is "variable");
          s2->addVar(MW_LIST,&tp);                          //create a variable of type "option list"..
          s2->addItem(MW_LIST,F("option 1"));               //add option to the OPTION LIST
          s2->addItem(MW_LIST,F("option 2"));               //add option to the OPTION LIST
          s2->addItem(MW_LIST,F("option 3"));               //add option to the OPTION LIST
          s2->addItem(MW_LIST,F("option 4"));               //add option to the OPTION LIST
          s2->addItem(MW_LIST,F("option 5"));               //add option to the OPTION LIST
//          s2->setBehaviour(MW_SCROLL_HORIZONTAL,true);   
//          s2->setBehaviour(MW_LIST_2COLUMNS,true);         
//          s2->setBehaviour(MW_LIST_3COLUMNS,true);         

      s2=menu.addMenu(MW_VAR,s1,F("float var"));       //add a terminal node (that is "variable");
          s2->addVar(MW_AUTO_FLOAT,&f,11.00,100.00,0.5); //create a variable of type "float number"...
                                                         //...associated to the terminal node and bind it to the app variable "f" of type float
      s2=menu.addMenu(MW_VAR,s1,F("byte var"));        //add a terminal node (that is "variable");
          s2->addVar(MW_AUTO_BYTE,&b,25,254,10);         //create a variable of type "byte"...
                                                         //...associated to the terminal node and bind it to the app variable "b" of typr byte
      s2=menu.addMenu(MW_VAR,s1,F("boolean var"));     //add a terminal node (that is "variable");
          s2->addVar(MW_BOOLEAN,&bb);                    //create a variable of type "boolean"
                                                         //...associated to the terminal node and bind it to the app variable "bb" of type boolean
    s1=menu.addMenu(MW_VAR,r,F("WRITE TO SERIAL"));             //add a terminal node (that is "variable") create an "action" associated to the terminal node...
      s1->addVar(MW_ACTION,act);                         //the act function as default will be called when enter button is pushed
//      s1->setBehaviour(MW_ACTION_CONFIRM,false);         //...if you don't need action confirmation

    s1=menu.addMenu(MW_VAR,r,F("SAVE TO EPROM"));           //add a terminal node (that is "variable") create an "action" associated to the terminal node...
      s1->addVar(MW_ACTION,savevar);                     //the act function as default will be called when enter button is pushed

    s1=menu.addMenu(MW_VAR,r,F("LOAD FROM EEPROM"));        //add a terminal node (that is "variable") create an "action" associated to the terminal node...
      s1->addVar(MW_ACTION,loadvar);                     //the act function as default will be called when enter button is pushed

  //declare navigation buttons (required)
  menu.navButtons(UP_BUTTON_PIN,DOWN_BUTTON_PIN,ESCAPE_BUTTON_PIN,CONFIRM_BUTTON_PIN);

  //(optional)create a user define screen callback to activate after 10 secs (10.000 millis) since last button push
  menu.addUsrScreen(msc,10000);

  //(optional) create a splash screen (duration 5.000 millis)with some usefull infos the character \n marks end of LCD line
  //(tip): use preallocated internal menu.sbuf buffer to save memory space!
//  sprintf(menu.sbuf,"MENWIZ TEST V %s\n.Free mem. :%d\n.Used mem  :%d\n.Lap secs  :%d",menu.getVer(),menu.freeRam(),mem-menu.freeRam(),5);
//  menu.addSplash((char *) menu.sbuf, 5000);
  }

void loop(){
  digitalWrite(timerPin, digitalRead(timerPin) ^ 1);
  menu.draw();
  //PUT APPLICATION CODE HERE (if any)
  }

// user defined callbacks
// WARNING avoid sprintf usage: it requires > 1.5 kbytes of memory!
void msc(){
  static  char buf[7];
  strcpy(menu.sbuf,"User screen"); //1st lcd line
  strcat(menu.sbuf,"\nUptime (s): ");strcat(menu.sbuf,itoa((unsigned int)(millis()/1000),buf,10));//2nd lcd line
  strcat(menu.sbuf,"\nFree mem  : ");strcat(menu.sbuf,itoa((int)menu.freeRam(),buf,10));//3rd lcd line
  strcat(menu.sbuf,"\n"); //4th lcd line (empty)
  menu.drawUsrScreen(menu.sbuf);
  }
 
void act(){
  Serial.println("FIRED ACTION!");
}

void savevar(){
  menu.writeEeprom();
  }
 
void loadvar(){
  menu.readEeprom();
  }


I don't think I've altered anything else but I'm about to check just to be sure.
Tnank you again for your efforts, David.

brunialti

I tend to exclude that the strcat calls are the problem.
So the only place where the delay can occour is inside the drawUsrScreen.
The function is defined as following:

Code: [Select]
void menwiz::drawUsrScreen(char *scr){
  int i,j,k;
  ERROR(0);
  for (int i=0,j=0,k=0;(k<row)&&(i<(strlen(scr)+1));i++){
    if((scr[i]==MW_EOL_CHAR)||(scr[i]==0)){
      memset(&buf[min(j,col)],' ',col-j);
      buf[col]=0;
      lcd->setCursor(0,k);
      lcd->print(buf);
      j=0;
      k++;
      }
    else{
      buf[j]=scr[i];
      j++;
      }
    if(k==row)
      return;
    }
  }


the setCursor and print functions are supposed to be the slowest.
What do you mean when you say that you changed the lib ? Is the used lib one of the malpartida's libs?

djrm


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.

djrm

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.

brunialti

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

brunialti

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.

Go Up