Go Down

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

Silverdog63

I have the same shield I think and use LyquidCrystal with no problems.
what is your problem ?

aufruf

#346
Jan 30, 2013, 07:31 am Last Edit: Jan 30, 2013, 07:34 am by aufruf Reason: 1
Hi,

Sorry if that was unclear.

At the moment I am using the standard LiquidCrystal library with the following statement:

Code: [Select]
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

In the MENWIZ quicktour example the standard LiquidCrystal library is replaced with the New LiquidCrystal library from https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/Home

The statement for initialization in the example looks as follows:

Code: [Select]
LiquidCrystal_I2C lcd(0x27,2,1,0,4,5,6,7,3,POSITIVE);

My question now is, how should the statement look like for my LCD?

Silverdog63

Aufruf,
I use exacly your first statement an the calssic Liquidcrystal library:
Code: [Select]
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
You don't need to use LiquidCrystal_I2C to use MENWIZ.
I use flawlessly MENWIZ menu and library.
the olnly thing I did is to change from digital buttons to analog buttons.

aufruf

#348
Jan 30, 2013, 07:06 pm Last Edit: Jan 30, 2013, 07:12 pm by aufruf Reason: 1
Unfortunately I can't get it to work properly. Here is my code:

Code: [Select]
#include <Wire.h>
#include <LiquidCrystal.h>
#include <MENWIZ.h>
#include <EEPROM.h>


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

menwiz tree;

int  list, sp=110;


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


void setup(){

//_menu *r,*s1,*s2;

tree.begin(&lcd, 16, 2);

tree.addSplash("Library running", 2000);
}


void loop(){

 tree.draw();
}


But I get the following error message:

Code: [Select]
In file included from Splash.ino:3:
/Users/MyName/Documents/Arduino/libraries/MENWIZ/MENWIZ.h:214: error: ISO C++ forbids declaration of 'LCD' with no type
/Users/MyName/Documents/Arduino/libraries/MENWIZ/MENWIZ.h:214: error: expected ';' before '*' token


Would it be possible to fix that if I would you the new LiquidCrystal library? If yes, I would need to ask the same question as before as to how my statement for initialization would need to look like :)

Many thanks for your help!

Silverdog63

I this:
Code: [Select]
  menu.begin(&lcd,16,2);              //initialize the menwiz menu object passing the lcd object and the colums and rows params

put it after:
  _menu *r,*s1,*s2,*s3;

Silverdog63

In this thread at post 316 there is my code that is working on your hardware ....
Quote
Re: MENWIZ: yet another character lcd menu wizard library
« Reply #316 on: January 09, 2013, 09:59:40 PM »

(is on page 22)
you can try it then start to modify it for your convenience you will have the buttons working too ...

tack

It looks to me like you need to uncomment that _menu line and change it to _tree :-

Code: [Select]
#include <Wire.h>
#include <LiquidCrystal.h>
#include <MENWIZ.h>
#include <EEPROM.h>


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

menwiz tree;

int  list, sp=110;


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


void setup(){

_tree *r,*s1,*s2; // <<<<<<<<<<<<<<<<<< CHANGE HERE <<<<<<<<<<<<<<<<<

tree.begin(&lcd, 16, 2);

tree.addSplash("Library running", 2000);
}


void loop(){

  tree.draw();
}

aufruf


In this thread at post 316 there is my code that is working on your hardware ....
Quote
Re: MENWIZ: yet another character lcd menu wizard library
« Reply #316 on: January 09, 2013, 09:59:40 PM »

(is on page 22)
you can try it then start to modify it for your convenience you will have the buttons working too ...


Thanks for the offer. I have copied the code over but still get the same error message :(

Code: [Select]
In file included from Splash.cpp:7:
/Users/MyName/Documents/Arduino/libraries/MENWIZ/MENWIZ.h:214: error: ISO C++ forbids declaration of 'LCD' with no type
/Users/MyName/Documents/Arduino/libraries/MENWIZ/MENWIZ.h:214: error: expected ';' before '*' token

brunialti

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.

aufruf

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

Many thanks for your help and patience.

Cheers!

aufruf

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:

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

Silverdog63

#356
Feb 01, 2013, 05:07 pm Last Edit: Feb 01, 2013, 05:09 pm by Silverdog63 Reason: 1
Code: [Select]
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:
Code: [Select]
    if (60 <adc_key_in < 200)  return btnUP;
       if (210< adc_key_in < 400)  return btnDOWN;


ecc. isn'it ?

aufruf

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

If I put my code like this:

Code: [Select]
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
Code: [Select]
if(buttonPressed != lastButtonPressed) { ensures that a button can't be pressed more than once, can it?

HansF

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

Silverdog63

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

Go Up