LCD missing or corrupt characters

Hello, I've been battling with this problem for a while now and could really use some guidance.
I'm attempting to replace a REALLY OLD dot matrix display with a 7.0" inch 800x480 display from Adafruit that runs with an RA8875 driver board. I'm using an Arduino Mega.
The data displayed on the old screen is sent to it via one Serial line at 9600 baud. I have NO WAY of modifying that data coming in. All i can do is read the data and attempt to replicate it on my screen.
Theres a few special characters and commands that i've outlined in the code in my comments.
There's also a keypad to navigate the screen but that works indepndantly from the screen.

My program mostly works majority of the screens display perfectly but some screens miss some characters or leave characters from previous screens that were supposed to be overwritten with spaces but for some reason the spaces are written on the wrong lines. I'm almost certain the problem is with the LINE/COLUMN command and my use of "while (!Serial3.available())"
but i cant figure it out. Can anyone see anything wrong with this?




#include <SPI.h>
#include "Adafruit_GFX.h"
#include "Adafruit_RA8875.h"


#define RA8875_INT 44
#define RA8875_CS 46
#define RA8875_RESET 48
#define Busy 27 //Signal that must be toggled to keep screen from sleeping(cant wake it up)


Adafruit_RA8875 tft = Adafruit_RA8875(RA8875_CS, RA8875_RESET);

unsigned long startMillis; //timer for toggling busy
char SData; //Serial Data to be displayed
int CURRENTLINE = 0; //splitting my  800x480 LCD into 8 lines and 32 columns to match old screen
int CURRENTCOLUMN = 0;
int LINESTART[8] = {10, 60, 120, 180, 240, 300, 360, 420};
int COL[32];
int z = 0; //variable to fill my Column array
void setup()
{
  Serial3.begin(9600);      //Display data

  /* Initialize the display using 'RA8875_480x80', 'RA8875_480x128', 'RA8875_480x272' or 'RA8875_800x480' */
  if (!tft.begin(RA8875_800x480)) {
    while (1);
  }

  tft.displayOn(true);
  tft.GPIOX(true);      // Enable TFT - display enable tied to GPIOX
  tft.PWM1config(true, RA8875_PWM_CLK_DIV1024); // PWM output for backlight
  tft.PWM1out(255);
  tft.fillScreen(RA8875_BLACK);

  /* Switch to text mode */
  tft.textMode();

  memset(COL, 0, sizeof(COL)); //filling column array
  for (int i = 0; i < 32; i++)
  {
    COL[i] = z;
    z += 25;
  }
  pinMode(Busy, OUTPUT);
  digitalWrite(Busy, HIGH);
  startMillis = millis();
}

void loop()
{
  if (Serial3.available() > 0)
  {
    SData = Serial3.read();

    switch (SData)
    {
      case 0x13: //Command to move cursor to a new line
        {
          while (!Serial3.available()) {}
          CURRENTLINE = Serial3.read();   // second byte is the line
          break;
        }
      case 0x11: //0x13 is always followed by 0x11 for column
        {

          while (!Serial3.available()) {}

          CURRENTCOLUMN = Serial3.read();   // second byte is the column
          tft.textSetCursor( COL[CURRENTCOLUMN], LINESTART[CURRENTLINE]); //set the cursor to the specified Line/Column
          break;
        }
      case 0x87: //Special case to old Screen, useless now. Sends 2 bytes after 0x87
        {
          while (!Serial3.available()) {}
          Serial3.read();   // second byte


          while (!Serial3.available()) {}
          Serial3.read();   // third byte
          break;
        }
      case 0xC: //Refresh screen command
        {

          tft.fillScreen(RA8875_BLACK);
          tft.textColor(0xFBC0, RA8875_BLACK); //reset text color and size
          tft.textEnlarge(2);
          break;
        }

      default:
        {
          if (SData == 0xFE) // Special character unsupported by my LCD so i convert it to ":"
          {
            tft.textWrite(":");
            CURRENTCOLUMN = CURRENTCOLUMN + 1; //Increment Cursor
            tft.textSetCursor( COL[CURRENTCOLUMN], LINESTART[CURRENTLINE]);
            break;
          }

          tft.textColor(0xFBC0, RA8875_BLACK);
          tft.textEnlarge(2);
          tft.textWrite(&SData, 1); //Print Character to LCD

          CURRENTCOLUMN = CURRENTCOLUMN + 1;//Increment Cursor
          tft.textSetCursor( COL[CURRENTCOLUMN], LINESTART[CURRENTLINE]);
          break;
        }
    }
  }
  else if (millis() - startMillis >= 400)//toggle Busy every 400 ms
  {
    digitalWrite(Busy, LOW);
    delayMicroseconds(5); //made delay as small as possible to avoid missing serial data
    digitalWrite(Busy, HIGH);
    startMillis = millis();
  }
}


Sorry for the long post

Is the symptom consistent, or is it different characters in different location each time ?

If it works ‘sort of’, I’d start by looking at any internal delays within the LCD driver code.

Writing drivers, the developers often aim for the best performance on ‘their’ display, but another brand or model might be 20% ‘slower’, and those delays can make all the difference.

Alternately, because those timings are quite tight, there could be something else (wiring, voltages etc) that reveals the issue.

It's pretty consistent on this one screen. Even though if i refresh the screen it eventually gets it right. I've noticed on the screens that are more densely populated with characters is where it's more likely to mess something up but not always.

Why did you start a second topic on exactly the same problem ?

The other topic has been deleted

I figured out some new information that explains the problem better and i figured no one looked at this and its now buried. I'm sorry should i have just edited this post?

You should have added a new post to the topic if you had more information

I'm not sure what you mean? the posts were not identical. I changed some of the code and description of the problem

If it works eventually then you have a nasty bug to track down. Likely in the library as suggested in reply #2.

Do you see anything useful from google?

I did not say that they were identical, rather that they were on the same subject. Posting twice on the same subject, even if you provide more details in the later post, wastes the time of people offering help

1 Like

From what i can tell the issue might be caused by the Serial buffer limit of 64 bytes. I need to implement some sort of buffer to prevent blocking as suggested here
http://www.gammon.com.au/serial
problem is i have no termination marker nor do i know the length of the data. its just a stream of ascii with a few special commands.

The 9600 baud rate is slow, so without lots of delays, I would not expect it to have buffer overflow.

Setting color for every character seems excessive, can you make a bit smarter?

What's the busy line for?

The busy line is a remnant of the old screen im replacing. If i dont toggle the busy line the board that is sending me the ascii data will sleep and i will have no way of waking it up.
you're right I'll fix the color setting