MENWIZ: yet another character lcd menu wizard library

In order to let MENWIZ manage different lcd interfaces the internal variable holding the lcd object pointer is of type LCD.
LCD is a base class of new liquidCrystal, alllowing to "virtualize" the interface, that is to work with all the supported interfaces.
That is the reason why new liquidCrystal is needed.

Liquid crystal is a collection of classes based on the virtual base class LCD. Each subclass implement a different interface: LiquidCrystal_I2C, LiquidCrystal_SR, LiquidCrystal_SR2,LiquidCrystal_SR2W. To use one interface all you need to do is to change the name of the library directory matching that of the desired interface class. Arduino IDE will use the proper source file andcompile it.

So I'm quite confident liquidCrystal is able to drive your LCD. Unfortunately I cannot tell the proper constructor statement as I have not the device.

You could use an other "external" liquidCrystal library with small changes, in your case, in MENWIZ.H change:
#define MW_LCD LCD to #define MW_LCD LiquidCrystal
#include <LCD.h> to #include <LiquidCrystal.h>

If I'm not forgetting something, it should work. Again, I suggest to use new LiquidCrystal instead.

I have deinstalled everything and reinstalled afterwards. I don't know what it made not working but now it works - oh dear :slight_smile:

Many thanks for your help and patience.

Cheers!

Hi there,

Got another problem which is that the input seems to be too fast so that I flip through the menu without the possibility to navigate one by one.

This is my code:

#include <Wire.h>
#include <LiquidCrystal.h>
#include <MENWIZ.h>
#include <EEPROM.h>

const int btnNONE 	=	0;
const int btnUP    	= 	1;
const int btnDOWN  	= 	2;
const int btnLEFT  	= 	3;
const int btnRIGHT 	= 	4;
const int btnSELECT = 	5;

menwiz menu;
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

int adc_key_in = 0;

int buttonPressed = 0;
int lastButtonPressed = 0;

long lastDebounceTime = 0;  // the last time the output pin was toggled
long debounceDelay = 100;    // the debounce time; increase if the output flickers

int list,sp = 0;

extern byte MW_navbtn;


void setup() {
	
	_menu *r,*s1,*s2;

	menu.begin(&lcd,16,2);
	menu.addUsrNav(navMenu,4);
	MW_navbtn=4;
	
	r=menu.addMenu(MW_ROOT,NULL,F("Root"));
	s1=menu.addMenu(MW_SUBMENU,r, F("Node1"));
		s2=menu.addMenu(MW_VAR,s1, F("Node3"));
			s2->addVar(MW_LIST,&list);
			s2->addItem(MW_LIST, F("Option1"));
			s2->addItem(MW_LIST, F("Option2"));
			s2->addItem(MW_LIST, F("Option3"));
		s2=menu.addMenu(MW_VAR,s1, F("Node4"));
			s2->addVar(MW_AUTO_INT,&sp,0,120,10);
			
	menu.addSplash("LiPanCo\n2012 v01\n", 2000);
	menu.addUsrScreen(&myMenuCall, 5000);
}

void loop() {

  menu.draw();
}

void myMenuCall() {
 sprintf(menu.sbuf,"Uptime (s): %ld\nFree mem  : %d\n\n",millis()/1000,(int)menu.freeRam());
  menu.drawUsrScreen(menu.sbuf); 
  
}


int read_LCD_buttons() {
	
	adc_key_in = analogRead(0);

	if (adc_key_in < 50)   return btnRIGHT;  
	if (adc_key_in < 200)  return btnUP; 
	if (adc_key_in < 400)  return btnDOWN; 
	if (adc_key_in < 600)  return btnLEFT; 
	if (adc_key_in < 800)  return btnSELECT;   
	if (adc_key_in > 1000) return btnNONE;
	
	return btnNONE;
}

int navMenu() {
	buttonPressed = read_LCD_buttons();
	
	if (buttonPressed != lastButtonPressed) {
		
		lastDebounceTime = millis();
	}
	
	if ((millis() - lastDebounceTime) > debounceDelay) {
			
    	switch (buttonPressed) {
    		case btnUP:
      			return MW_BTU;
      			break;
			case btnDOWN:
	      		return MW_BTD;
	      		break;
    		case btnSELECT:
      			return MW_BTC;
      			break;
	    	case btnLEFT:
	      		return MW_BTL;
	      		break;
		   	case btnRIGHT:
				return MW_BTR;
				break;
			case btnNONE:
	      		return MW_BTNULL;
	      		break;
    	}
	}
	
	lastButtonPressed = buttonPressed;  
}

I would have expected that

if (buttonPressed != lastButtonPressed) {
		
		lastDebounceTime = millis();
	}
	
	if ((millis() - lastDebounceTime) > debounceDelay) {

...

prevents this as it does in other sketches but it doesn't seem to work here. Any ideas?

Many thanks for any help in advance. Cheers!

	if (adc_key_in < 50)   return btnRIGHT;  
	if (adc_key_in < 200)  return btnUP; 
	if (adc_key_in < 400)  return btnDOWN; 
	if (adc_key_in < 600)  return btnLEFT; 
	if (adc_key_in < 800)  return btnSELECT;

Uhmmm ...
As far I understant ... you have:
if pressed button brnRIGHT true all the statement below, because ex.30 is <50<200<400<600<800 ....
I think you shoud put something like:

     	if (60 <adc_key_in < 200)  return btnUP;
        if (210< adc_key_in < 400)  return btnDOWN;

ecc. isn'it ?

If I debug my code with Serialprints it is giving me the correct button.

If I put my code like this:

int read_LCD_buttons() {
	
	adc_key_in = analogRead(0);

        if (adc_key_in < 50)   return btnRIGHT;  
	if (adc_key_in < 200)  return btnUP; 
	if (adc_key_in < 400)  return btnDOWN; 
	if (adc_key_in < 600)  return btnLEFT; 
	if (adc_key_in < 800)  return btnSELECT;
	
	return btnNONE;
}

int navMenu() {
	
	buttonPressed = read_LCD_buttons();
	
	if(buttonPressed != lastButtonPressed) {
			
    	switch (buttonPressed) {
    		case btnUP:
      			return MW_BTU;
      			break;
		case btnDOWN:
	      		return MW_BTD;
	      		break;
    		case btnSELECT:
      			return MW_BTC;
      			break;
	    	case btnLEFT:
	      		return MW_BTL;
	      		break;
		   case btnRIGHT:
			return MW_BTR;
			break;
		case btnNONE:
	      		return MW_BTNULL;
	      		break;
    	}
	}
	
	lastButtonPressed = buttonPressed;  
}

I would have thought, that if(buttonPressed != lastButtonPressed) { ensures that a button can't be pressed more than once, can it?

Hi, brunialti. With reference to your request in post #302 here is an example of addUsrNav. You are free to use this if you find it beneficial.

MENWIZ is controlled via addUsrNav call to function navMenu. This function check the value of "virtualButton". Values of virtualButton is set in one of two ISR functions. The reason to use ISR is that both pid calculation and temperature sensor communication is time consuming, and I was worried that button presses would be missed.

One ISR is handling the rotary encoder (up/down) and the other ISR two push buttons (confirm/escape).

Please ask if anything is unclear.

(only fragment of code is pasted due to 9500 char limit... Se full .ino below.)

ISR(PCINT0_vect) // handle pin change interrupt for PCINT0 to PCINT7 here, pin D53-D50 and D10-D13
{
  static uint8_t btn = _BV(PB5) | _BV(PB6);
  uint8_t t = PINB;  // read port status

  // check if buttons are pushed
  t &= _BV(PB6) | _BV(PB5); // D11 D12
  if (t != btn) {  // activity on pins, we're only interested in high to low transitions
    if((long)(micros() - last_micros) >= debouncing_time * 1000) {  
      push[0] |= !(t & _BV(PB5));
      push[1] |= !(t & _BV(PB6));
      btn = t;
      last_micros = micros();  // start/restart bounce guard timer (covers make and break)
    }
 }  
}

ISR(PCINT2_vect) // handle pin change interrupt for PCINT 16 to PCINT23 here, pin D62-D69/A8-A15
{
  static uint8_t AB = 0x03;  //lookup table index
  static long encval = 0;    //encoder value
  static const int8_t enc_states[] =   {0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0};
  uint8_t t = PINK;          // read port status

  // check for rotary2 state change on pin D5 D6
  AB <<= 2;                  // save previous state
  AB |= (t >> 5) & 0x03;     // add current state
  encval += enc_states[AB & 0x0f];
  if( encval > 1 ) {         // step forward
    virtualButton = 2; encval = 0;
  }
  else if( encval < -1 ) {   // step backwards
    virtualButton = 1; encval = 0;
  }
}
int navMenu() // called from menu.draw 
{ 
  switch (virtualButton) 
  {
  case 5: // Escape
    virtualButton = 0;
    return MW_BTE;
    break;
  case 6: // Confirm
    virtualButton = 0;
    return MW_BTC;
    break;
  case 1: // Up
    virtualButton = 0;
    return MW_BTU;
    break; 
  case 2: // Down
    virtualButton = 0;
    return MW_BTD;
    break;
  case 0: // no button
    return MW_BTNULL;
    break;
  }
}
void setup() {
  Serial.begin(9600);
  _menu *r,*s1,*s2;
  menu.begin(&lcd,20,4);
  menu.addUsrNav(navMenu,4);
  r=menu.addMenu(MW_ROOT,NULL,F("BC Main menu"));
    s1=menu.addMenu(MW_VAR,r, F("Set BC On/Off"));
      s1->addVar(MW_BOOLEAN,&running);
    s1=menu.addMenu(MW_VAR,r, F("Set pump On/Off"));
      s1->addVar(MW_BOOLEAN,&mashPump);
    s1=menu.addMenu(MW_SUBMENU,r, F("Select state"));
      s2=menu.addMenu(MW_VAR,s1, F("Prep1"));
        s2->addVar(MW_ACTION,selStatePrep1);
      s2=menu.addMenu(MW_VAR,s1, F("Prep2"));
        s2->addVar(MW_ACTION,selStatePrep2);
      s2=menu.addMenu(MW_VAR,s1, F("Mash"));
        s2->addVar(MW_ACTION,selStateMash);
      s2=menu.addMenu(MW_VAR,s1, F("Boil"));
        s2->addVar(MW_ACTION,selStateBoil);
      s2=menu.addMenu(MW_VAR,s1, F("Cool"));
        s2->addVar(MW_ACTION,selStateCool);
    s1=menu.addMenu(MW_SUBMENU,r, F("Change T SetP"));
      s2=menu.addMenu(MW_VAR,s1, F("HLT SetP"));
        s2->addVar(MW_AUTO_INT,&selectHltSetp,25,98,1);
      s2=menu.addMenu(MW_VAR,s1, F("Boil SetP"));
        s2->addVar(MW_AUTO_INT,&selectBoilSetp,25,102,1);
      s2=menu.addMenu(MW_VAR,s1,F("back"));
        s2->addVar(MW_ACTION,escapeFunct);
        s2->setBehaviour(MW_ACTION_CONFIRM,false);  // MW_ACTION_IMMEDIATE described in MENWIZ_0-6-0_QUICK TOUR.pdf  
    s1=menu.addMenu(MW_VAR,r, F("View details"));
      s1->addVar(MW_LIST,&selectView);
      s1->addItem(MW_LIST, F("(no detail)"));
      s1->addItem(MW_LIST, F("HLT"));
      s1->addItem(MW_LIST, F("Boiler"));
  menu.addUsrScreen(lcdUpdate,3000);                 // Default screen function shown after msecs since last button push
}

//==========================================================================================
//                                Arduino Loop
//==========================================================================================

void loop() {
  menu.draw();                            // NAVIGATION MANAGEMENT & DRAWING ON LCD. NOT BLOCKING has to be the first in the void loop
  if (running) {
    hltPID.SetMode(AUTOMATIC);            //turn the PID on
    boilPID.SetMode(AUTOMATIC);           //turn the PID on
  } else {
    hltPID.SetMode(MANUAL);               //turn the PID off
    boilPID.SetMode(MANUAL);              //turn the PID off
    Timer3.setPwmDuty(pin_PWM_a, 0);      // set the pwm with the output of the pid output to control the SSR:
    Timer3.setPwmDuty(pin_PWM_b, 0);      // set the pwm with the output of the pid output to control the SSR:
  }
  if ( hltSet != selectHltSetp ) { hltSet = selectHltSetp; }
  if ( boilSet != selectBoilSetp ) { boilSet = selectBoilSetp; }
  switch(selectView) {
    case 0: viewActive = viewNormal; break;
    case 1: viewActive = viewHltD; break;
    case 2: viewActive = viewBoilD; break;
  }
  if ( push [0] > 0 ) { // confirm
    virtualButton = 6;
    push[0] = 0;
  }
  if ( push [1] > 0 ) { // escape
    virtualButton = 5;
    push[1] = 0;
  }

  // do brew process activity
  brewProcess();

  // do data logging if it is time for it
  if(millis() - logTime>LOG_DELAY) {
    logTime += LOG_DELAY;
    Serial.print("brewController loop, do dataLogger");
    dataLogger();
  }
}

I have included two pictures, showing wall mounted controller and a look inside the box.

BrewCtrl_09_06.ino (27.4 KB)

Roberto,
just two more questions ....
The fist, is about the Max Menu number I know by default set to 15 .... increasing that number affect memory ... does it increase a lot ? I mean if I change the limit to 30 but use only 15 menus ... I use the same memory amount of using 15 with a limit of 15 ?
The second ... I would like to move my height in 0.1mm step ...

     s3->addVar(MW_AUTO_INT,&HeightZ,0,100,1);

if I set 0.1 step in my var, it does not the decimal step just the integer ... any suggestion ?
thanks

Declare your variable as Float and

s3->addVar(MW_AUTO_FLOAT,&HeightZ,0,100,0.1);

Thanks Khalid,
I had doubt because they told me to not use float because sometimes gives erratic rounding values ....
don't know why ....

Grumpy_Mike:

changing the variable from INT to FLOAt is ok ?

Sorry I dnon't know how many times you need telling
DO NOT USE A FLOAT!!!!!
You will suffer from rounding errors. Mathematical operations will not be commutative.
What do you not understand about using an int with the numbers greater than your resolution?

Silverdog63:
Thanks Khalid,
I had doubt because they told me to not use float because sometimes gives erratic rounding values ....
don't know why ....

I am using it without any trouble...Without the Float you will unable to do step increment like 0.1mm etc...

Saw this one about floats: "Working with floating point is like moving piles of sand. Every time you move one you lose a little sand and pick up a little dirt."

In practice you can do a lot of things with floating points, they have their own points of extra attention, just like integers and bytes etc.

e.g. adding 0.1 in a loop give another kind of error that calculating the next value with a multiply

float f = 0; 
while (f< 1.0)
{
  Serial.println(f, 8);
  f += 0.01;
}


float f = 0;
int n = 0; 
while ( f < 1.0); 
{
  Serial.println(f, 8);
  n++;
  f = n*0.01;
}

In the first loop 100 rounding errors add up, in the second there is only one rounding error (OK it uses an extra integer)

I am having trouble when using the MW_BOOLEAN. When changing the value, the display updates from OFF to ON in a flicker and goes back to OFF again :~

(I think it worked on MENWIZ 1.0.2.). I have searched the forum and looked at the examples, but found no help. Any of you have an idea of what I am missing?

boolean mashPump = false;        // on-off state for pump
boolean running = false;         // on-off state for BrewCtrl, execute the pid control or only do logging

void setup() {
  Serial.begin(9600);
  _menu *r,*s1,*s2;
  menu.begin(&lcd,20,4);                  //declare lcd object and screen size to menwiz lib
  menu.setBehaviour(MW_MENU_INDEX,false); // turn off the menu index - 1/3 etc
  menu.addUsrNav(navMenu,4);
  r=menu.addMenu(MW_ROOT,NULL,F("BC Main menu"));
    s1=menu.addMenu(MW_VAR,r, F("Set BC On/Off"));
      s1->addVar(MW_BOOLEAN,&running);
    s1=menu.addMenu(MW_VAR,r, F("Set pump On/Off"));
      s1->addVar(MW_BOOLEAN,&mashPump);

The full code is attached to post #358.

Hello, First I want to thank you for an amazingly cool library, it has enhanced my project so much.

So here is what I'm running into I wonder if you might be able to help, I am a novice, but I manage.

I have a variable I use to set the number of identical menu options that control an array of variables, below is a sniplet of working code.

s1=menu.addMenu(MW_SUBMENU,r,F("Lights"));
      for (int count = 0; count < PWMs; count++){
        Serial.println(menuname);
        String current = "PWM" + String(count);
        s2=menu.addMenu(MW_SUBMENU,s1,F("PWM"));
          s3=menu.addMenu(MW_VAR,s2,F("Mode"));
            s3->addVar(MW_LIST,&PWM_Mode[count]);
              s3->addItem(MW_LIST,F("Auto"));
              s3->addItem(MW_LIST,F("On"));
              s3->addItem(MW_LIST,F("Off"));
          s3=menu.addMenu(MW_VAR,s2,F("Level"));
            s3->addVar(MW_AUTO_BYTE,&PWM_Level[count],0,100,5);
          s3=menu.addMenu(MW_VAR,s2,F("Soft"));
            s3->addVar(MW_AUTO_BYTE,&PWM_Soft[count],0,180,5);
          s3=menu.addMenu(MW_SUBMENU,s2,F("Schedule"));
              s4=menu.addMenu(MW_SUBMENU,s3,F("Start"));
                s5=menu.addMenu(MW_VAR,s4,F("Hour"));
                  s5->addVar(MW_AUTO_BYTE,&PWM_StartHH[count],0,23,1);
                s5=menu.addMenu(MW_VAR,s4,F("Minute"));
                  s5->addVar(MW_AUTO_BYTE,&PWM_StartMM[count],0,59,1);
              s4=menu.addMenu(MW_SUBMENU,s3,F("End"));
                s5=menu.addMenu(MW_VAR,s4,F("Hour"));
                  s5->addVar(MW_AUTO_BYTE,&PWM_EndHH[count],0,23,1);
                s5=menu.addMenu(MW_VAR,s4,F("Minute"));
                  s5->addVar(MW_AUTO_BYTE,&PWM_EndMM[count],0,59,1);
      }

This works great Except I would like to name the "s2=menu.addMenu(MW_SUBMENU,s1,F("PWM"));" PWM1, PWM2, PWM3 etc etc etc.. So I tried this.

s2=menu.addMenu(MW_SUBMENU,s1,F("PWM" + String(count)));

but the error I get is

"error: initializer fails to determine size of '__c"

I've read about string buffers but I get a little lost, I've tried to dig through the .cpp and .h files but can't make much sense of it.

Any Help you can provide would be great!, Thanks!

On a side note,

I've found a way to make the Menwiz Lib work with the Adafruit I2c backpack.

You need the following:

Adafruit LiquidTWI2 library available here GitHub - lincomatic/LiquidTWI2: A lean, high speed I2C LCD Library for Arduino, which supports MCP23008 and MCP23017

Make these changes to MENWIZ.H

//#include <LCD.h>
and
//MW_LCD* lcd;
LiquidTWI2* lcd;

Make this Change to MENWIZ.CPP

//lcd=(MW_LCD*)l;
lcd=(LiquidTWI2*)l;

Make these changes to your sketch
//#include <LCD.h>
//#include <LiquidCrystal_I2C.h>
#include <LiquidTWI2.h>
and
//LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
LiquidTWI2 lcd(0);

and
lcd.setMCPType(LTI_TYPE_MCP23008); // add this at the top of void setup()

Hope this helps someone.

--EDIT--
I found the MENWIZ lib changes in a blog that originally made them work with the LiquidTWI library, when trying to figure out how to make the Adafruit I2c backpack work with LiquidTWI I stumbled on their fork. I do not know the name, nor can I find the blog I found the original information on. My I'd give credit if I could find it.

Hi guys. I'm back.
I've lost all the reply notifications, without any apparent reason.
I'll try to work on menwiz in order to implement some improvement as soon as possible.

I'm also working on a completely different slim library implementing the notion of "watchdog" on any user variable.
In this new lib it is possible to create for any user defined variable some triggers, that is an action to be fired when the trigger conditions (>,=, <,null for now) are verified. As many sketches are nothing else than a continuous control on some variable values, this lib let the user concentrate on the actions to be performed instead of the control logic, allowing very compact user code...
stay tuned !

Hi,
I will be the one who will use your great library...:slight_smile: Thank You for sharing :slight_smile:

:smiley:

Is Bump, against forum rules?

I was curious because I'm still stuck on the problem I've listed in a previous post.

Hello,

I am trying to use Menwiz with my setup using an encoder (see code below - I have borrowed a lot from others in this thread!). I have tried setting up an exit function in the menu so I can escape back up to the previous level. The function works as expected but once I exit a submenu I cannot re-enter it without resetting the Arduino. It seems that when I try to re-enter the submenu it automatically selects 'exit' and brings me right back out. I don't think it is a button debounce issue because it seems to be working fine otherwise.

Any thoughts on why this might be happening? I have the feeling I am missing something simple...

//The full code is in library example file Quick_tour.ino
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
#include <buttons.h>
#include <MENWIZ.h>
#include <EEPROM.h>
#include <rotary.h>
#include <Bounce.h>

menwiz tree;
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

// ENCODER 
Rotary r = Rotary(2, 3);
int encoderSwitchPin = 4; //push button switch
volatile int virtualButton = 0;

// Instantiate a Bounce object with a 5 millisecond debounce time
Bounce bouncer = Bounce(encoderSwitchPin, 150);

// MENWIZ
int  list,sp = 110;
float setTemp = 25;
float whiOn = 6;
float whiOff = 18;
float actOn = 6;
float actOff = 18;
float ledOn = 6;
float ledOff = 18;

void setup(){
  
  // MENWIZ
  _menu *r,*s1,*s2;  
  Serial.begin(9600);    
  
  tree.begin(&lcd,16,2); //declare lcd object and screen size to menwiz lib
  tree.addUsrNav(navMenu,4);
    
  r=tree.addMenu(MW_ROOT, NULL, F("Root"));
    s1=tree.addMenu(MW_SUBMENU,r, F("Temperature"));
      s2=tree.addMenu(MW_VAR,s1, F("Set Temp"));
        s2->addVar(MW_AUTO_FLOAT, &setTemp, 20, 30, 0.1);
      s2=tree.addMenu(MW_VAR,s1, F("Exit"));
        s2->addVar(MW_ACTION, escapeFunc);
        s2->setBehaviour(MW_ACTION_CONFIRM, false);   
    s1=tree.addMenu(MW_SUBMENU,r, F("Lights"));       
        s2=tree.addMenu(MW_VAR,s1, F("white ON"));
          s2->addVar(MW_AUTO_FLOAT, &whiOn, 0, 24, 0.5);
        s2=tree.addMenu(MW_VAR,s1, F("white OFF"));
          s2->addVar(MW_AUTO_FLOAT, &whiOff, 0, 24, 0.5);   
        s2=tree.addMenu(MW_VAR,s1, F("actinic ON"));
          s2->addVar(MW_AUTO_FLOAT, &actOn, 0, 24, 0.5);
        s2=tree.addMenu(MW_VAR,s1, F("actinic OFF"));
          s2->addVar(MW_AUTO_FLOAT, &actOff, 0, 24, 0.5);
        s2=tree.addMenu(MW_VAR,s1, F("LED ON"));
          s2->addVar(MW_AUTO_FLOAT, &ledOn, 0, 24, 0.5);
        s2=tree.addMenu(MW_VAR,s1, F("LED OFF"));
          s2->addVar(MW_AUTO_FLOAT, &ledOff, 0, 24, 0.5);
        s2=tree.addMenu(MW_VAR,s1, F("Exit"));
          s2->addVar(MW_ACTION, escapeFunc);
          s2->setBehaviour(MW_ACTION_CONFIRM, false);    

  tree.addUsrScreen(msc,10000);

  // ENCODER
  pinMode(encoderSwitchPin, INPUT);
  digitalWrite(encoderSwitchPin, HIGH); //turn pullup resistor on
  PCICR |= (1 << PCIE2);
  PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);
  sei();
  
  }

void loop(){
  
  tree.draw(); 
 
  // Update the debouncer
  bouncer.update ( );
 
 // Get the update value
 int value = bouncer.read();
  
  //if(digitalRead(encoderSwitchPin) == LOW) 
  if (value == LOW) {
    virtualButton = 3;
  }
  
  }
  
void msc(){
  static  char buf[7];
  strcpy(tree.sbuf,"User screen"); //1st lcd line
  strcat(tree.sbuf,"\nsetTemp  : ");strcat(tree.sbuf, dtostrf(setTemp, 4, 1, buf));
  tree.drawUsrScreen(tree.sbuf);
  }

void myfunc(){
  Serial.println("ACTION FIRED");
  }

int navMenu() { 
  
  switch(virtualButton) {
    case 1: // RIGHT
      virtualButton = 0;
      return MW_BTD;
      
      break;
    case 2: // LEFT
      virtualButton = 0;
      return MW_BTU;
      
      break;
    case 3: // CONFIRM
      virtualButton = 0;
      return MW_BTC;
      
      break;
    case 4: // Escape
      virtualButton = 0;
      return MW_BTE;
      
      break;
    case 0: // NONE
      return MW_BTNULL;
      break;
        
  }  
      
}

ISR(PCINT2_vect) {
  unsigned char result = r.process();
  if (result) {
    if (result == DIR_CW) { 
      virtualButton = 1;
    }
    if (result == DIR_CCW) {
      virtualButton = 2;
    }
  }
  
}

void escapeFunc() {
  virtualButton = 4;  
}
 if(list,dc == 0)

What's that?

Please use code tags when posting code.

int list,dc = 0;        // Drops Count, Nmber of drops to produce.
byte ds = 0;            // Drops Size, in Milliseconds,Time Solenoid Valve stays open.
byte di12 = 0;          // Drops Interval, in Millisecons, Time Between Drops 1 & 2 That Solenoids Shuts off.
byte di23 = 0;          // Drops Interval, in Millisecons, Time Between Drops 1 & 2 That Solenoids Shuts off.
int svpd = 0;           // Solenoid Valve Purge Delay.
byte svpdo = 2;         // Digital Out Pin For Solenoid Valve Purge.
byte dgo = 3;           // Digital Out Pin For Go Drop Launch.
byte sd = 0;            // Sensor's Delay Value.
byte st = 0;            // Sensor's Threshold Value
int bmd = 0;            // Bulb Delay, When Button Pressed To Confirm, Shutter will Trigger In Bulb Mode For That Set delay.
byte bmo = 4;           // Digital Out Pin For Bulb Mode.
byte sdo = 5;           // Digital Out Pin For Shutter.

Mixing (constant) pin numbers in with variables is a really bad idea.

if(list,dc == 0) refers to the number of drop from 1 to 3 is set up in Drop count menu

Nope, sorry, I'm not seeing it.
Can you point to some similar code like that?
What I'm seeing is
"is "list" non zero? Discard that result. Is "dc" equal to zero? If so do something on that basis."

I can see no reason to have "list" in that expression.