MENWIZ: yet another character lcd menu wizard library

okay got it:

int x=strlen(menu.sbuf);
then

i will place the Moon at x-1.
Regards

nice work khalid.
I suggest to submit to arduino blog.

brunialti:
nice work khalid.
I suggest to submit to arduino blog.

Sure, i shall put that once it complete...

Ciao a tutti,
I am a very beginner (it's my first week on Arduino), no experience in programming, I already read the guide and the book "Getting Started With Arduino 2ndEd" ..... but .... it's still a long way ....
Anyway, what I am trying to do is to make an actuator with a stepper (and a relative mechanical transmission) to move the height of a the saw in a table saw. I need to set the height to a certain amount of mm, or to move of a certain amount on mm.
Now my starting problem is to use Menwiz with the classic LCD Keypad Shield (16x2) that have 5 analog buttons (it's perfectly ok to use only 4).
(From this tutorial which is perfecly working I took some setup:

http://tutorial.cytron.com.my/2011/08/12/project-1-“hello-world”-on-lcd/)

#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); //this is the working pins

[sup]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 //this is what I replaced
[/sup]

and from Backbone post « Reply #188 on: September 27, 2012, 07:17:31 PM » I took his example changing the button parameters:

// +++++++ 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("SET1"));                        //add a submenu node 1 to the root menu
  s2=menu.addMenu(MW_VAR,s1,F("MD"));                         //add a terminal node in the menu tree (that is "variable");
  s2=menu.addMenu(MW_VAR,s1,F("BR"));                         //add a terminal node in the menu tree (that is "variable");
  s2=menu.addMenu(MW_VAR,s1,F("RH"));                         //add a terminal node in the menu tree (that is "variable");

  //---------------
  s1=menu.addMenu(MW_SUBMENU,r,F("SET2"));                    //add a submenu node 2 to the root menu
  s2=menu.addMenu(MW_VAR,s1,F("CP"));                         //add a terminal node in the menu tree (that is "variable");
  s2=menu.addMenu(MW_VAR,s1,F("DB"));                         //add a terminal node in the menu tree (that is "variable");
  s2=menu.addMenu(MW_VAR,s1,F("SQ"));                         //add a terminal node in the menu tree (that is "variable");

  //---------------
  s1=menu.addMenu(MW_SUBMENU,r,F("SET3"));                    //add a submenu node 3 to the root menu
  s2=menu.addMenu(MW_VAR,s1,F("RS"));                         //add a terminal node in the menu tree (that is "variable");
  s2=menu.addMenu(MW_VAR,s1,F("RCALIB"));                     //add a terminal node in the menu tree (that is "variable");
  s2=menu.addMenu(MW_VAR,s1,F("SCALIB"));                     //add a terminal node in the menu tree (that is "variable");

/*
  //++++++ 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 >= 700)
  {
    buttonPressed = 0;
    noButtonPressed(); // is calling an extra fucntion
  }
  else  if(buttonValue >= 470 & buttonValue <= 600)
  {
    buttonPressed = 4;
    buttonAct = 1; // set the menu flag1
  }
  else if(buttonValue >= 300 & buttonValue <=420)
  {    
    buttonPressed = 3;
    buttonAct = 1; // set the menu flag1
  }
  else if(buttonValue >= 100 & buttonValue <=200)
  {    
    buttonPressed = 1;
    buttonAct = 1; // set the menu flag1
  }
  else if(buttonValue >= 10 & buttonValue <=50)
  {    
    buttonPressed = 2;
    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);
}

that was the code for the buttons on the "helloWorld" example (it's a completely different approach from the Backbone one:

int analogPin = A0;
int adc_key_old;
int adc_key_in;
int NUM_KEYS = 5;
int key=-1;
int adc_key_val[5] ={30, 150, 360, 535, 760 };  

//omitted some functions , then ...

int get_key(unsigned int input)
{
	int k;
    
	for (k = 0; k < NUM_KEYS; k++)
	{
		if (input < adc_key_val[k])
		{
           
    return k;
        }
	}
    
    if (k >= NUM_KEYS)
        k = -1;     // No valid key pressed
    
    return k;
}

I am not asking to check all the code, but can somebody check if I did some noticeable error in manipulating the code ?
Thanks from a beginner.
Sergio

I'm planning on having a play with this as it could be the solution to a manu system we need to provide user settings saved to EEPROM.

Reading through it seems that it can use a 4 button or 6 button set up.

6 Buttons - Up, Down, Left, Right, Select, Back
4 Buttons - Up, DOwn, Select, Back

What about 5 Button option, like what you'd have on some default shields:-

5 Buttons - Up, Down, Left, Right, Select

This doesn't have a specific button for the Back option, but couldn't the library incorporate a visual replacement. When in Menu's or on items you'd have a last option of 'BACK' which you just Select as with any other.

Actually, I guess this could also provide you a 3 button option too, along the lines of your existing 4 button plus the 'BACK' display for selection.

the visual back solution is interesting. I should'nt be really a problem to implement it and it could be delivered in next release.
About solutions without confirmation: they have a deeper impact, neverthless I could consider to implement such an option as well

@silverdog
at a first glance I see some point to check:

  • the following line is not necessary: MW_navbtn=4;
  • when you use addusernav the declared callback should be in charge with button checking and code returning. The call to readButtons() should be therefore inside the callback funcion , not in the loop. the code works the same, but is more polite
  • you defined the menu framework, but after each creation of menu nodes of type MW_VAR you need to create the variable with addVar in order to let the menu working.

I suggest to start from the example, adapt it to your LCD device at first and when it works properly, modify the menu framework to your design and after introduce the button managemnt

First of all, thanks for the help and ... Happy new year !
In my humble opinion the 5 option button (analog) option will be great, because it would allow all the users of the lcd shield (which is very common) to benefit of the Menwiz. The 5 buttons menu control is widely used (I have it on my Nikon camera, on the onkyo AVR ampli ecc.) you move "up" and "down" on the menus/options you enter in the sub menus with the "right" button or with "ok" (select) you choose the option by pressing "ok" (select) and the left button is for "exit" (go back).
the 3 button menus the visual back solution.

Now for my particular case .... It Works !! (well quite works ... -:slight_smile: )
two of the button are working and two are nor, in any case the menu is working so I just have to trick around the values of the buttons

  /*
  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 >= 700)
  {
    buttonPressed = 0;
    noButtonPressed(); // is calling an extra fucntion
  }
  else  if(buttonValue >= 470 & buttonValue <= 600)
  {
    buttonPressed = 4;
    buttonAct = 1; // set the menu flag1
  }
  else if(buttonValue >= 300 & buttonValue <=420)
  {    
    buttonPressed = 3;
    buttonAct = 1; // set the menu flag1
  }
  else if(buttonValue >= 100 & buttonValue <=200)
  {    
    buttonPressed = 1;
    buttonAct = 1; // set the menu flag1
  }
  else if(buttonValue >= 10 & buttonValue <=50)
  {    
    buttonPressed = 2;
    buttonAct = 1; // set the menu flag1
  }
}

Up is working corectly and down is working but it's the left button which should be "esc".

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

the working test line is:

int adc_key_val[5] ={30, 150, 360, 535, 760 };

so in some ways I'll find the solution.

.... Grazie Brunialti, for the particular attention to my stupid problems, I apreciate that and I will do my best to understand and follow your advices.
As soon I get the solution to the buttons problem I'll post it. I think can help those are starting like me.
ciao

You can check the values of button presses on Serial Monitor. Just add Serial.println(buttonValue ); as shown in the following code of yours:

  /*
  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
Serial.println(buttonValue );
  if(buttonValue >= 700)
  {
    buttonPressed = 0;
    noButtonPressed(); // is calling an extra fucntion
  }
  else  if(buttonValue >= 470 & buttonValue <= 600)
  {
    buttonPressed = 4;
    buttonAct = 1; // set the menu flag1
  }
  else if(buttonValue >= 300 & buttonValue <=420)
  {    
    buttonPressed = 3;
    buttonAct = 1; // set the menu flag1
  }
  else if(buttonValue >= 100 & buttonValue <=200)
  {    
    buttonPressed = 1;
    buttonAct = 1; // set the menu flag1
  }
  else if(buttonValue >= 10 & buttonValue <=50)
  {    
    buttonPressed = 2;
    buttonAct = 1; // set the menu flag1
  }
}

Kalid, thank you a great help !! ( and exacly what a "dummy" like me need ! explanation and example ! thanks !! )

This is my solution for the Lcd Keypad Shield with the anologic buttons !
I think something like a delay has to be put somewhere because sometimes I have to push the button twice ... let give me a bit more time to fix it :slight_smile: (or help :slight_smile: )

/*
  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
  Serial.println(buttonValue );
  
  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;
}

As soon I do my homework ...

(from the Master Brunialti)
at a first glance I see some point to check:

  • the following line is not necessary: MW_navbtn=4;
  • when you use addusernav the declared callback should be in charge with button checking and code returning. The call to readButtons() should be therefore inside the callback funcion , not in the loop. the code works the same, but is more polite
  • you defined the menu framework, but after each creation of menu nodes of type MW_VAR you need to create the variable with addVar in order to let the menu working.

I will post the complete code
Thanks

Ok..You can also add in if-else statements the button name for example:
Serial.println("DOWN");..This will ensure you the button press behavior...

..... :slight_smile: I'm starting having fun !!

/*
  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
  Serial.println(buttonValue );
  
  
  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
    Serial.println("Escape");
  }
  else if(buttonValue >= 200 & buttonValue <=300)
  {    
    buttonPressed = 3;
    buttonAct = 1; // set the menu flag1
    Serial.println("DOWN");
  }
  else if(buttonValue >= 0 & buttonValue <=50)
  {    
    buttonPressed = 2;
    buttonAct = 1; // set the menu flag1
    Serial.println("Confirm");
  }
  else if(buttonValue >= 80 & buttonValue <=150)
  {    
    buttonPressed = 1;
    buttonAct = 1; // set the menu flag1
    Serial.println("Up");
  }
}

Thanks Khalid

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

      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:

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

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

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

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();

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 )

// +++++++ 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 ! :blush:

You've got the 57 error because I' forgot to insert the bte function of course :slight_smile:

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

sorry...

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

Silverdog63, so you own Mechmate. I also visit Mechmate forum and my login is Khalid;)
Regards

is there a comlete Terry thermostat_meny.ino whitout the problems from post 194 i cant seem to get that one compiled .. i have the 6button test_all_var_type runing very nice inded but want to look try build on terrys menu i gues.

im a total newbie 8) as you probably understand sins i cant fix the probs but i cant figure out the changes to get it to compile i run ide 1.0.3 * THERMOSTAT_MENU.ino (13.62 KB from reply 194

best regards.

Thomas_berg_:
is there a comlete Terry thermostat_meny.ino whitout the problems from post 194 i cant seem to get that one compiled ..

Tell us the compilation errors...

okey i think im gonna hold my horses with that .ino becouse it seems terry has got later one , if i get probs, starting or compile that one il get back and i probobly will when i start modding it. :%

the one from reply 194

menu.begin(&lcd,16,2);
menu.addUsrNav(navMenu,); <----this one whas obvius as allso with the savevar lines..
MW_navbtn=4;

THERMOSTAT_MENU.ino: In function 'void loop()':
THERMOSTAT_MENU:148: error: 'tempF' was not declared in this scope
THERMOSTAT_MENU.ino: In function 'void msc()':
THERMOSTAT_MENU:303: error: 'tempF' was not declared in this scope
THERMOSTAT_MENU:328: error: a function-definition is not allowed here before '{' token
THERMOSTAT_MENU:333: error: a function-definition is not allowed here before '{' token

but i think i will get new .ino frof terry so i will wait for that one insted of trying to fix the one from reply 194