LCD shield menu

Hello, I'm beginig my adventure with Arduino Mega 2560. I was bought a LCD shield with keyboard. I want to build some menu. This shield have 6 push buttons who's connected to analog pin A0 (select, right, left, up, down, reset). They gives values: 142, 328, 0, 504, 741. Menu must have 6 windows for egzample: 1 2 3 4 5 6 If I will start the program on LCD should be 1. When I press a right button should be 2. When I press a right button once again it sholud go to 3. . . . as to 6. When i press left it shold revers to previous.

I try to do this with switch case structures but is no good idea.

How i shold to do this??

Sorry for my english - im begining :) Thank you!

I didn't understand how the LCD shield is exactly wired to your Arduino? All pushbuttons are connected to A0 and you distinguish which is pressed by an analogread value? Maybe post a link where you bought it.

By an analogread value i read a value of button. All pushbutton are connected to A0, everyone of this button have another value for egzample right = 0.

sounds interesting hav never heard about this before maybe share a link where you bought it?

Switch case is not a bad approach but allow a range because analogread is not exact. By the way how big is your screen character resolution 16x02 e.g. ?

i just found MenuBackend hope it helps

I bought lcd shield like this one: http://www.robotshop.com/dfrobot-lcd-keypad-shield-arduino-3.html

My screen character resolution is 16x2.

this is problem - analogread is not exact, i sholud give a section of value for every key, becouse raesitance can change with temparature etc.

'karlok' i just seen MenuBackend i google. Can you post link with your?

Thanks for the link. Now I understand better.

employer:
i sholud give a section of value for every key,

yes, a range. maybe +/- 5% or so, it depends on your given values.
What is analogread when no pushbutton is connected? If it is not a constant value, you might use a pullup/pulldown resistor.
Maybe post your exact table. If you don’t know - just test it.
You mentioned 6 buttons (select, right, left, up, down, reset) but only 5 values (142, 328, 0, 504, 741).

If they are linearray arranged you could calculate the pushbutton’s id. Something like analogread(0)/6
see attached graph

And MenuBackend is a library I just found, however you can make your own menu like you want it without this library.
Just google it - menubackend arduino ? arduino.cc › … › Software › Development ? MenuBackend, new menu managment library.

Screenshot 20121027 14.06.05.png

When no pushbutton is connected analogread value is 1023. I didnt write 6th value becouse is reset, the same whos on arduino board.

I want to write my own menu. So I have one idea:

dod is a intiger

void loop() { dod == 0; sensVal = analogRead(A0);

if (sensVal == 142 ) { dod ++; delay(500); }

if (sensVal == 0 ) { dod --; delay(500); } switch (dod) { case 0: lcd.clear(); lcd.setCursor(0,0); lcd.print("work"); delay(1000); break; case 1: lcd.clear(); lcd.setCursor(0,0); lcd.print("do"); delay(100); break;

. . . . . . case 6: lcd.clear(); lcd.setCursor(0,0); lcd.print("nothing"); delay(100); break;

}

What are You thinkig about this?

I must limit a dod value to 6 and 0. This program is working, but it's not exact. When it's in example case 1, on lcd is ''nothing'', so what sholud i do to eliminate blink with delay frequency? I want to constans print on lcd and I dont have Idea to do this.

I already told you how I would use the fact that the values are arranged in a linear correlation, look my diagram above.
And use some round function, there has to be one already I think. (I don’t mean casting the value but really rounding it like 2.5~3; 2.4~2)

karlok: I already told you how I would use the fact that the values are arranged in a linear correlation, look my diagram above. And use some round function, there has to be one already I think. (I don't mean casting the value but really rounding it like 2.5~3; 2.4~2)

I dont understand what you exact mean. I should divide anlaogread by 6 and suply a sensVal and give a range for every button?

How can I exterminade a blink inscription on lcd?? case 0: lcd.clear(); lcd.setCursor(0,0); lcd.print("work"); delay(1000); break; I want to constans descirption show for every case without delay. Is it any command to do this?

Do you see my diagram I have created for you?
What do you recognize?

This is the table, isn’t it? Please check it, that is important.

BUTTON | READ
left       0
select   142
right    328
up       504
down     741
reset  reset

If you see that this curve is linear, you may assume that all the values are multiples of the smallest one (142) which is not exact but approximately.
You should repeat the analogRead test some times to get a good average value for each button.

Just divide the analogRead by the smallest one whose the other values are multiples of or use some average value approach.

And I forgot the best: You don’t even range checking!

So i should create some buttons id? I should divide every button value by for example 2 and save it in intiger?

Can you post part of program with this? Will be very easier to understand.

Thank you for intersting my problem.

Hello, try this code:

/* FILE:    ARD_LCD_HCARDU014_Buttons_Example.pde
   DATE:    02/07/12
   VERSION: 0.1

 This is a simple example of how to use the buttons included on the 
 HobbyComponents Arduino LCD shield (HCARDU0014). The shield will work 
 with the standard Arduino LiquidCrystal library.
 
 The buttons when pressed apply different offset voltages to the
 Arduino ADC0. Reading the ADC will give an ADC code in the following 
 range depending on which button has been pressed:

     Between 0 & 49 = RIGHT button pressed.
     Between 50 & 194 = UP button pressed.
     Between 195 & 379 = DOWN button pressed.
     Between 380 & 555 = LEFT button pressed.
     Between 555 & 789 = SELECT button pressed.
  
     Above and ADC code of 790, assume no button has been pressed.
  
You may copy, alter and reuse this code in any way you like but please 
leave reference to HobbyComponents.com in your comments if you
redistribute this code. */



/* Include the standard LiquidCrystal library */
#include <LiquidCrystal.h>


/* DIO pin definitions */
#define LCD_DATA4 4         /* LCD data DIO pin 4 */
#define LCD_DATA5 5         /* LCD data DIO pin 5 */
#define LCD_DATA6 6         /* LCD data DIO pin 6 */
#define LCD_DATA7 7         /* LCD data DIO pin 7 */
#define LCD_RESET 8         /* LCD Reset DIO pin */
#define LCD_ENABLE 9        /* LCD Enable DIO pin */
#define LCD_BACKLIGHT 10    /*LCD backlight DIO pin */


/* Definitions for current button state */
typedef enum
{
  E_LCD_BTN_RIGHT,          /* LCD RIGHT button pressed */
  E_LCD_BTN_UP,             /* LCD UP button pressed */
  E_LCD_BTN_DOWN,           /* LCD DOWN button pressed */
  E_LCD_BTN_LEFT,           /* LCD LEFT button pressed */
  E_LCD_BTN_SELECT,         /* LCD SELECT button pressed */
  E_LCD_BTN_NONE,           /* LCD NONE button pressed */
} 
teButtonState;       


/* Initiliase the LiquidCrystal library with the correct DIO pins */
LiquidCrystal lcd(LCD_RESET, LCD_ENABLE, LCD_DATA4, LCD_DATA5, LCD_DATA6, LCD_DATA7);


void setup() {

  /* Set the correct display size (16 character, 2 line display) */
  lcd.begin(16, 2);  
}


/* Main program loop */
void loop() 
{

  /* Put the LCD cursor on the first row and prompt the user to press a button */
  lcd.setCursor(0,0); 
  lcd.print("Press a button...");

  /* Keep checking for a button press */
  while (1)
  {
    /* Put the LCD cursor on the second row */
    lcd.setCursor(0,1); 

    /* Get the current state of the LCD buttons */
    switch(iGetLCDButtonState())
    {
      /* If the RIGHT button has been pressed then display this on the LCD */
    case E_LCD_BTN_RIGHT:
      lcd.print("RIGHT ");
      break;

      /* If the LEFT button has been pressed then display this on the LCD */
    case E_LCD_BTN_LEFT:
      lcd.print("LEFT   ");
      break;

      /* If the UP button has been pressed then display this on the LCD */
    case E_LCD_BTN_UP:
      lcd.print("UP    ");
      break;

      /* If the DOWN button has been pressed then display this on the LCD */
    case E_LCD_BTN_DOWN:
      lcd.print("DOWN  ");
      break;

      /* If the SELECT button has been pressed then display this on the LCD */
    case E_LCD_BTN_SELECT:
      lcd.print("SELECT");
      break;

      /* If no button has been pressed then display NONE on the LCD */
    case E_LCD_BTN_NONE:
      lcd.print("NONE  ");
      break;
    }
  }
}



/* Read the current state of the LCD buttons using the ADC */
int iGetLCDButtonState()
{
  int iADC_Value;
  int iADC_Button_State = E_LCD_BTN_NONE;

  iADC_Value = analogRead(0);      /* Read the ADC */


  /* If ADC reads above 1000 then assume no buttons have been pressed */
  if (iADC_Value > 1000) 
  {
    iADC_Button_State = E_LCD_BTN_NONE;
  } 
  else /* If it was below 1000 then a button is pressed... */
  {

    /* If ADC reads between 0 & 49, then the RIGHT button has been pressed */
    if (iADC_Value < 50)             
    {
      iADC_Button_State = E_LCD_BTN_RIGHT; 
    }
    else
    {
      /* If ADC reads between 50 & 194, then the UP button has been pressed */
      if (iADC_Value < 195)
      {      
        iADC_Button_State = E_LCD_BTN_UP;      
      }
      else
      {
        /* If ADC reads between 195 & 379, then the DOWN button has been pressed */
        if (iADC_Value < 380) 
        { 
          iADC_Button_State = E_LCD_BTN_DOWN;
        }
        else
        {
          /* If ADC reads between 380 & 555, then the LEFT button has been pressed */
          if (iADC_Value < 555)  
          {
            iADC_Button_State = E_LCD_BTN_LEFT;
          }
          else
          {
            /* If ADC reads between 555 & 789, then the SELECT button has been pressed */
            if (iADC_Value < 790)  
              iADC_Button_State = E_LCD_BTN_SELECT;  
          }
        }
      }
    }
  }
  return iADC_Button_State;
}

That is possible, too. But inconvenient IMHO.
Concerning my approach: To round the value, just operate on the quotient the following (int)((float)Q+0.5)
This will round (adding 0.5) instead of trunacte and additionally turning it into an int !
Now simple switch case or the like.

P.S.: Maybe you must cast analogRead to float as well …

I’m not sure what your problem is but the sketch below has worked for me. I have not worried about the analogue values and this just uses the key returns. Check your pins LCD D4 is usually on D4, and my ladder is on pin 14. I don’t know what pin 13 is for, and the code seems to work if it is disconnected. This is work in progress. There is an if,do command around line 56

/*
  The circuit:
 * LCD RS pin to digital pin 8
 * LCD Enable pin to digital pin 9
 * LCD D4 pin to digital pin 16
 * LCD D5 pin to digital pin 5
 * LCD D6 pin to digital pin 6
 * LCD D7 pin to digital pin 7
 * LCD BL pin to digital pin 10
 * KEY pin to analog pin 0        (14)  THIS IS THE BUTTON PIN
 */

#include <LiquidCrystal.h>

LiquidCrystal lcd(8, 13, 9, 16, 5, 6, 7);

char msgs[5][16] = {"Right Key OK ",
                    "Up Key OK    ",               
                    "Down Key OK  ",
                    "Left Key OK  ",
                    "Select Key OK" };

int adc_key_val[5] ={50, 200, 400, 600, 800 };
int NUM_KEYS = 5;
int adc_key_in;
int key=-1;
int oldkey=-1;

void setup()
{
    Serial.begin(9600);
  lcd.clear(); 
  lcd.begin(16, 2);
  lcd.setCursor(0,0); 
  lcd.print("ADC key testing"); 
}

void loop()
{ //1
  adc_key_in = analogRead(0);    // read the value from the sensor 
  key = get_key(adc_key_in);  // convert into key press
 
  if (key != oldkey)   // if keypress is detected "!=" means not equal!!
   {//2
    delay(50);  // wait for debounce time
    adc_key_in = analogRead(0);    // read the value from the sensor 
    key = get_key(adc_key_in);    // convert into key press
    if (key != oldkey)    
    {//3   
      lcd.setCursor(0, 1);
      oldkey = key;
      if (key >=0){//4
           lcd.print(msgs[key]);
      Serial.println(key); 
      
      if (key == 2)
 {
  Serial.println("            down  ");
 }
      
      
lcd.setCursor(15,1);  
lcd.print(key);

      }//4
    }//3

   }//2
  /*
 if (key = 800)
 {
   delay(2000);
   lcd.clear();
  }
*/
 delay(100);
 
}//1

// Convert ADC value to key number
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;
}

Yes, this is the same idea as above. I just suggested a solution that uses this linear correlation I mentioned. How to finally implement the feature is left to the author.

Hello, I am sorry for my absence.
Thanks everyone for help with menu.
I need this menu to bulid steering of kettle. I want to measure temperature and activate pump. I try to do this in code below. I use sensor DS18B20 and LED on pin 52. In egz wen temp is over 25deg pin 52 is high. I cant place this part of code to void loop because is generate error: tempC is not declared in this scope. When I place it into void setup is working good.
What I do wrong?

Thank you for help.

code:

 if (tempC >= 25.00)
    {
     digitalWrite(52, HIGH);
    }
    else
    {
      digitalWrite(52, LOW);
    }

code:

    #include <OneWire.h>
    #include <DallasTemperature.h>
    #include <LiquidCrystal.h>
    #define ONE_WIRE_BUS 22

    LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
    OneWire oneWire(ONE_WIRE_BUS);
    DallasTemperature sensors(&oneWire);
    DeviceAddress insideThermometer = { 0x28, 0x26, 0x44, 0xBB, 0x03, 0x00, 0x00, 0x0D };




    void setup(void)
    {
      Serial.begin(9600);
      pinMode(52, OUTPUT);
      sensors.begin();
      sensors.setResolution(insideThermometer, 10);
      lcd.begin(16,2); // columns, rows. use 16,2 for a 16x2 LCD, etc.
      lcd.clear(); // start with a blank screen
    }
      void printTemperature(DeviceAddress deviceAddress)
    {
      float tempC = sensors.getTempC(deviceAddress);
      if (tempC == -127.00) {
      lcd.print("Error");
    }
      else {
      lcd.print(tempC);
    }
    }


    void loop(void)
    {
      delay(2000);
      sensors.requestTemperatures();
      lcd.setCursor(0,0);
      lcd.print("kociol: ");
      printTemperature(insideThermometer);
      lcd.write(0xDF);
      lcd.write('C'); 
    }

I don't see a "tempC" in your loop. You could also initiate (e.g. declare) this var at the very beginning after havign defined the classes instances

You don't see tempC in loop because when i declare: float tempC; if (tempC >= 25.00) { digitalWrite(52, HIGH); } else { digitalWrite(52, LOW); } and I print tempC on serial i recive value: 0.00 On lcd I have good temperature.

You don't see tempC in loop because when i declare: float tempC; if (tempC >= 25.00) { digitalWrite(52, HIGH); } else { digitalWrite(52, LOW); } and I print tempC on serial i recive value: 0.00

When I declare a variable, but don't give it a value, I get zero. Why is that?