LCD Help?

Hi guys, first of all, I will get this said and out the way.. I am completely new to this. I have been learning to program with arduino for about 2-3 days now.. That's how new I am! I have never tried anything like this before so I hope you don't think my question is stupid!

So far, I have just been taking some of the example programs and messing around with them. I decided yesterday, after getting the hang of controlling outputs with a switch and stuff, I decided to try my hand with LDC's. What I am trying to do it to get an LCD (16x2) to cycle through messages where the top row stays constant and the bottom row cycles through. Then, when I press a switch, I want the top row to change and the bottom to keep going through the same cycle as before. I have tried multiple if/else commands but always I find the display reaching the end of its cycle before changing, whereas I want it to be instant. I managed it once, but it reverted back to the first message after cycling through again and I had to have an if/else statement under each cycle so it just got far too long and too much for a complete noob!
I want a way for it to recognise the button press and change the top line of the LCD while keeping the same cycle on the bottom line.

I would post my code so far, but I have just started it again from scratch as it was getting too hard to follow. I was going to write it this time with a goto command instead but being as I am attempting to research as many ways as possible, this seems like an option alot of people don't seem to agree with.

I hope this makes sense to you guys and you don't think I am completely stupid!

Many thanks!

Conceptually, I imagine you would have some sort of continuous loop for line 2.
Now since you probably want line 1 to change any time, u would have to check the status of the switch input between each change within the line 2 loop.

On detection of status change of the switch, line 1 change is implemented and the line 2 loop continues.

For the switch presses, u might want a counter, when the count is even, display "abc" on line 1; when the count is odd, display "cba" on line 1. Alternatively u can just check for HIGH or LOW.

@econjack, yes, the hello world program is what I started with. That ran fine, and the messages I was displaying were fine. It was when I tried other things I had issues.

@aisc, yes, line 2 will be a continuous loop, and line 1 is changed with a button press. I did check for the HIGH and LOW status of the input and managed to get it to change, however, line 1 reverted back to its original display once line 2 had finished its loop. I wanted line 1 to ONLY change with the press of a button. Hence why I was considering the goto option, which people are rather much against so am trying to do it a different way.

If it helps, here is the code I have come up with to get the top line to switch while keeping the bottom line cycling through.

The problem with this one is that it waits untill the end of the loop before changing.

#include <LiquidCrystal.h>            // Specify library code to use

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);  // Use the default pins for the MAPLIN LCD shield. Pins are Arduino I/O D4-D9

void setup() {
 pinMode(11, INPUT);             // Set digital I/O pin as switch
 lcd.begin(16, 2);               // set up the LCD's number of columns and rows:
}

void loop() {
 if (digitalRead(11) == LOW) {   // LCD displays first constant message
 lcd.print("constant 1");      // Message to be sent to LCD
 lcd.setCursor(0, 1);            // set where second row starts
 lcd.print("loop 1");              // display first loop message
 delay(2500);                    // delay
 lcd.clear();                    // clear LCD
 delay(100);                     // delay 
 lcd.setCursor(0, 0);            // Set where LCD starts again
 lcd.print("constant 1");      // reset constant message on 
 lcd.setCursor(0, 1);            // Set row 1 of LCD to begin writing
 lcd.print("loop 2");    // display second loop message
 delay(2500);                    // delay 
 lcd.clear();                    // clear LCD
 delay(100);                     // delay 
 lcd.setCursor(0, 0);            // Set where LCD starts again
 lcd.print("constant 1");      // reset constsnt message 
 lcd.setCursor(0, 1);            // Set row 1 of LCD to begin writing
 lcd.print("loop 3");          // display third loop message
 delay(2500);                    // delay 
 lcd.clear();                    // clear LCD
 delay(100);                     // delay 
 lcd.setCursor(0, 0);            // Set where LCD starts again
 lcd.print("constant 1");      // reset default message on line 0
 lcd.setCursor(0, 1);            // Set row 1 of LCD to begin writing
 lcd.print("loop 2");    // display fourth loop message
 delay(2500);                    // delay 
 lcd.clear();                    // clear LCD
 delay(100);                     // delay for 
 lcd.setCursor(0, 0);            // Set where LCD starts again
 }

 else {
 lcd.print("constant 2");      // Message to be sent to LCD
 lcd.setCursor(0, 1);            // set where second row starts
 lcd.print("loop 1");              // display first loop message
 delay(2500);                    // delay
 lcd.clear();                    // clear LCD
 delay(100);                     // delay 
 lcd.setCursor(0, 0);            // Set where LCD starts again
 lcd.print("constant 2");      // reset constant message on 
 lcd.setCursor(0, 1);            // Set row 1 of LCD to begin writing
 lcd.print("loop 2");    // display second loop message
 delay(2500);                    // delay 
 lcd.clear();                    // clear LCD
 delay(100);                     // delay 
 lcd.setCursor(0, 0);            // Set where LCD starts again
 lcd.print("constant 2");      // reset constsnt message 
 lcd.setCursor(0, 1);            // Set row 1 of LCD to begin writing
 lcd.print("loop 3");          // display third loop message
 delay(2500);                    // delay 
 lcd.clear();                    // clear LCD
 delay(100);                     // delay 
 lcd.setCursor(0, 0);            // Set where LCD starts again
 lcd.print("constant 2");      // reset default message on line 0
 lcd.setCursor(0, 1);            // Set row 1 of LCD to begin writing
 lcd.print("loop 4");    // display fourth loop message
 delay(2500);                    // delay 
 lcd.clear();                    // clear LCD
 delay(100);                     // delay for 
 lcd.setCursor(0, 0);            // Set where LCD starts again
 }
}

Now, I am positive someone will be able to shorten that up massively and be able to solve my issue, but if you are able to, can you please mention how that particular bit of code works when you do it? Otherwise I won't learn!
As I said, I am very new and this is only my third day of learning programming.

The only way I can think to do it is using goto and getting having the program check for a button press after every loop message.... but that seems like a very long winded way of doing it and I am sure there are much better ways!

Thank you!

You need to look into using millis() for timing as in the BlinkWithoutDelay example and Several things at the same time
Save the time an event happens, such as when a message is displayed, then each time through loop() check whether the required period has elapsed since the event. If not then go round loop() again reading inputs and changing line 1. If the period has elapsed then take the required action such as changing line 2

You can do yourself a favour by putting the messages in arrays which will make it easier to cycle through them by changing the index value when the period has elapsed (line 2) or the button becomes pressed (line 1)

angath:
The only way I can think to do it is using goto and getting having the program check for a button press after every loop message.... but that seems like a very long winded way of doing it and I am sure there are much better ways!

Thank you!

The blocking delays are not conducive to your pin change detection method.

You can look at this example and perhaps you can figure out how to move the display to the next state with a pushbutton instead of the timer:

I think once you study the example, you will understand.

edit: Untested!

#include <LiquidCrystal.h>            // Specify library code to use
#include <Wire.h>

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);  // Use the default pins for the MAPLIN LCD shield. Pins are Arduino I/O D4-D9

void setup()
{
  pinMode(11, INPUT);             // Set digital I/O pin as switch
  lcd.begin(16, 2);               // set up the LCD's number of columns and rows:
}

int lcdState = 4;
int lastState = 4;

void loop() 
{
  static unsigned long lastMillis = 0;
  if (millis() - lastMillis > 2500UL)
  {
    lcdState++;
    if (lcdState > 4)
    {
      lcdState = 0;
    }
    lastMillis = millis();
  }
  
  //Put your pinChange state detection here instead of the timer above
  
  if (lcdState != lastState)
  {
    switch (lcdState)
    {
      case 0:
        lcd.setCursor(0, 1);
        lcd.print("constant 1      "); // easy way to clear the lcd chars
        lcd.setCursor(0, 1); 
        lcd.print("loop 1          ");
        break;
      case 1:
        lcd.setCursor(0, 1); 
        lcd.print("loop 2          ");
        break;
      case 2:
        lcd.setCursor(0, 1);
        lcd.print("constant 2      "); // easy way to clear the lcd chars
        lcd.setCursor(0, 1); 
        lcd.print("loop 1          ");
        break;
      case 3:
        lcd.setCursor(0, 1); 
        lcd.print("loop 2          ");
        break;
      case 4:
        lcd.setCursor(0, 1); 
        lcd.print("loop 3          ");
        break;
    }
    lastState = lcdState;
  }
}

Thank you both very much for the help.

UKHeliBob, I have not looked into using arrays yet, that seems a bit advanced for me at the moment, but I hope to start looking into them more as I get better.

Bulldog, I am trying to get my head around your code now... I will upload it into the arduino tonight and see if I can visually see what happens, that should help me understand a bit more, then I can edit to my liking! What is that pinChange detector instead of the timer? Are you saying dont use the timer? And what are the cases? I have not used these before.

Sorry if I sound silly, but as I mentioned before, 3rd day!

angath:
Thank you both very much for the help.

UKHeliBob, I have not looked into using arrays yet, that seems a bit advanced for me at the moment, but I hope to start looking into them more as I get better.

Bulldog, I am trying to get my head around your code now... I will upload it into the arduino tonight and see if I can visually see what happens, that should help me understand a bit more, then I can edit to my liking! What is that pinChange detector instead of the timer? Are you saying dont use the timer? And what are the cases? I have not used these before.

Sorry if I sound silly, but as I mentioned before, 3rd day!

My code simply changes the display every 2500milliseconds, but in a non-blocking fashion. You wanted to change the display on a button press, modifying my example will be trivial, even for a newcomer.

Switch Case conditional statements are a lot like if (-then-else if) type of conditional statements.

refer to the state change detection sample code included in the arduino IDE:

/*
  State change detection (edge detection)

 Often, you don't need to know the state of a digital input all the time,
 but you just need to know when the input changes from one state to another.
 For example, you want to know when a button goes from OFF to ON.  This is called
 state change detection, or edge detection.

 This example shows how to detect when a button or button changes from off to on
 and on to off.

 The circuit:
 * pushbutton attached to pin 2 from +5V
 * 10K resistor attached to pin 2 from ground
 * LED attached from pin 13 to ground (or use the built-in LED on
   most Arduino boards)

 created  27 Sep 2005
 modified 30 Aug 2011
 by Tom Igoe

This example code is in the public domain.

 http://arduino.cc/en/Tutorial/ButtonStateChange

 */

// this constant won't change:
const int  buttonPin = 2;    // the pin that the pushbutton is attached to
const int ledPin = 13;       // the pin that the LED is attached to

// Variables will change:
int buttonPushCounter = 0;   // counter for the number of button presses
int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button

void setup() {
  // initialize the button pin as a input:
  pinMode(buttonPin, INPUT);
  // initialize the LED as an output:
  pinMode(ledPin, OUTPUT);
  // initialize serial communication:
  Serial.begin(9600);
}


void loop() {
  // read the pushbutton input pin:
  buttonState = digitalRead(buttonPin);

  // compare the buttonState to its previous state
  if (buttonState != lastButtonState) {
    // if the state has changed, increment the counter
    if (buttonState == HIGH) {
      // if the current state is HIGH then the button
      // wend from off to on:
      buttonPushCounter++;
      Serial.println("on");
      Serial.print("number of button pushes:  ");
      Serial.println(buttonPushCounter);
    }
    else {
      // if the current state is LOW then the button
      // wend from on to off:
      Serial.println("off");
    }
    // Delay a little bit to avoid bouncing
    delay(50);
  }
  // save the current state as the last state,
  //for next time through the loop
  lastButtonState = buttonState;


  // turns on the LED every four button pushes by
  // checking the modulo of the button push counter.
  // the modulo function gives you the remainder of
  // the division of two numbers:
  if (buttonPushCounter % 4 == 0) {
    digitalWrite(ledPin, HIGH);
  } else {
    digitalWrite(ledPin, LOW);
  }

}

Yes, but I only wanted to change the top line of the display on the button press, where the bottom line continues its loop, then another press of the button will revert the top line back to the original text.

I assume I will be able to do that from your example and this switch state tutorial?

angath:
Yes, but I only wanted to change the top line of the display on the button press, where the bottom line continues its loop, then another press of the button will revert the top line back to the original text.

I assume I will be able to do that from your example and this switch state tutorial?

Try it and see what happens. Changing the top line versus the bottom line, or even a single character at say row zero column 3 is trivial.

and for the sake of risking being snooty,

where the bottom line continues its loop

I follow its meaning but your word choice is poor.

You want the program to maintain one line and simply change the other... then you may want to change both lines...

Temperature:
32F
Temperature:
0C
Temperature:
273K
Relative Humidity:
38%

I see what you mean with my word choice... It wasn't my finest moment! I will give this a go tomorrow and make whatever changes I need to and post the result if I manage to get the result I am after! Thank you very much for your patience and help, and don't worry about risking sounding snooty or anything, if you are helping me learn, be as snooty as you need to get your point across, I want to learn and you have the knowledge!

Thank you again!

angath:
@aisc, yes, line 2 will be a continuous loop, and line 1 is changed with a button press. I did check for the HIGH and LOW status of the input and managed to get it to change, however, line 1 reverted back to its original display once line 2 had finished its loop. I wanted line 1 to ONLY change with the press of a button. Hence why I was considering the goto option, which people are rather much against so am trying to do it a different way.

This is the approach I would use...

  1. write a function to print to line 1
  2. write a function to print to line 2 with a display delay() or u can use millis()
void LCDprintln2(char *msg, int dlay ) {
  lcd.setCursor(0,1);
  lcd.print(F("                "));
  lcd.setCursor(0,1);
  lcd.print(msg);
  delay(dlay);
}

put your line 2 messages into array i.e. an array of arrays.

char line2a[] = "    Line 2 A    ";
char line2b[] = "    Line 2 B    ";
char line2c[] = "    Line 2 C    ";
char *array_line2[] = {line2a, line2b, line2c};

Now create a loop which cycles through the line 2 array.
Now you have a starting point.
All u have to do now is figure out how to add line 1.
N.B. by filling the lines with 16 chars, u don't have to print the blank line in the function