I just programmed this code below for scrolling LCD text, and for whatever reason it freezes at 45 characters... (Don't mind the "customdelay()" as it does the same function as delay, and the "if(exitready)", as I've just set this code up to be able to exit by user input)
void lcdScroll(String text, int delaytime){
//LOAD THE STRING IN ADVANCE (I have no idea why I have to do this, just other wise it throws an error...)
lcd.print(text.substring(0,0));
char chartext[text.length()];
text.toCharArray(chartext, text.length() + 1);
lcd.setCursor(0, 0);
lcd.print(sizeof(chartext));
for (int a = 0; a < sizeof(chartext); a += 1){
if(exitready){
return;
}
for (int b = 15; b >= 0; b -= 1){
if(a - ((b - 15) * (-1)) > -1){
lcd.setCursor(b, 0);
lcd.print(chartext[a - ((b - 15) * (-1))]);
}
}
customdelay(delaytime);
}
lcd.clear();
}
I compiled your program, which came to 7560 bytes. (I have to comment out those parts I don't have source for.) I don't know why, but it did not hang on my system. However, using the String class is a waste of memory. I made a few minor changes without the String class:
/* YourDuino.com Example Software Sketch
20 character 4 line I2C Display
Backpack Interface labelled "YwRobot Arduino LCM1602 IIC V1"
Connect Vcc and Ground, SDA to A4, SCL to A5 on Arduino
terry@yourduino.com */
/*-----( Import needed libraries )-----*/
#include <Wire.h> // Comes with Arduino IDE
// Get the LCD I2C Library here:
// https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads
// Move any other LCD libraries to another folder or delete them
// See Library "Docs" folder for possible commands etc.
#include <LiquidCrystal_I2C.h>
/*-----( Declare Constants )-----*/
/*-----( Declare objects )-----*/
// set the LCD address to 0x27 for a 20 chars 4 line display
// Set the pins on the I2C chip used for LCD connections:
// addr, en,rw,rs,d4,d5,d6,d7,bl,blpol
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Set the LCD I2C address
/*-----( Declare Variables )-----*/
void setup() /*----( SETUP: RUNS ONCE )----*/
{
char text[] = "When in the course of human events it becomes necessary to dissolve the political bands...";
Serial.begin(9600); // Used to type in characters
lcd.begin(20,4); // initialize the lcd for 20 chars 4 lines, turn on backlight
lcdScroll(text, 250);
}/*--(end setup )---*/
void loop() /*----( LOOP: RUNS CONSTANTLY )----*/
{
}/* --(end main loop )-- */
void lcdScroll(char *text, int delaytime){
//LOAD THE STRING IN ADVANCE (I have no idea why I have to do this, just other wise it throws an error...)
// lcd.print(text.substring(0,0));
// char chartext[text.length()];
// text.toCharArray(chartext, text.length() + 1);
int chartext = strlen(text);
Serial.println(chartext);
lcd.setCursor(0, 0);
lcd.print(chartext);
for (int a = 0; a < chartext; a += 1){
/*
if(exitready){
return;
}*/
for (int b = 15; b >= 0; b -= 1){
if(a - ((b - 15) * (-1)) > -1){
lcd.setCursor(b, 0);
lcd.print(text[a - ((b - 15) * (-1))]);
}
}
delay(delaytime);
}
lcd.clear();
}
and it compiles to 5824 bytes; a pretty significant savings.
Here is one I wrote awhile back.
I don't think I made it compatible with strings larger than 20 characters but I can fix that when I get home tonight.
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#define N_CHARS ((sizeof(MessageOut)/sizeof(MessageOut[0]))-1)
#define N_CHARS2 ((sizeof(MessageOut2)/sizeof(MessageOut2[0]))-1)
LiquidCrystal_I2C lcd(0x20, 20, 4); // set the LCD address to 0x20 for a 16 chars and 2 line display
int index = 19, index2 = 0;
void setup()
{
lcd.init(); // initialize the lcd
lcd.backlight();
}
void loop()
{
setHeadingRight("Hello", 0, 1000); // message, row, duration
setHeadingLeft("Welcome", 1, 500);
}
void setHeadingRight(char * msg, byte row, unsigned long duration)
{
static char MessageOut[21];
static long oldTime = millis();
strncpy(MessageOut, msg, sizeof(MessageOut));
if (millis() - oldTime > duration) // check the difference of the current time "millis()" to the previous time "oldTime" against the duration you want.
{
oldTime += duration; // update oldTime with the current time
if (index >= 0) // make sure the index does not go under 0
{
index--; // decrecment index by 1
for (int i = 0; i < N_CHARS; i++) // this part here displays the message on the display
{
lcd.setCursor(i, row); // set the column to show the element in the array
if (index == N_CHARS) index = 0; // set index back to 0 if the index has reached the arrays max size.
if (MessageOut[index++] != NULL) // if the element @ index is anything but NULL, show it.
lcd.print(MessageOut[index - 1]);
else
lcd.print(' '); // if the element @ index is NULL, display a space.
}
}
else index = 19; // if index is less than 0, then set it back to 19
}
}
void setHeadingLeft(char * msg, byte row, unsigned long duration2)
{
static char MessageOut2[21];
static long oldTime2 = millis();
strncpy(MessageOut2, msg, sizeof(MessageOut2));
if (millis() - oldTime2 > duration2)
{
oldTime2 += duration2;
if (index2 < 20) // check to see if index2 is under the array max size
{
index2++; // increment index
for (int i = 0; i < N_CHARS2; i++) // same as above
{
lcd.setCursor(i, row);
if (index2 == N_CHARS2) index2 = 0;
if (MessageOut2[index2++] != NULL)
lcd.print(MessageOut2[index2 - 1]);
else
lcd.print(' ');
}
}
else index2 = 0; // otherwise set it back to 0
}
}
5000 posts, woot 
@HazardsMind: your code stops scrolling after one "screen width" of text is processed and then repeats the same message. The OP code scrolls the entire message regardless of LCD screen width or the message length. The two versions are a little different.
EDIT: I just saw your caveat on the message length...never mind!
Thanks for the responses, I'll try these out when I get home from school...