[Solved] Unable to Display Two Lines on an LCD

I have been working on making a counter that displays the string "Total: " and has a left justified number, and similarly, this is displayed on the second line of the LCD. When trying to debug the program I can display each individual line on the display by themselves, but never on the screen simultaneously.

I believe I narrowed the problem down to the update function and how I make the String to display. This is because I can test other code with defined strings, not dynamic strings, that I know works and displays two lines.

I did set up the LCD as a 16x2 at the beginning of startup.

//Useful information to remove confusion
static char countText[] = "Total: "; // 7 chars long
static char specialText[] = "Interview: "; //11 chars long

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address

//String to display
char* text(char* initial, int num){
  int i = 0;
  //Make a left aligned count
  char actualArray[17];
  char* printText = actualArray;
  char count[9];
  itoa(num, count, 10);
  char spaces[16];
  int countLength = strlen(count);

  strcat(printText, initial);
  for(i = strlen(printText); i < (16-countLength); i++)
    strcat(spaces, " ");
  strcat(printText, spaces);
  strcat(printText, count);
  strcat(printText, "\0"); //Close the string and ignore if there is text here

  return printText;
}

//Function that is called everytime the count is updated
int UpdateScreen(){
  lcd.clear();

//  delay(50); //Debug
  
  lcd.setCursor(0,0); //Start at character 0 on line 0
  lcd.print(text(countText, cCount));

//  delay(50); //Debug

  lcd.setCursor(0,1);
  lcd.print(text(specialText, cRCount));

  return 0;
}

That is not your complete sketch.

Post that!

.

For those who want to see the rest of the sketch here is all I am willing to share because it long and not all of it is necessary to share.

#include <Wire.h>
#include<LiquidCrystal_I2C.h>
#include <string.h>

#define CLICKER_ONE A0
#define CLICKER_TWO A1
#define CLICKER_THREE A2
#define CLICKER_FOUR A3

static int inputArray[] = {CLICKER_ONE, CLICKER_TWO, CLICKER_THREE, CLICKER_FOUR};
int lCount, cCount;
int ClickOneLast, ClickTwoLast, ClickThreeLast, ClickFourLast;
int lRCount, cRCount;

unsigned long timer;

static char countText[] = "Total: "; // 7 chars long
static char specialText[] = "Interview: "; //11 chars long

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address

int UpdateScreen();
char* text(char* initial, int num);

void setup() {

  lCount = 0; cCount = 0;
  ClickOneLast = 0; ClickTwoLast = 0; ClickThreeLast = 0; ClickFourLast = 0;
  lRCount = 0; cRCount = 0;
  timer = 0;
  int i = 0;
  for(i = 0; i < 4; i++){
    pinMode(inputArray[i], INPUT_PULLUP); //Set the 4 inputs
  }

  Serial.begin(9600);
  lcd.begin(16,2);

  lcd.backlight();
  delay(250);
  lcd.noBacklight();
  delay(250);
  lcd.backlight(); //helps tell the arduino reset
  
  UpdateScreen();

}

void loop(){
  //It is unnecessary to share because it is a basic button counter
  //this calls UpdateScreen() if the button has been pressed
}

char* text(char* initial, int num){
  int i = 0;
  //Make a left aligned count
  char actualArray[17];
  char* printText = actualArray;
  char count[9];
  itoa(num, count, 10);
  char spaces[16];
  int countLength = strlen(count);

  strcat(printText, initial);
  for(i = strlen(printText); i < (16-countLength); i++)
    strcat(spaces, " ");
  strcat(printText, spaces);
  strcat(printText, count);
  strcat(printText, "\0"); //Do not for to close the string

  return printText;
}

int UpdateScreen(){
  lcd.clear();

//  delay(50); //Debug
  
  lcd.setCursor(0,0); //Start at character 0 on line 0
  lcd.print(text(countText, cCount));

//  delay(50); //Debug

  lcd.setCursor(0,1);
  lcd.print(text(specialText, cRCount));

  return 0;
}

It is unnecessary to share because it is a basic button counter
//this calls UpdateScreen() if the button has been pressed

Then it is unnecessary to find out what is causing your problem.

Have a good night/day wherever you are.

.

Can you clear the LCD and then print a test text of 30 characters?
It will print starting at "home" and should print at BOTH lines.

Ok, spaces is declared to be 16 bytes long, but it needs 17 - one extra for the nul terminator. And there's really no need to use strcat to fill it with spaces - horribly inefficient.

"Interview: " - 11 chars
spaces - 16 chars

So you need 27 chars, plus one for the nul terminator. actualArray is defined to have a length of 17.

Furthermore, printText is a pointer to actualArray. actualArray is an "automatic" variable - it's defined on the stack and it disappears after the function is done. So you are returning a pointer to a chunk of memory that is about to be used by something else.

And furthermore to that, because actualArray is allocated from the stack, it contains garbage. This means that there is no guarrantee that the first byte will be a null terminator. So when you [nobbc]strcat(printText, initial);[/nobbc] , strcat will search through memory until it finds the first zero in memory, and append initial at that point. This could be anywhere and so will likely scribble over the top of something important.

to fix (without doing too much violence to the original code):

char* text(char* initial, int num) {
  //Make a left aligned count
  static char actualArray[28]; // maximum length of the string we are going to need (11+16), plus 1

  char count[7]; // maxint is 16k, so 5 digits, a negative sign, and a null terminator is enough. 
  itoa(num, count, 10);
  int countLength = strlen(count);

  char spaces[17];
  memset(spaces, ' ', 16); // fill with 16 spaces
  spaces[16 - countLength] = '\0'; // terminate at appropriate spot

  strcnpy(actualArray, initial, 11);
  strcat(actualArray, spaces);
  strcat(actualArray, count);

  return actualArray;
}

Cool, Thanks this works. I just need to fix a few errors in the spaces string because it prints the number off the screen, but that is easy to fix.

Hooray, yet another satisfied customer who IMHO has no idea how he fixed it.
See post #4