Vertical "moving" text on a LCD-display
waitUntilClear is always 0 when clearScreen is false then boolean flag is redundant:

void setDisplay(String lineValue, int lineNumber, unsigned long msToWaitBeforeClear) {
  lcd.setCursor(0, lineNumber),
  lcd.print(lineValue); 

  if (msToWaitBeforeClear &gt; 0) {
   delay(msToWaitBeforeClear);
   lcd.clear(); 
  }
}


Note that delay() accepts unsigned long instead of int then our parameter should match its type (does it make sense to have a negative delay?)

Now is (should be) clearer that we're calling setDisplay() twice but it's easier to simply call it with the index of the current line:

void displayPage(String messages[], size_t startIndex) {
  for (int8_t rowIndex = 0; rowIndex &lt; NUMBER_OF_DISPLAY_LINES; ++rowIndex) {
      lcd.setCursor(0, rowIndex),
      lcd.print(messages[startIndex + rowIndex]); 
  }

   delay(DELAY_BETWEEN_PAGES_IN_MS);
   lcd.clear(); 
}


Used as:

for (size_t i = 0; i &lt; COUNT_ELEMENTS - 1; ++i) {
  displayPage(messages, i);
} 


Now it's time to remove those magic numbers in setup() and lcd declaration. I'd also suggest to move all global constants to the very top, outside functions (probably in a separate file). It's what you want to change to configure your display and it's better if you don't have to search them buried inside code.

One small note: if you manually unroll the loop over NUMBER_OF_DISPLAY_ROWS then you can skip the first call to setCursor() because clear() already do it for you:

void displayPage(String messages[], size_t startIndex) {
    lcd.print(messages[startIndex]); 
    lcd.setCursor(0, 1),
    lcd.print(messages[startIndex + 1]); 

    delay(DELAY_BETWEEN_PAGES_IN_MS);
    lcd.clear(); 
}