Go Down

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

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