40 x 2 character LCD not showing last 17 characters

I'm having an issue getting a full screen of text on a 40 x 2 character lcd,

I've tried both the standard way to connect the lcd to the arduino in 4 bit mode (parallel?) and an I2C lcd backpack, as well as different 40 x 2 LCD's,
And i've tried it with 3 different uno's a leonardo and a mega 1280 and a mega 2560 and i get the same issue,
which is that the last 17 characters will not show on the lcd.

It does this with the SerialDisplay sketch in the examples folder, and the I2C version of that, i ensure i am sending either 80 or more characters.
And it does the same with a sketch that reads the text data on the serial port that's coming from a game, that sends out CSV's of variable length, and it quite often outputs the full 80 characters.
But when ever it's sent more than 63 characters, it refuses to show past the 63rd character.

BUT, if i run a sketch that sends 80 consecutive characters to the lcd... then it will display them all, using the exact same lcd, same port, same speed (115200) and so on.

This is the sketch that tests the lcd:

#include <LiquidCrystal.h>

//LiquidCrystal lcd(rs,en,d4,d5,d6,d7);
  LiquidCrystal lcd(12, 11, 5, 4, 3, 2);       // put your pin numbers here

void setup()
  {
    lcd.begin(40, 2);                          // put your LCD parameters here
    for (char i=47; i<127; i++)                // send 80 consecutive displayable characters to the LCD
      {
        lcd.print(i);
        delay(100);                            // this delay allows you to observe the addressing sequence
      }
  }


void loop()
  {  
  }

From where did you source the LCD and what is the controller IC?

Simple. Nothing is wrong with the display.
The issue is caused by a buffer overrun.
You are overflowing the serial RX buffer.

The HardwareSerial RX buffer is only 64 characters.
Here is loop() portion of the SerialDisplay sketch that comes with the LiquidCrystal library:

void loop() {
  // when characters arrive over the serial port...
  if (Serial.available()) {
    // wait a bit for the entire message to arrive
    delay(100);
    // clear the screen
    lcd.clear();
    // read all the available characters
    while (Serial.available() > 0) {
      // display each character to the LCD
      lcd.write(Serial.read());
    }
  }
}

Note that it does a 100ms delay waiting for an "entire message" before printing anything.
Since the serial buffer is only 64 characters, you can overrun the HardwareSerial RX buffer if you send more than 64 characters in 100ms which you will even at 9600 baud.

A few weeks ago, somebody reported a the same issue for my hd44780 library.
I updated the Serial2LCD examples that come with the hd44780 library, to be smarter and overlap the receiving of the characters and the printing to the LCD. So while it can still have an overflow issue if you crank up the baud rate, especially on a slower interface like i2c, it will not have the issue you are currently seeing.

Unfortunately, since I haven't done another release of the hd44780 library since this update, it isn't yet available, but it will be available in the next release of the hd44780 library.

--- bill

Thankyou very much for the explanation, makes sense,

i had tried changing the delay thinking it was that, as i was wondering if the data was coming in too fast, the program that sends the data runs at 115200 and that speed can't be changed,

Only thing that can be changed is the update time, it's currently on 500ms.

RE: where i got the LCD's and their controllers,
2 of them off ebay, 1 off amazon, and 1 was in the bus ticket machine i bought so is at least 20 years old,

They all have the hitachi 44780 controllers on them (either reading the chip or in the specs)
the ebay ones have 3 chip on board blobs, and unbranded it seems,
The amazon one is a vishay one, that has 4 chip on board blobs,
And the one from the ticket machine has 4 large surface mount chips, and some smaller ones.

The rate of the LCD update is mostly based on the s/w not the h/w.
The reason I say mostly is that update speed is based on two things:

  • How fast the s/w can get the byte to the interface h/w
  • the speed of the interface h/w

The maximum speed that a hd44780 LCD can process bytes is 1 byte every 1us using direct pin control.
That is when using 8 data pins in 8 bit mode.
In 4 pin mode, it is just a bit less than half that.

The speed of the LCD is not the issue.

If you are using a PCF8574 based backpack, the rate at which you can send bytes to the LCD is dramatically slowed down since you have to transfer multiple bytes over the i2c bus to get a single byte to the LCD and the i2c bus is normally only running at 100Khz. So you can see that even if the s/w overhead was zero, there is no way to send bytes to the LCD over i2c using an i2c backpack and keep up with a 115200 baud connection.
Depending on the serial RX buffer size and the size of LCD message, you can overrun the buffer even if writing the LCD while receiving serial data.

here are some timings using a 16Mhz AVR. The specific processor doesn't matter.

When using a PCF8574 based backpack.
The hd44780 library can transfer a byte to the LCD in about 500us.
All the other libraries will take over 1ms per byte.
If you bump the SCLK of the bus to 400 kHz (which is beyond spec for the PCF8574)
The hd44780 library can transfer a byte to the LCD in about 200us

For direct pin control of the LCD using 4 pin mode.
The hd44780 library can transfer a byte to the LCD in 91us
The latest LiquidCrystal library can transfer a byte to the LCD in 284us

Using these numbers you can do the math to calculate how large your RX buffer needs to for the way you are sending the data, and update speed of the h/w interface based on the library being used.

If you are not already using the hd44780 library and you want faster LCD updates, then you will want to switch to using the hd44780 library.
The hd44780 library can also perform long line wrapping, which can be useful in some use cases.


It isn't' clear exactly what you are wanting to do in terms of updating the display and what form the data is in.

In order push an entire screen to a 40x2 LCD all at once, you are going to have to modify and / or write some code.

If you are periodically slamming all 80 bytes to update the display and the existing SerialDisplay example would have worked if there were no buffering issues, then you may want to modify the HardwareSerial.cpp code down in the Arduino AVR bundled core library to simply increase the buffer to 128 bytes instead of 64 bytes.

If you need something more sophisticated that can do LCD updates while receiving data, you will need to write you own sketch.
There are different ways to handle clearing/repositioning the display between updates.
for example
It can be character based. i.e. look for a or tor some other data value to determine the end of a message

If you are doing frequent updates of the entire LCD, then you likely don't want to clear the LCD between updates as that will cause unnecessary flicker.
You will likely want to detect "message" boundaries based on time.
For example, if the code notices that more than 1/2 or 3/4 of the update time being used by the sender has elapsed without receiving any characters then the code should set the LCD cursor position to 0,0 to get ready for the next update.

You should never write the code to assume no characters will ever get lost or that an extra character will never show up.
i.e. doing something simple like just writing each byte to LCD memory and assume that each update will fill the full DDRAM memory and wrap back to the beginning for the next update.
While that can work, if there is ever a lost character or an extra garbage character ever shows up in the data stream, the system will never recover whereas if it was doing something time based to detect a message boundary, the screen would recover on the next update.

BTW,
If you want to see the code that will be in the next hd44780 library update I have provided links to the i2c and pin control versions
The code is meant for text based messages.
It use and to mark update boundaries and enables line wrapping for long lines.

--- bill

I tried the pin control library you linked, and it works... i get all 40 characters on the lcd.

Brilliant, thankyou for this,