Text from array will only display on second line of 16x2

I'm hoping someone can point this noob in the right direction.

I've been trying to update a really old sketch that has a module that reads and displays text from an array.

It's all there, but when the code calls for the text to be displayed on two lines, the first line fails.

I'm pretty sure it's in this area:

//================================================================================//
// Grab messages from Stored Array and display for a specified duration //
//================================================================================//
void LCD_Msg(LiquidCrystal_I2C & lcd, int top, int bottom, unsigned long del)
{
  strcpy_P(lcd_line1, (char*)pgm_read_word(&(lcd_msg_table[top])));
  strcpy_P(lcd_line2, (char*)pgm_read_word(&(lcd_msg_table[bottom]))); 

  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print(lcd_line1); 
  lcd.setCursor(0,1);
  lcd.print(lcd_line2);
  delay(del);
}
//================================================================================//

Specifically here:

  strcpy_P(lcd_line1, (char*)pgm_read_word(&(lcd_msg_table[top])));
  strcpy_P(lcd_line2, (char*)pgm_read_word(&(lcd_msg_table[bottom])));

As when I // out the second line of the code, I get all the text I'm looking for on the top line just fine.

Using this format for retrieving the text from the array:

LCD_Msg(lcd, 1, 2, 10000);

Any clear reasoning that this should not work to display both LCD_Msg_1 on the top line and LCD_Msg_2 on the bottom? Currently, only LCD_Msg_2 displays.

Thanks in advance!

I'm pretty sure there is a wrong memory reading in these lines.

A wild guess: you call LCD_Msg(lcd, 1, 2, 10000) which means you call lcd_msg_table[1] and lcd_msg_table[2] - should it not be 0 and 1?

Cannot say without the rest of the code though, in particular how lcd_message_table and lcd_line1&2 are declared.

Try to add a Serial.begin(9600) in your setup (if there isn't already one), and then print on the Serial the value of lcd_line1 and lcd_line2.

ToneArt:
I'm pretty sure there is a wrong memory reading in these lines.

A wild guess: you call LCD_Msg(lcd, 1, 2, 10000) which means you call lcd_msg_table[1] and lcd_msg_table[2] - should it not be 0 and 1?

Cannot say without the rest of the code though, in particular how lcd_message_table and lcd_line1&2 are declared.

Try to add a Serial.begin(9600) in your setup (if there isn't already one), and then print on the Serial the value of lcd_line1 and lcd_line2.

Thank you, Still no change but at least now, I can see in the serial monitor that the data is correct, it's just not reaching (0,0) on the display.

It's almost as if the top line (0,0) is being erased when the bottom line (0,1) is displayed.

Pardon my ignorance, I'm extremely new to this.

All used to work fine on a previous IDE version. My problem began (I think?) when I updated from const char from

//was - prog_char lcd_msg_1[] PROGMEM =  "      txt line 1";

to

 const char lcd_msg_1[] PROGMEM =  "      txt line 1";

to write the strings and and switched from

// was PROGMEM const char *lcd_msg_table[] =

to

PGM_P const lcd_msg_table[] PROGMEM =

to populate the table

All from GoogleFoo - struggled but managed to get it to compile and except for the lack of the top line in the display, the sketch works.

I wish I could post the whole sketch here but I do not (yet) have permission to do so from the author.

I can see in the serial monitor that the data is correct, it's just not reaching (0,0) on the display.
It's almost as if the top line (0,0) is being erased when the bottom line (0,1) is displayed.

What lcd display are you using? How many rows and columns? What lcd library are you using?

cattledog:
What lcd display are you using? How many rows and columns? What lcd library are you using?

LiquidCrystal_I2C (not certain which library), with a generic 1602 LCD with the I2C onboard.

JANSANE 16x2 1602 LCD Arduino Display Screen Blue + IIC I2C Module Interface Adapter

I like the direction you are going with this... Think it may be the library?

Is the display declared as a 16x2?

Can you show the code with the cursor management? There should be some .setCursor() statements before the .print() statements.

LiquidCrystal_I2C (not certain which library),

Can you show the display library # include and lcd instantiation. It should be something like this.

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);  // set the LCD address to 0x27 for a 16 chars and 2 line display

cattledog:
Is the display declared as a 16x2?

Can you show the code with the cursor management? There should be some .setCursor() statements before the .print() statements.

Can you show the display library # include and lcd instantiation. It should be something like this.

#include <Wire.h> 

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);  // set the LCD address to 0x27 for a 16 chars and 2 line display

I just stripped out all of the extraneous code, focusing only on the LCD and array:

//===============================================================================//

#include <SoftwareSerial.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <EEPROM.h>
// "Un"comment the following line to see serial monitor message DEBUGGING output
//#define SERIAL_MONITOR_ON
// For storing TXT strings to Flash Memory
#define __PROG_TYPES_COMPAT__  
#include <avr/pgmspace.h>
//================================================================================//

//================================================================================//
// define Global Variables //
//================================================================================//

//================================================================================//

//================================================================================//
// Define LCD MSG strings Load into String Array and Store in PERM memory
//================================================================================//
const char lcd_msg_0[] PROGMEM =  "Begin line Zero ";  
const char lcd_msg_1[] PROGMEM =  " Welcome to the ";
const char lcd_msg_2[] PROGMEM =  "  Beta Test of  ";
const char lcd_msg_3[] PROGMEM =  " -------------- ";
const char lcd_msg_4[] PROGMEM =  "text for line 4 ";
const char lcd_msg_5[] PROGMEM =  "text for line 5 ";
const char lcd_msg_6[] PROGMEM =  "text for line 6 ";
const char lcd_msg_7[] PROGMEM =  "text for line 7 ";
const char lcd_msg_8[] PROGMEM =  "text for line 8 ";
const char lcd_msg_9[] PROGMEM =  "It goes on & on ";

// Fill up lcd_msg table with lcd_msg TXT defined above

PGM_P const lcd_msg_table[] PROGMEM = 
{
  lcd_msg_0, lcd_msg_1, lcd_msg_2, lcd_msg_3, lcd_msg_4, lcd_msg_5, lcd_msg_6, lcd_msg_7, lcd_msg_8, lcd_msg_9,
};

// LCD Max String size is 16 characters
char lcd_line1[16]; 
char lcd_line2[16];


//================================================================================//
// Initialize functions //
//================================================================================//

void EEPROM_Read(float *num, int MemPos);
void EEPROM_Write(float *num, int MemPos);

void LCD_Msg(LiquidCrystal_I2C &lcd, int top, int bottom, unsigned long del);
void Msg(LiquidCrystal_I2C &lcd, const char *top, const char *bottom, unsigned long del); 

//================================================================================//
// Assign Arduino pins to each LED lights GPS and Pizo      //
//================================================================================//
LiquidCrystal_I2C lcd(0x27, 16, 2);


//  Uhoh.. Should I add something here to define more related to the 16x2 ????

//================================================================================//
// Setup and Initialization                   //
//================================================================================//
void setup()
{
  // establish communication with 16x2 LCD //
  lcd.init();
  lcd.begin (16, 2);
  lcd.backlight();
  
} // END Setup()

//================================================================================//
// END Setup and Initialization //
//================================================================================//


//================================================================================//
// BEGIN MAIN LOOP //
//================================================================================//
void loop(void)
{
  
//   "Begin line Zero " , "It goes on & on ", delay 1500 SHOULD display " Begin line Zero on first line
//   and "It goes on & on" on second line. This only displays the second line.

  LCD_Msg(lcd, 0, 9, 1500);

 
}
//================================================================================//
// END MAIN LOOP                                                                  //
//================================================================================//


//================================================================================//
// Start Script - Opening Greeting                                                  //
//================================================================================//
void Start_Script_Intro(void)
{
    // "Welcome to the " , "  Beta Test of  "
  LCD_Msg(lcd, 1, 2, 2500);
  
  //"------------ ", "text for line 4 "
  LCD_Msg(lcd, 3, 4, 2500);
  // "text for line 5 ", "text for line 6 "
  LCD_Msg(lcd, 5, 6, 2500);
  // Etc...
 
} // END Start_Script_Demo()
//================================================================================//


//================================================================================//
void EEPROM_Write(float *num, int MemPos)
{
  byte ByteArray[4];
  memcpy(ByteArray, num, 4);
  for (int x = 0; x < 4; x++)
  {
    EEPROM.write((MemPos * 4) + x, ByteArray[x]);
  }
}
//================================================================================//

//================================================================================//
void EEPROM_Read(float *num, int MemPos)
{
  byte ByteArray[4];
  for (int x = 0; x < 4; x++)
  {
    ByteArray[x] = EEPROM.read((MemPos * 4) + x);
  }
  memcpy(num, ByteArray, 4);
}
//================================================================================//


//================================================================================//
// Grab messages from Stored Array and display for a specified duration //
//================================================================================//
void LCD_Msg(LiquidCrystal_I2C & lcd, int top, int bottom, unsigned long del)
{
  strcpy_P(lcd_line1, (char*)pgm_read_word(&(lcd_msg_table[top])));
  strcpy_P(lcd_line2, (char*)pgm_read_word(&(lcd_msg_table[bottom]))); 

  lcd.clear();
  lcd.setCursor(0,0); 
  lcd.print(lcd_line1); // if changed to (top) LCD displays message #, not text
  lcd.setCursor(0,1);
  lcd.print(lcd_line2);
  delay(del);
}
//================================================================================//

//================================================================================//
// Display message. Used for Debug. Otherwise replaced w/ LCD_Msg f()
//================================================================================//
void Msg(LiquidCrystal_I2C & lcd, const char * top, const char * bottom, unsigned long del)
{
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(top);
  lcd.setCursor(0, 1);
  lcd.print(bottom);
  delay(del);
}
//================================================================================//


//================================================================================//
//  END  SKETCH                                                  //
//================================================================================//
char lcd_line1[16]; 
char lcd_line2[16];

You have not allocated space for the terminating null character.

david_2018:

char lcd_line1[16]; 

char lcd_line2[16];



You have not allocated space for the terminating null character.

That did it!!!!

Thank you so much!! I was set on the idea that the line should be 16.

Time to wrap it all up.

You don't even need the buffers, print() will work with program memory directly, as long as you cast the char * to __FlashStringHelper *

//================================================================================//
// Grab messages from Stored Array and display for a specified duration //
//================================================================================//
void LCD_Msg(LiquidCrystal_I2C & lcd, int top, int bottom, unsigned long del)
{
  lcd.clear();
  lcd.setCursor(0,0); 
  lcd.print((__FlashStringHelper*)pgm_read_word(&(lcd_msg_table[top])));
  lcd.setCursor(0,1);
  lcd.print((__FlashStringHelper*)pgm_read_word(&(lcd_msg_table[bottom])));
  delay(del);
}

david_2018:
You don't even need the buffers, print() will work with program memory directly, as long as you cast the char * to __FlashStringHelper *

//================================================================================//

// Grab messages from Stored Array and display for a specified duration //
//================================================================================//
void LCD_Msg(LiquidCrystal_I2C & lcd, int top, int bottom, unsigned long del)
{
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print((__FlashStringHelper*)pgm_read_word(&(lcd_msg_table[top])));
  lcd.setCursor(0,1);
  lcd.print((__FlashStringHelper*)pgm_read_word(&(lcd_msg_table[bottom])));
  delay(del);
}

Thank you! I will try that too.