Advanced Scrolling on 16 x 2 LCD with user input at the same time

...maybe this isn't advanced to some folk, but it sure is to me! I'm having trouble figuring this out and my code just gets worse and worse. Here's what I'm trying to do: Scroll this message across the top line of the LCD: String stringOne = "Enter the number of cups, followed by the '*' "; And then have the blinking cursor in the center of the second line. The users input will be displayed here. Input is coming from a keypad set up like the hellokeypad demo, so this would get the key press:   char key = keypad.getKey();

I'm at a loss--the autoscroll function uses delay() to scroll the text, but I will miss key presses with that method. And then there's this: I'd really like the user to be able to enter the numbers 10 and 12, which means 2 keypresses, saving the first digit, the second digit, adding them together, checking for the '*' keypress, still auto scrolling... It's almost overwhelming! If this all sounds fairly simple to someone, could you please post a little code on how to do it?

Thanks!

Try simplifying your features at first. After you have a simple program working then add more features one at a time. Here are some thoughts:

(1) Leave out the scrolling for now. Not only does it use delay() but, due to the way the LCD controller works it probably also scrolls both lines simultaneously unless they have done some fancy programming in the library.

(2) Work with only single digit entries at first, then only two digit entries, and finally either one or two digit entries.

Don

I'd like to figured out this scrolling a little more. Does anyone know of some good tutorials on advanced scrolling? I've noticed that this LCD must have 40 spaces across a line, even though you can't see them, because it take 39 chars before it start wrapping to the next line. I'm just using the standard library that came with the Arduino 0022.

This actually scrolls without delay! But it still doesn’t work. :frowning:
Can someone tell me why the end of the string switches to the bottom row, or better yet tell me how to fix it!
thanks.

/*
 Demonstrates the use a 16x2 LCD display.  The LiquidCrystal
 library works with all LCD displays that are compatible with the 
 Hitachi HD44780 driver. There are many of them out there, and you
 can usually tell them by the 16-pin interface.
 
 The circuit:
 * LCD RS pin to digital pin 12
 * LCD Enable pin to digital pin 11
 * LCD D4 pin to digital pin 5
 * LCD D5 pin to digital pin 4
 * LCD D6 pin to digital pin 3
 * LCD D7 pin to digital pin 2
 * LCD R/W pin to ground
 */

// include the library code:
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

String str1 = "'Hello World' was not long enough";  // using a constant String
String strClear = "                  ";
long previousMillis = 0;        // will store last time LCD was updated
long interval = 300;           // interval at which to update LCD (milliseconds)

void setup() {
  // set up the LCD's number of columns and rows: 
  lcd.begin(16,2);
  Serial.begin(9600);
}

void loop() {
str1 = str1 + strClear;

  int i;
  lcd.setCursor(16,0); 

  for (i = 0; i < str1.length() ; ) {
    // wait without delay:
    unsigned long currentMillis = millis();
 
    if(currentMillis - previousMillis > interval) {
      //update last LCD write
      previousMillis = currentMillis;   
      Serial.println(str1.charAt(i));
      lcd.print(str1.charAt(i));
      lcd.scrollDisplayLeft(); 
      i++;
    }
  //Do something else here, like check keypress events
  }
  // clear screen for the next loop:
  lcd.clear();
}

Can someone tell me why the end of the string switches to the bottom row,

A complete description of this phenomena can be found by following the [u]LCD Addressing[/u] link at http://web.alfredstate.edu/weimandn.

or better yet tell me how to fix it!

If you've checked out the link you will know what has to be done. I believe this action has been implemented in the LiquidCrystal440 library.

You have to remember that the LCD controller was designed more than two decades ago and was subject to the technology restrictions of the time. The display was not meant to be a substitute for a CRT terminal, it was really meant to display short messages such as the Time and Date or Replace Toner etc.

Don

I believe this action has been implemented in the LiquidCrystal440 library.

Will this library work for a 16 x 2 display? I looked at it but it looked like it was set for 40x4. Is there an example sketch of it somewhere working on a 16x2? thanks

I’ve got this working, scroll text on the top, and posting a user input number on the bottom, in the center. Not sure how it works, but it works, so I guess it’ll do to incorporate into my main sketch. If there’s an improvement on this out there, I’d like to know about it…

/*
 Demonstrates the use a 16x2 LCD display.  The LiquidCrystal
 library works with all LCD displays that are compatible with the 
 Hitachi HD44780 driver. There are many of them out there, and you
 can usually tell them by the 16-pin interface.
 
 The circuit:
 * LCD RS pin to digital pin 12
 * LCD Enable pin to digital pin 11
 * LCD D4 pin to digital pin 5
 * LCD D5 pin to digital pin 4
 * LCD D6 pin to digital pin 3
 * LCD D7 pin to digital pin 2
 * LCD R/W pin to ground
 */

// include the library code:
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

String str1 = "Select 2-12 cups, & press *    ";  // using a constant String
String strClear = "                  ";
long previousMillis = 0;        // will store last time LCD was updated
long interval = 400;           // interval at which to update LCD (milliseconds)
int UserData = 2;    //input from serial monitor
int MyNumber = 13;

void setup() {
  // set up the LCD's number of columns and rows: 
  lcd.begin(16,2);
  Serial.begin(9600);
}

void loop() {
//str1 = str1 + strClear;

  int i;
  int j = 17;
  lcd.setCursor(16,0); 

  for (i = 0; i < str1.length() ; ) {
    // wait without delay:
    unsigned long currentMillis = millis();
 
    if(currentMillis - previousMillis > interval) {
      //update last LCD write
      previousMillis = currentMillis;   
      Serial.println(i);
//      if(i==24) lcd.setCursor(i,1);
      if (i==23) j=-23;
      lcd.print(str1.charAt(i));
      lcd.scrollDisplayLeft();
      lcd.setCursor(6+i,1);

      lcd.print("  "); 
      lcd.print(MyNumber); 
//      lcd.print(" " + UserData); 
      lcd.setCursor(j+i,0);
      i++;
    }
    //Check for keypress event here
    CheckSerial();
  }
  // clear screen for the next loop:
  delay(2000);
  lcd.clear();
}


void CheckSerial(){
  if (Serial.available() > 0) {
      // get incoming byte:
      MyNumber = Serial.read();
  }

Will this library work for a 16 x 2 display?

Why wouldn't it? It is promoted as an enhancement with additions to do various features. See: http://code.google.com/p/liquidcrystal440/

Don

floresta:

Will this library work for a 16 x 2 display?

Why wouldn't it? It is promoted as an enhancement with additions to do various features. See: http://code.google.com/p/liquidcrystal440/

Don

I did, and downloaded it, but there were no examples...

Oops - I just read this part of his description: "The software does not handle autoScroll, however. "

I’m not quite sure what he means by autoScroll here. I was pretty sure he took care of the scrolling from line to line when you send a lot of characters so that it works more like you would expect. (Line 1-2-3-4 instead of the native Line 1-3-2-4).

I believe that what the Arduino developers call ‘scrolling’ is what the Hitachi developers call ‘shifting’. The ‘Cursor and Display Shift’ command built into the LCD controller shifts the entire display (both lines together or all four lines together as applicable). I think that this behavior is what John has not fixed up.

Don

I found something that works great, ...scrolls the top line, no matter how long the string is, and lets me put data in the bottom line without worrying about where ther top line is: Thanks to JeffB42 at http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1246484182 I had to add the begin(16,2) line...

I'm not prepared to try and decipher un-commented code. At a glance I don't see where the second line is implemented, but I don't do much C programming either. When you have information displayed on the bottom line does it stay put when the top line shifts?

Don

Here’s what I’ve finished up with: It does work nice, and the bottom line stays put. The LCD seems plenty clear to read.

…off the main subject, but I want to figure out how to remove the line:

const int MESSAGE_LENGTH = 60;

So that I could pass any string into this and have it programatically tell how long it is.
str.length() doesn’t work with char str, but there must be a way to tell how long str is?

#include <LiquidCrystal.h>

const int BACK_LIGHT = 13;                  // Pin 13 will control the backlight
const char* MESSAGE = "      Got Coffee?  Enter amount needed and press *          ";
const int MESSAGE_LENGTH = 60;
const int DISPLAY_WIDTH = 16;


/* Connections:
 * LCD RS pin to digital pin 12
 * LCD Enable pin to digital pin 11
 * LCD D4 pin to digital pin 5
 * LCD D5 pin to digital pin 4
 * LCD D6 pin to digital pin 3
 * LCD D7 pin to digital pin 2
 * LCD R/W pin to ground
 */
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int nPosition = 0;
long previousMillis = 0;        // will store last time LCD was updated
long interval = 500;           // interval at which to update LCD (milliseconds)
int MyNumber = 10;      //input form serial monitor

void setup()
{
     lcd.begin(16,2);
     lcd.clear();                              // Start with a blank screen
     Serial.begin(9600);
}

void loop()
{
  unsigned long currentMillis = millis();  //get current time
 
  if(currentMillis - previousMillis > interval) {  //check if it's been long enough to shift left

      previousMillis = currentMillis;        //update last LCD write
    
         int i;
         if(nPosition < MESSAGE_LENGTH - DISPLAY_WIDTH)
         {
               for(i=0; i<DISPLAY_WIDTH; i++)
               {
                     lcd.setCursor(i, 0);
                     lcd.print(MESSAGE[nPosition + i]);
               }
         }
         
         else
         {
               int nChars = MESSAGE_LENGTH - nPosition;
               for(i=0; i<nChars; i++)
               {
                     lcd.setCursor(i, 0);
                     lcd.print(MESSAGE[nPosition + i]);
               }
    
               for(i=0; i<(DISPLAY_WIDTH - nChars); i++)
               {
                     lcd.setCursor(nChars + i, 0);
                     lcd.print(MESSAGE[i]);
               }
         }
    
         nPosition++;
         if(nPosition >= MESSAGE_LENGTH)
         {
               nPosition = 0;
         }
          lcd.setCursor(8,1);
          lcd.print(char(MyNumber));
          CheckSerial();
  }     
}



void CheckSerial(){
  if (Serial.available() > 0) {
      // get incoming byte:
      MyNumber = Serial.read();
  }
}