LCD Input and Output

Just so y'all know, I am very new to arduino.

I am using the Liquid Crystal LCD for arduino. It has 6 buttons, which I am trying to use to input values. The other piece to this project is a GPS which is not part of my problem, so do not concern yourself with it.

My problem is when I run this code, the LCD will not take in any inputs. It constantly blinks and almost looks like its just running through the loop and not taking in any inputs except reset. My best guess is to have something that would pause the code and wait for the user to input the value necessary. Then after the input is made, it continues on with whatever it is supposed to do. I tried a while loop to satisfy that condition where the SELECT button was pressed. However, it does not seem to be doing any better.

Any suggestions would be greatly helpful.

//Sample using LiquidCrystal library
#include <LiquidCrystal.h>
#include <math.h>
#include <stdlib.h>


// select the pins used on the LCD panel
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); 
// define some values used by the panel and buttons
int lcd_key     = 0;
int adc_key_in  = 0;
int lcd_key_value = 1500;
#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5

float latitudeD = 0;
float longitudeD = 0;
float latitudeL = 7357.1870;
float longitudeL = 4123.4700;
float distance = 0;
int iteration = 1;
String latitudeDestination = "";
String longitudeDestination = "";

void setup(){
}
 
void loop(){
  if (iteration = 1) {
    latitudeDestination += inputCoordinates();
    iteration++;
    longitudeDestination += inputCoordinates();
  }
  latitudeD = latitudeDestination.charAt(0)*pow(10,3) + latitudeDestination.charAt(1)*pow(10,2) + latitudeDestination.charAt(2)*pow(10,1) + 
              latitudeDestination.charAt(3)*pow(10,0) + latitudeDestination.charAt(4)*pow(10,-1) + latitudeDestination.charAt(5)*pow(10,-2) +
              latitudeDestination.charAt(6)*pow(10,-3) + latitudeDestination.charAt(7)*pow(10,-4);
  longitudeD = longitudeDestination.charAt(0)*pow(10,3) + longitudeDestination.charAt(1)*pow(10,2) + longitudeDestination.charAt(2)*pow(10,1) + 
              longitudeDestination.charAt(3)*pow(10,0) + longitudeDestination.charAt(4)*pow(10,-1) + longitudeDestination.charAt(5)*pow(10,-2) +
              longitudeDestination.charAt(6)*pow(10,-3) + longitudeDestination.charAt(7)*pow(10,-4);
  //Main Operation (navigating to destination)
  lcd.setCursor(16, 2);
  lcd.print(latitudeDestination + longitudeDestination);
  lcd.setCursor(0,1);
  distance = calculateDistance(latitudeD,longitudeD,latitudeL,longitudeL);
  lcd.print(distance);
}

String inputCoordinates() {
  lcd.begin(16, 2);              // set LCD to top row
  if(iteration = 1) {
  lcd.print("Input Latitude"); // print instructions to operator
  }
  else {
  lcd.print("Input Longitude"); // print instructions to operator
  }
  int space = 0;
  int digit[] = {0,0,0,0,0,0,0,0,0};
  int run = 1;
  lcd.setCursor(0,1);
  lcd.print("0000.0000");
  delay(200);
  while(run = 1) {
    while(lcd_key_value > 1000) {    
      lcd_key_value = analogRead(0);
      lcd_key = read_LCD_buttons();  // read the buttons
    }
    switch (lcd_key)  {    // depending on which button was pushed, we perform an action   
      case btnRIGHT: {     
        space++;
        if (space == 4) {
          space++;
        }
      }
      case btnLEFT: {     
        space--;
        if (space == 4) {
          space--;
        }     
      }
      case btnUP: {
        digit[space] = digit[space] + 1;
        lcd.setCursor(space,1);
        lcd.print(digit[space]);
      }
      case btnDOWN: {
        digit[space] = digit[space] - 1;
        lcd.setCursor(space,1);
        lcd.print(digit[space]);
      }   
      case btnSELECT: {     
        run = 0;
      }
      case btnNONE:{
      }
    }
    String digit0 = "";
    digit0 += digit[0];
    String digit1 = "";
    digit1 += digit[1];
    String digit2 = "";
    digit2 += digit[2];
    String digit3 = "";
    digit3 += digit[3];
    String digit5 = "";
    digit5 += digit[5];
    String digit6 = "";
    digit6 += digit[6];
    String digit7 = "";
    digit7 += digit[7];
    String digit8 = "";
    digit8 += digit[8];
    String coordinate = "";
    coordinate += digit0 + digit1 + digit2 + digit3 + digit5 + digit6 + digit7 + digit8;
    return coordinate;
 }
}

int read_LCD_buttons(){ 
adc_key_in = analogRead(0);      // read the value from the sensor  
 // my buttons when read are centered at these valies: 0, 144, 329, 504, 741 
 // we add approx 50 to those values and check to see if we are close 
 if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result 
 if (adc_key_in < 50)   return btnRIGHT;   
 if (adc_key_in < 195)  return btnUP;  
 if (adc_key_in < 380)  return btnDOWN;  
 if (adc_key_in < 555)  return btnLEFT;  
 if (adc_key_in < 790)  return btnSELECT;    
 return btnNONE;  // when all others fail, return this...
} 

float calculateDistance(float lat1, float lon1, float lat2, float lon2)  {
  float d;
  d = 2*asin(sqrt(pow(sin((lat1-lat2)/2),2)+cos(lat1)*cos(lat2)*pow(sin((lon1-lon2)/2),2)));
  return d;
}

I am using the Liquid Crystal LCD for arduino. It has 6 buttons, which I am trying to use to input values. The other piece to this project is a GPS which is not part of my problem, so do not concern yourself with it.

You will have better luck getting help if you:

(1) Identify your LCD with a specific part number, a link to the site where you got it, a link to any documentation you have found, etc.

(2) Thin out your code to the minimum amount that will still illustrate the problem.

(3) Outline any troubleshooting that you have done. For example, did you consider adding a delay after sending something to the LCD so you can see if it is being displayed before being overwritten by something else?

Don

  1. Arduino_LCD_KeyPad_Shield__SKU__DFR0009_-DFRobot

String inputCoordinates() {
  lcd.begin(16, 2);              // set LCD to top row
  if(iteration = 1) {
  lcd.print("Input Latitude"); // print instructions to operator
  }
  else {
  lcd.print("Input Longitude"); // print instructions to operator
  }
  int space = 0;
  int digit[] = {0,0,0,0,0,0,0,0,0};
  int run = 1;
  lcd.setCursor(0,1);
  lcd.print("0000.0000");
  delay(200);
  while(run = 1) {
    while(Serial.available() > 0) {    
      lcd.write(Serial.read());  // read the buttons
    }
    switch (lcd_key)  {    // depending on which button was pushed, we perform an action   
      case btnRIGHT: {     
        space++;
        if (space == 4) {
          space++;
        }
      }
      case btnLEFT: {     
        space--;
        if (space == 4) {
          space--;
        }     
      }
      case btnUP: {
        digit[space] = digit[space] + 1;
        lcd.setCursor(space,1);
        lcd.print(digit[space]);
      }
      case btnDOWN: {
        digit[space] = digit[space] - 1;
        lcd.setCursor(space,1);
        lcd.print(digit[space]);
      }   
      case btnSELECT: {     
        run = 0;
      }
      case btnNONE:{
      }
    }
    String digit0 = "";
    digit0 += digit[0];
    String digit1 = "";
    digit1 += digit[1];
    String digit2 = "";
    digit2 += digit[2];
    String digit3 = "";
    digit3 += digit[3];
    String digit5 = "";
    digit5 += digit[5];
    String digit6 = "";
    digit6 += digit[6];
    String digit7 = "";
    digit7 += digit[7];
    String digit8 = "";
    digit8 += digit[8];
    String coordinate = "";
    coordinate += digit0 + digit1 + digit2 + digit3 + digit5 + digit6 + digit7 + digit8;
    return coordinate;
 }
}

int read_LCD_buttons(){ 
adc_key_in = analogRead(0);      // read the value from the sensor  
 // my buttons when read are centered at these valies: 0, 144, 329, 504, 741 
 // we add approx 50 to those values and check to see if we are close 
 if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result 
 if (adc_key_in < 50)   return btnRIGHT;   
 if (adc_key_in < 195)  return btnUP;  
 if (adc_key_in < 380)  return btnDOWN;  
 if (adc_key_in < 555)  return btnLEFT;  
 if (adc_key_in < 790)  return btnSELECT;    
 return btnNONE;  // when all others fail, return this...
}
  1. Delays don't work. Even if I made a long enough delay, I am trying to get it so that the user hits a button (the select button) and the data is passed into the code. There are a series of 0's displayed across the LCD. The user is supposed to move the cursors (left or right) and then change the digit values using (higher or lower). Once the user is satisfied with the numbers displayed, the user hits the select button to then input another value.

I have tried placing a while loop that would only be satisfied until that select button was hit. However, this did not solve the problem, as all the LCD continued to not show any input changes.

You have multiple mistakes in your code. You should read up on "if statement".
You should have double equal in while and if statement like if (iteration==1).

I understand your intent. I have software library that does the input you want but will need modification to run on your shield. I feel like most of us have become free tech support for this dfrobot company. They produce cheap and low quality designs and leave the arduino forum to support them. I am not interested in modifying my library to support their product, would just help them such more money and burden us more. Be my guest if you want to modify it though.

Hi...

I have that exact LCD and use the code below to drive it. I can't remember where I downloaded the code from, but it worked out of the box and the original author's name is at the top. (EDIT: I see I got the code from the DFR page you linked to....)

I modified it very slightly to turn on an LED when one of the buttons is pressed and off again with another.

//Sample using LiquidCrystal library
#include <LiquidCrystal.h>
 
/*******************************************************
 
This program will test the LCD panel and the buttons
Mark Bramwell, July 2010
Jim May 2012... also "up" button lights up led on pin 2
 
********************************************************/

// select the pins used on the LCD panel
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);  
 
// define some values used by the panel and buttons
int lcd_key     = 0;
int adc_key_in  = 0;
#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5
 
// read the buttons
int read_LCD_buttons()
{
 adc_key_in = analogRead(0);      // read the value
 
 // his buttons when read are centered at these valies: 0, 144, 329, 504, 741
 // and with no button pressed 1023
 
 // we add approx 50 to those values and check to see if we are close
 if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result
 if (adc_key_in < 50)   return btnRIGHT;  
 if (adc_key_in < 195)  return btnUP; 
 if (adc_key_in < 380)  return btnDOWN; 
 if (adc_key_in < 555)  return btnLEFT; 
 if (adc_key_in < 790)  return btnSELECT;   
 return btnNONE;  // when all others fail, return this...
}
 
void setup()
{
  // initialize the digital pin2 as an output and force it low
  pinMode(2, OUTPUT); 
  digitalWrite(2, LOW);
  // then do lcd stuff...
 lcd.begin(16, 2);              // start the library
 lcd.setCursor(0,0);
 lcd.print("Push a button..."); // print a simple message
}
  
void loop()
{
  //led on 2 test
  //digitalWrite(2, HIGH);
 lcd.setCursor(12,1);            // move cursor to second line "1" and 9 spaces over
 lcd.print(millis()/1000);      // display seconds elapsed since power-up
 
 
 
 lcd_key = read_LCD_buttons();  // read the buttons
 lcd.setCursor(7,1);            //print the raw value
 lcd.print("    ");             //first clearing cos they not all same length so last number might show from under
 lcd.setCursor(7,1);  
 lcd.print(adc_key_in);          
 
 lcd.setCursor(0,1);            // move to the begining of the second line
 switch (lcd_key)               // depending on which button was pushed, we perform an action
 {
   case btnRIGHT:
     {
     lcd.print("RIGHT ");
     break;
     }
   case btnLEFT:
     {
     lcd.print("LEFT   ");
     break;
     }
   case btnUP:
     {
     lcd.print("UP2LED");
     digitalWrite(2, HIGH);  //led on
     break;
     }
   case btnDOWN:
     {
     lcd.print("DOWN  ");
     digitalWrite(2, LOW); //led off
     break;
     }
   case btnSELECT:
     {
     lcd.print("SELECT");
     break;
     }
     case btnNONE:
     {
     //digitalWrite(2, LOW);  //make sure led is off again
     lcd.print("NONE  ");
     break;
     }
 }
 
}

Thanks for all the help I have been getting. I have been taking this time to modify my project to the solutions you have provided. I will post the results hopefully soon.

EDIT: I changed up the code a lot and moved things around. I made some progress where it seems like the buttons are starting to listen to me. However, they are not completing their necessary function.
When I hit the up button, I want the digit value at the cursor to increase in value. The down button would decrease the cursored value. The left and right move the cursor. The left and right buttons also make sure it doesn't hover over the '.' character.

The problem now is when I hit a button, it spits out 8 more zeroes and will do so with everytime I hit the button. Once the LCD is full, the LCD goes blank.

I have tried the clear() option in a few areas where it might be duplicating. But the issue continues. I feel like it is somewhere in my case statements.

void loop(){
  if(iteration == 1) {
  lcd.print("Input Latitude"); // print instructions to operator
  }
  else {
  lcd.print("Input Longitude"); // print instructions to operator
  }
  while( iteration < 3) {
  iteration++;
  int space = 0;
  int digit[] = {0,0,0,0,0,0,0,0};
  int run = 1;
  lcd.setCursor(0,1);
  lcd.print("00000000");
  delay(200);
  while(run = 1) {
    lcd.setCursor(0,1);
    lcd_key = read_LCD_buttons();
    while(lcd_key == 5) {    
      lcd_key = read_LCD_buttons();
    }
    switch(lcd_key) {
    case btnRIGHT: {     
        if(space = 8) space = 0;
        else space++;
      }
      case btnLEFT: {     
        if(space = 0) space = 7;
        else space--;
      }
     case btnUP: {
        digit[space] = digit[space] + 1;
      }
      case btnDOWN: {
        digit[space] = digit[space] - 1;
      }   
     case btnSELECT: {     
        run = 0;
      }
    }
      digit0 += digit[0];
      digit1 += digit[1];
      digit2 += digit[2];
      digit3 += digit[3];
      digit4 += digit[4];
      digit5 += digit[5];
      digit6 += digit[6];
      digit7 += digit[7];
      coordinate = "";
      coordinate += digit0 + digit1 + digit2 + digit3 + digit4 + digit5 + digit6 + digit7;
      lcd.setCursor(16,2);
      lcd.clear();
      if(iteration == 2) {
      lcd.print("Input Latitude"); // print instructions to operator
      }
      else {
      lcd.print("Input Longitude"); // print instructions to operator
      }
      lcd.setCursor(0,1);
      lcd.print(coordinate);
      delay(200);
    }
    if (iteration == 2) {
    latitudeDestination = coordinate;
    }
    else {
    longitudeDestination = coordinate;
    }
  }

Even if I made a long enough delay, I am trying to get it so that the user hits a button (the select button) and the data is passed into the code.

I just want to clarify this 'delay' concept so that it may be of use to you in the future. The delay that I proposed would only be a temporary troubleshooting device that would be removed from the final code.

don

OP, you are dealing with a complex situation:

  1. Buttons need to be debunced and button up-to-down transition needs to be detected. You are not debuncing. You only have certain thing done when a button is down so if the button is down, the thing will repeat as fast as arduino can minus the delay. It's a very basic mistake. You should detect the transition, not the current state. If you press down the button, the transition of up-to-down only happens once, so you can use that as a cue to run something, once per button press. If you detect button down state instead, it will fire that "something you do" repeatedly, thus the 8 zeros. Hint: read up on how to process buttons. You need a variable to track the state of the button.

  2. You need a flow chart to tell yourself what should happen if certain condition is met, such as the up button is pressed (hint: button up-to-down transition), what should happen. Don't just go and program it until you can describe this logic in a chart. Imagine you will hire some cheap labor to do this for you with a bunch of number cards and you will yell up/down/left/right. This cheap labor has the chart and follows your instruction on the chart. Right now, your logic needs fixing. You need a clear step-by-step plan, plan it well, and then turn the plan into code. Don't write the code and then try to change it when it doesn't do what you want.

  3. I don't find where you print your updated number once a button is pressed. Point to me where that is.

  4. You missed a few of these while(run = 1).

  5. Please don't just post the part you changed, post the entire code every time. I was going back and forth between two replies just to read your code cause you didn't include the entire code in your later posts.

  6. What is this line doing? "lcd_key == 5" Can you make it more readable?

  7. Did you watch the video? Was that what you need, half way into the video?