LCDs and Strings and Substrings Oh My - Need help with my C++

So for starters, this is my first forum post so I'll try and make a good impression. :stuck_out_tongue:

Currently as a little side-fun-project thingy I'm developing a program that will take lots of text, adapt it for an LCD screen of a user-specified size, and then print that text line after line. The code will measure the text.length(), then act accordingly. The trouble comes after I need to go through more rows than the LCD screen has. By my calculations the String newString = text.substring(lcdCols * numOfRepeats, lcdCols * (numOfRepeats + 1) - 1); substring creator should work as I intend it to, but currently my lcd just shows a blank screen. (Hopefully you'll understand what's going on after reading the code...)

I know everything is working properly because the if and else if statements print just fine, but that last else statement is what gets me. If you need more clarification on what my code is actually doing, then by all means feel free to ask, but I think it's pretty easy to understand (I'm not exactly a C++ wizard 8)). Oh and by the way, does String.h actually do anything and is it needed at all for Arduino machine code?

And one more thing - is there already a way to do this? If so, please tell me. Also, If I'm missing some punctuation somewhere, my Arduino is going through the window ]:D. Thanks to anyone who can help!

#include <LiquidCrystal.h>
 #include <String.h>
 int numOfRepeats = 0;
 int numOfLinesPrinted = 0;
 //Variables to change
 LiquidCrystal lcd(12, 11, 5, 4, 3, 2); //Calling my LCD "lcd" w/ pins
 
 const int lcdCols = 16; //Number of columns in my lcd
 const int lcdRows = 2;//Number of rows in my lcd
 const int delayTime = 1000; //Value in milliseconds to delay the scroll
 
 String text = "This is example text that should need more than one line to print. Here's more text."; //The actual text
 
 void setup() {
   lcd.begin(lcdCols, lcdRows); 
 }
 
 void loop() {
   printString(text);
   numOfRepeats = 0;
 }
 
 void printString(String text) {
   if (text.length() <= lcdCols) {  //Prints the string if its length is
     lcd.clear();                                //Less than or equal to the # of cols
     lcd.print(text);
   }
   
   else if (text.length() <= lcdCols*lcdRows && lcdRows >= 2) { //Print the string if its length can be fit on the display
     for (int i; i <= lcdRows; i++) { //Without any scrolling - this works fine
       lcd.setCursor(0, i-1);
       String newString = text.substring(lcdCols * i - lcdCols, lcdCols * i - 1);
       lcd.print(newString);
     }
   }
   
   else {
    for (int counter = 0; counter <= text.length() / (lcdCols * lcdRows) + 1; counter++) {
      for (int i = 0; i <= lcdRows; i++) {
         lcd.setCursor(0, 1);
         String newString = text.substring(lcdCols * numOfRepeats, lcdCols * (numOfRepeats + 1) - 1);
         lcd.print(newString);
         delay(1000);
         numOfLinesPrinted++;
         numOfRepeats++;
       }
      delay(delayTime);
    }
   }
 }

Firstly let's give the normal advice and suggest that you use C style strings instead of Strings, particularly with all that String manipulation which tends to fragment memory.

@UKHeliBob using char arrays doesn't seem to work either...

What do you see if you Serial.println() newString in the last else ? Print a character such as > before it and < after it so that you can see how long it is.

I don't have an LCD display handy, but the code below uses the char array as suggested by UKHeliBob. Avoid the C++ String class whenever you can.

#include <String.h>


const int lcdCols = 16; //Number of columns in my lcd
const int lcdRows = 2;//Number of rows in my lcd
const int delayTime = 1000; //Value in milliseconds to delay the scroll

char text[] = "This is example text that should need more than one line to print. Here's more text."; //The actual text

void setup() {
  Serial.begin(115200);
  Serial.println("                |");  // The screen size
}

void loop() {
  printString(text);
}

void printString(char *text) {
  char temp[lcdCols + 1];
  int iterations;
  int len = strlen(text);

  if (len <= lcdCols) {  //Prints the string if its length is
    Serial.println(text);
    return;
  }
  iterations = len / lcdCols + 1;
  for (int counter = 0; counter < iterations; counter++) {
    strncpy(temp, &text[counter * lcdCols], lcdCols);
    temp[lcdCols] = '\0';
    Serial.println(temp);
    delay(delayTime);
  }
  Serial.println();
}

The Serial.println() call in setup() gives you a frame of reference for the width of a 2x16 LCD display.

Thanks for the help econjack - that code does work once I've adapted it to my LCD 8).