Go Down

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

brunialti

#290
Jan 02, 2013, 02:47 pm Last Edit: Jan 02, 2013, 04:42 pm by brunialti Reason: 1
Hi.
for all people interested in "odd" button models (that is 3 or 5 button models) I give you a *very simple* patch to implement it now. The next version will consolidate the change.

Inside the library is implemented a "logical level" where are defined all actions performed  after a button push.
Those functions are private members of class menwiz,  so it is necessary to make just one  change to the MENWIZ.h file, moving  the  definition of actBTE() from private to public. That is all.

In your sketch you can implement a menu entry acting exactly as the escape button as following (example):

Code: [Select]
     s2=menu.addMenu(MW_VAR,s1,F("Back"));     //add a terminal node (that is "variable");
         s2->addVar(MW_ACTION,&bte);                    //create a variable of type "action"
         s2->setBehaviour(MW_ACTION_CONFIRM,false);         // you don't need action confirmation to emulate Escape button!!!


EDIT:
Code: [Select]

void bte(){
menu.actBTE();
}





Silverdog63

Ciao Roberto,
This is what I tried, but I got "57: error: 'bte' was not declared in this scope". I don't know what I did wrong, it was just a test I don't need it at the moment. The Menu frame it's working, I just have to think and put my variable in. (P.S. my project is to control with a stepper the height of my Saw, Planner and shaper ... http://www.bricosergio.it/combinate/Sicar/furore300i%20NEW.htm ... )

Code: [Select]

//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("SAW"));                        //add a submenu node 1 to the root menu
    s2=menu.addMenu(MW_VAR,s1,F("ABS Height"));                         //add a terminal node in the menu tree (that is "variable");
      s2=menu.addMenu(MW_VAR,s1,F("REL Move"));                         //add a terminal node in the menu tree (that is "variable");
        s2=menu.addMenu(MW_VAR,s1,F("Zero"));                         //add a terminal node in the menu tree (that is "variable");
          s2=menu.addMenu(MW_VAR,s1,F("Back"));     //add a terminal node (that is "variable");
            s2->addVar(MW_ACTION,&bte);                    //create a variable of type "action"
            s2->setBehaviour(MW_ACTION_CONFIRM,false);         // you don't need action confirmation to emulate Escape button


And in the MENWIZ.h file:
Code: [Select]

class menwiz{
public:
           menwiz();
  void     begin(void *,int, int);
  void     addSplash(char *,int);
  void     addUsrScreen(void (*f)(), unsigned long);
  void     addUsrNav(int (*f)(), int);
  void     setBehaviour(MW_FLAGS,boolean);
  _menu*   addMenu(int, _menu *, MW_LABEL);
  void     draw();
  void     drawUsrScreen(char *);       //draw user screen(s)
  int      getErrorMessage(boolean); //if arg=true, err message is printed to the default Serial terminal, otherwise the function returns error code only
  int      freeRam();
  void     actBTE();


Silverdog63

Ciao,
This is a "perfecly" working ( at least I hope ) start base of MENWIZ to be used with the Arduino Lcd Keypad Shield ( http://www.robotshop.com/cytron-lcd-keypad-shield-arduino.html )

Code: [Select]

// +++++++ Libaries included
#include <Wire.h>
#include <LiquidCrystal.h>
//INSERT ALL THE LIBARIES AFTER INCLUDING WIRE LIB (MENWIZ request)
#include <LiquidCrystal_I2C.h>
#include <buttons.h>
#include <MENWIZ.h>
#include <EEPROM.h>

// Create global object for menu and lcd
menwiz menu;
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
/*LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Addr, En, Rw, Rs, d4, d5, d6, d7, backlightpin, polarity 4 x 20 LCD
*/
boolean wr=0; // Instantiate global variables to bind to menu

const int buttonPin = A0;             // 4 button switch circuit input connected to analog pin 0
const int led13Pin = 13;              // the number of the LED output pin

boolean buttonBlock = 0;
boolean buttonAct = 0; // flag 1
boolean stopMenu = 0; // flag 2
byte buttonPressed = 0;  // which button was pressed
byte lastButtonPressed = 0; // prev button pressed
int buttonValue = 0;  // read value from analog port for the 4 navigation pushbuttons
long menuOffTime = 0;  //used for timer

extern byte MW_navbtn;  //needed to run the software key navigation in Menwiz



void setup()
{
  Serial.begin(9600);                       // Output to serial writing

  digitalWrite((54), HIGH);  // enable the 20k internal pullup for MEGA board for analog port A0
  // digitalWrite((A0), HIGH);  // enable the 20k internal pullup for UNO based board for analog port A0

  //++++++++++++++++++++Menu and LCD 
  char b[84];
  _menu *r,*s1,*s2;

  // initialize the menu object ( 4 x rows x 20 colums LCD)
  menu.begin(&lcd,16,2); //initialize the menwiz menu object passing the lcd object and the colums and rows params
  menu.addUsrNav(navMenu,4);
  MW_navbtn=4;  // force 4 or 6 buttons mode for menu navigation -> MW_navbtn=4; or MW_navbtn=6;

  //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("SAW"));                        //add a submenu node 1 to the root menu (control the heigh of my Saw)
  s2=menu.addMenu(MW_VAR,s1,F("ABS Height"));                         //add a terminal node in the menu tree (that is "variable"); (should move at a certain mm height)
  s2=menu.addMenu(MW_VAR,s1,F("REL Move"));                         //add a terminal node in the menu tree (that is "variable"); (should move of a certain mm the height)
  s2=menu.addMenu(MW_VAR,s1,F("Zero"));                         //add a terminal node in the menu tree (that is "variable");

  //---------------
  s1=menu.addMenu(MW_SUBMENU,r,F("PLANNER"));                    //add a submenu node 2 to the root menu (control the heigh of my Planner)
  s2=menu.addMenu(MW_VAR,s1,F("ABS Height"));                         //add a terminal node in the menu tree (that is "variable"); (should move at a certain mm height)
  s2=menu.addMenu(MW_VAR,s1,F("REL Move"));                         //add a terminal node in the menu tree (that is "variable"); (should move of a certain mm the height)
  s2=menu.addMenu(MW_VAR,s1,F("Zero"));                         //add a terminal node in the menu tree (that is "variable"); (should set the zero)

  //---------------
  s1=menu.addMenu(MW_SUBMENU,r,F("SHAPER"));                    //add a submenu node 3 to the root menu
  s2=menu.addMenu(MW_VAR,s1,F("ABS Height"));                         //add a terminal node in the menu tree (that is "variable"); (should move at a certain mm height)
  s2=menu.addMenu(MW_VAR,s1,F("REL Move"));                     //add a terminal node in the menu tree (that is "variable"); (should move of a certain mm the height)
  s2=menu.addMenu(MW_VAR,s1,F("Zero"));                     //add a terminal node in the menu tree (that is "variable"); (should set the zero)

  /*
  //++++++ Splash screen +++++++
 
  sprintf(menu.sbuf,"TEST minimum menu\nwith 4 or 6\nanalog push buttons\n",1);
  menu.addSplash((char *) menu.sbuf, 1000);

  //++++++ Userscreen ++++++++++
  // create an user define screen callback to activate after X secs since last button push
  menu.addUsrScreen(msc,3000);
  */
  pinMode(led13Pin, OUTPUT);                // initialize the led as a output control pin
}

void loop()   
{
// NAVIGATION MANAGEMENT & DRAWING ON LCD. NOT BLOCKING has to be the first in the void loop
  menu.draw();
/*
  put your regular code here
   */
  readButtons();
}

//  ++++++ functions +++++++

void readButtons()

// ++++ Control 4 buttons ++++
{
  lastButtonPressed = buttonPressed;

  /*
  Analog values representing the pushbutton value are depending on the resitor value used.
   Test the values first with the serial.monitor
   */
  buttonValue = analogRead(buttonPin); //analog value to simulate the pushed buttons
 
  if(buttonValue >= 850)
  {
    buttonPressed = 0;
    noButtonPressed(); // is calling an extra fucntion
  }
  else  if(buttonValue >= 380 & buttonValue <= 450)
  {
    buttonPressed = 4;
    buttonAct = 1; // set the menu flag1
  }
  else if(buttonValue >= 200 & buttonValue <=300)
  {   
    buttonPressed = 3;
    buttonAct = 1; // set the menu flag1
  }
  else if(buttonValue >= 0 & buttonValue <=50)
  {   
    buttonPressed = 2;
    buttonAct = 1; // set the menu flag1
  }
  else if(buttonValue >= 80 & buttonValue <=150)
  {   
    buttonPressed = 1;
    buttonAct = 1; // set the menu flag1
  }
}

int noButtonPressed()
{
  return MW_BTNULL;
}

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 2000 msec even if the same button is being kept pressed for 2000 msecs by flag2.
   */

  long menublockTime = millis();

  if (buttonAct == 1 && buttonPressed != 0 && stopMenu == 0)  // we have a state were we process a menu navigation step once and block it for 2 secs
  {
    digitalWrite(led13Pin,HIGH);  // set timer led ON
    menuOffTime = menublockTime  + 2000; //start the timer. You can change this blocking time to your convenience but do not make it lower aa 200 msecs
    stopMenu = 1;

    switch (buttonPressed)
    {
    case 1: // Up
      return MW_BTU;
      break;
    case 2: // Confirm
      return MW_BTC;
      break;
    case 3: // Down
      return MW_BTD;
      break;   
    case 4: // Escape
      return MW_BTE;
      break;
    }
  }

  if (menuOffTime != 0  &&  menublockTime  > menuOffTime)  //  Reset of the timer so a new menu action can be processed
  {
    buttonAct = 0; // resets the flag 1
    buttonPressed = 0;
    menuOffTime = 0;  // resets timer to zero
    stopMenu = 0;
    digitalWrite(led13Pin,LOW);  // set timer led OFF
  }
}
/*
// user defined default screen.
void msc()
{
  sprintf(menu.sbuf,"User screen\nUptime (s): %ld\nFree mem  : %d\n\n",millis()/1000,(int)menu.freeRam());
  menu.drawUsrScreen(menu.sbuf);
}*/


P.S.
/*
   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 2000 msec even if the same button is being kept pressed for 2000 msecs by flag2.
   */
This is why sometimes I had to push twice a button to operate .... didn't wait enough !  :smiley-red:

brunialti

#293
Jan 02, 2013, 04:40 pm Last Edit: Jan 02, 2013, 04:44 pm by brunialti Reason: 1
You've got the 57 error because I' forgot to insert the bte function of course :-)
Code: [Select]

void bte(){
menu.actBTE();
}


sorry...

Silverdog63

Roberto, it's me who apology ... if I was just a bit smarter, I could be able to understand what was missing.
Thank you very much for your work.
Sergio

Go Up