Eliminate garbage characters on LCD displays

I had a problem with 16 x 2 LCD displays using the HD44780 controller occasionally displaying garbage characters. Resetting the MCU board (e.g. UNO) would not fix the problem as the display controller was probably in a permanently crashed state. 16 x 2 LCD displays consume about 20mA and as an ATMEGA328P will supply 20mA at a voltage not less than 4.2v it is possible to power one display from one digital IO pin. It then becomes possible to power down and power up the display under software control and if this is done before writing to the display it will NEVER show garbage characters, unless faulty. I connected IO2 to the display Vcc and used the following code:

#include <Wire.h> // Library file
// Bill Perry's extensible LCD library for HD44780 based LCD displays
#include <hd44780.h> // Library file, main hd44780 header
#include <hd44780ioClass/hd44780_I2Cexp.h>  // Library file, i2c expander i/o class header

/*-----( Declare Constants )-----*/
// LCD geometry
const int LCD_COLS = 16;
const int LCD_ROWS = 2;

// Variables
int Count = 0; //A number to display and increment
int status; // holds returned status after lcd.begin if needed

/*-----( Declare objects )-----*/
//hd44780_I2Cexp lcd;  // declare lcd object: and specify lcd address as below:
 hd44780_I2Cexp lcd(0x27);
// if you don´t know the I2C address of the display, use I2C scanner first (https://playground.arduino.cc/Main/I2cScanner/)

void setup() {

  PowerCycle(); // Power down. delay and power up LCD display to ensure full reset under software control to fix any garbage displayed characters
    
  status = lcd.begin(LCD_COLS, LCD_ROWS);
  delay(10);
  lcd.backlight();   // Turn on backlight of LCD display screen.
//lcd.noBacklight(); // Turn off backlight of LCD display screen.
  lcd.clear(); // Clear display
  delay (10);
  // Commonly used instruction codes
  // lcd.clear();               // Clear LCD display screen
  // lcd.home();                // Go to home position (0,0) - column 1 & row 1
  // lcd.setCursor(col,row);    // Go to position (column, row)
  // lcd.print("text");         // Print text start from specified (column, row)
}
 
void loop() {

  PowerCycle(); // Power down. delay, power up & initialise LCD display to ensure full reset under software control to fix any garbage displayed characters
  
  lcd.setCursor(0, 0);          // Go to position column 0 & row 0
  lcd.print("No crash display");   // Print "Hello, World!"    
  lcd.setCursor(0, 1);          // Go to position column 0 & row 1
  lcd.print("Count ");          // Print "Count "
  lcd.print(Count);             // Print the value of the variable Count
  Count ++;
  delay (1000);
}

void PowerCycle() {
  pinMode(2, OUTPUT); // +5v Vcc to power LCD module
  digitalWrite(2, LOW); // Power down LCD
  delay (100);
  digitalWrite(2, HIGH); // Power up LCD
  delay(10);
  status = lcd.begin(LCD_COLS, LCD_ROWS);
  delay(10);
  lcd.backlight();   // Turn on backlight of LCD display screen.
//lcd.noBacklight(); // Turn off backlight of LCD display screen.
  lcd.clear(); // Clear display
  delay (10);  
}

Before attempting to drive a 16 x 2 LCD from an Arduino pin I did measure the current used and the total for the display including the LCD, HD44780 controller, PCF8574 backpack AND the LED backlight was about 20mA. I assume they use ultrabright LEDs which can work well with less than 10mA and it seems reasonable that the various CMOS chips might use the remaining 10mA. I've attached pictures of the display and current meter that shows this lower current consumption. Voh for an ATMEGA328P is specified as 4.2v minimum at an Ioh of -20mA and the absolute maximum for Ioh is specified as -40mA. So I can not see a problem taking 20mA from an Arduino digital IO pin, since as long as its operating limits are not violated the MCU will not care what it is driving, be it another chips input, an LED or in this case an LCD module.

Instead of powering directly off of a GPIO pin, why not use something like a mosfet or transistor to control the power line to the display? That way you can still reset it if you want to. But I suspect some of those "garbage" characters are being caused by a dip in the power to the display driver.

Also, the chip consumes 20mA but how much does the backlight consume? you are powering both off of a GPIO?

A Power Supply the Arduino is NOT!

3 Likes

Yes that would be a good solution if the display used more than 20mA, but as you can see from my other replies the whole display, including the backlight LEDs consumes less than 20mA. I did try everything to avoid noise first such as massive Vcc capacitors and small ceramic capacitors on the SDA and SCL lines to no effect. The controller crash is intermittent and I suspect it may be caused by a timing violation, perhaps due to bad design/construction on the Oriental UNO and LCD module.

I'm only driving an LCD module that takes no more current than a beefy LED, so the Arduino will not know that is being used as a "power supply".

1 Like

Are you sure the garbage characters are not caused by something in your code?

Hi,

What other device have you got connected to the UNO?

Can you please post a circuit diagram of your project.

Thanks.. Tom.. :smiley: :+1: :coffee: :australia:

1 Like

No other devices connected to the UNO although it would be possible. Circuit is simple the LCD ground goes to UNO ground, SCL from display to A5 on UNO, SDA from display to A4 on UNO and the only variation from a normal I2C connection is that Vcc from the display goes to Digital IO2 on the UNO, although any suitable IO pin could be used if you modify my code listed earlier.

If you see weird characters on an hd44780 driven LCD display, characters you have never even seen on a keyboard, then there has been a synchronisation problem. Data and commands are usually sent to the display driver chip as two half bytes (nibbles) which are joined up later. When these get out of sync, the wrong nibbles are joined together causing this effect. To recover from this, you must re-issue a "init()" or "begin()" method for the library you are using to control the display. It is not enough simply to cut the power to the display momentarily then restore it.


If that is a power supply how have you got it connected, which terminals, and what are its specs?

Thanks.. Tom.. :smiley: :+1: :australia:
PS, I'm off to bed. :sleeping: :sleeping: :sleeping: :sleeping:

The bit you have outlined is just the In Circuit Programmer, known as USBASP, if you are not familiar with this device see USBASP ICSP Programmer Quickstart Guide | Freetronics . When not being used for programming the USBASP just provides 5v from the USB port on the computer, just the same as if using the UNO's micro USB connector - no magic involved. I prefer programming with a programmer rather than using the serial port as it seems to be much more reliable, does not require bootloader firmware to be installed on the target and enables a corrupted bootloader to be re-installed if desired, which can't be done via the serial port.

Yes that's all correct, but the problem I was having could not be resolved using an "init()" or "begin()" method. My idea to power the display from an IO pin enables the power to be removed, and restored, from the display under software control, so can be used in a finished project. PS 807s trump 6V6. :grin:

:slightly_smiling_face:

It works for you, congrats.
Your mistake was posting your (nonstandard) solution where every newbie will think that an output pin is a powersource. Trust me, newbies will try solenoids, filament bulbs, motors, and the list continues.

A resistor, a transistor added will bring your idea into non-critical territory. Accept the criticism, get a tough skin, and enjoy tinkering.

I will admit to on-bench butchering design rules; but, I will never tell what I have done in the privacy of my electronic bench! (Smoked parts have no voice.)

Ray

I am but have you tried powering via the micro USB connection on the UNO. The ICSP port on the UNO may not be wired for more current than needed for programming.
Track widths and bypassing components may be inadequate for powering any peripherals.

Garbage characters can be caused by power supply TO the LCD not being sufficient if the supply to the UNO is not from a purpose built terminal.

Is there a reason you are using the ICSP port to program?

Thanks.. Tom.. :smiley: :+1: :coffee: :australia:
PS, Can't sleep..

The garbage character problem only affected one display, so I think the problem resides there, I just didn't want to throw it away and it was raining! As I said I find ICSP programing more reliable than using the serial port.

OK,
I am very interested in this.
I'd like to work with you to determine the actual issue.
(in order to truly fix something you have to first fully understand the issue)
I have seen this garbage character / nibble sync issue come up a few times before but in the cases were it wasn't quickly resolved, each time I have tried to work with the person reporting it to really track it down, I've not been able to reproduce it and they tend to give up so quickly and move on that I can never resolve what the issue really was/is to determine if there is an actual s/w issue in the library.

In nearly all the cases I've seen so far the issue has been tracked down to be a power supply issue and/or a noise issue on the I2C signals.
And if/how it shows up can be part dependent.
There was one case where it was a hd44780 library issue. In that case, LiquidCrystal_I2C was working and hd44780_I2Cexp was not.
That turned out to be a timing issue that was only triggered by a specific PCF8574 chip - the person with the issue was nice enough to send me the device so I could track down the issue.

Power supply issues are quite common. Many cheap USB adapters have issues. And some PCs have noisy power from USB port.
Also, I've seen cases where low cost USB cables cause power issues as well as data communication issues.
The ESP8266 boards seem to be especially sensitive to this.

It appears what you are showing is a setup that "works".
i.e. a setup that is doing a kludge work around for some sort of issue.

What I would like to see is the setup that fails and to have a way to reproduce the failure to see what is the actual cause.

Can you create a setup that repeatedly fails?
So I can recreate the issue to see what is causing it.

The initialization code for the hd44780 chipset should be robust enough to be able to recover no matter what state the chipset is in when it starts.
i.e. chip can initially be in 8 bit mode, 4 bit mode nibble0, 4 bit mode nibble1
It consists of a sequence that will reliably get the chip back into 8 bit mode then once in 8 bit mode it can send the instruction to reliable get the chip into 4 bit mode.
While it is possible that the chip set might lock up or get deaf to new instructions I've ever seen an hd44780 chip actually crash or stop processing instructions.
In all cases I've seen so far, anytime there is garbage on the screen it is due the to the host and the hd44780 chip being out of nibble sync with each other.

The hd44780 chip has no way to reset it other than to power cycle.
A power cycle puts chip back into its default state which is 8 bit mode.
But if the hd44780 initialization code in the library is proper and robust there should never be a situation where resetting the Arduino does not get everything back in sync as the initialization sequence should get the host and the LCD back into nibble sync with each other and back to a known initialization state no matter what state the LCD is in when the sequence starts.

If there is a possibility that this is subtle issue in the hd44780 library code, I'd like to figure it out to fix it.

The hd44780 library returns status on each API call so the sketch code can determine if that API call succeeded.

I did notice that the code is calling begin() and saving the return status but not ever looking at it to see if begin() has failed.
If begin() fails, then communication with the LCD will not work properly.

Another thing that could contribute to something like this is using the USBASP device.
I worked with these devices and their firmware on them for a couple of years.
So I'm quite familiar with the device and its firmware.
I worked with another person and we corrected several issues & bugs in the firmware, updated the code to use the latest v-USB, and added a true auto SCK clock rate detection capability.
One relevant issue/bug in the code for this relates to handling of the ISP signals during initialization. There are brief periods of time when the original code didn't properly ensure that certain pins were never driven when they weren't supposed to be.
This can potentially create momentary shorts with the target.

In your current setup that doesn't look like that issue could be the cause since
you are using digital pin 2 and the ISP pins digital pins 10,11,12, & 13 are not only different but also on a different internal AVR PORT.

That said, as @TomGeorge mentioned there could be power issues with your current setup due to using USB power going through the USBASP board.
You also have a fairly lengthy 10 pin cable that could be picking up some noise or the PC power supplied on the USB port could be glitching every so often based on the MAINs power glitching, etc...

The power consumption you measured is a static measurement.
When the LCD E signal changes state, lots of things switch inside the chipset to create momentary loads.
I have seen cases where this added load causes momentary glitches on the powersupply voltage or creates ground bounce which ends up causing the E signal to not be interpreted properly by the LCD chipset which causes a nibble to be ignored or a phantom nibble to be clocked in - which gets the host and the LCD out of nibble sync.
I have seen that adding additional decoupling caps on the LCD has fixed this issue in the past.
And in others, changing the USB cable resolved the issue as the one with the issue was poor quality and couldn't carry as much current cleanly to the device.

I've also seen cases where the power on the PC USB port is noisy and it causes issues. This can interact with the USB cable as well.
I've seen this quite a bit on ESP8266 boards.

Lots of things to look at but I would like to work with you to try to get to bottom of this issue on the chance that it is a hd44780 library issue.

--- bill

1 Like

Hi,
Can you post some images of how you have soldered the I2C board to the LCD PCB?


Are you using header pins or what to connect the two?

Thanks.. Tom.. :smiley: :+1: :coffee: :australia:

Isn't the photo shown a photo of the device that is "working"?
--- bill

Just the normal method Tom, of adding a "backpack" consisting of a PCF8574A https://www.ti.com/lit/ds/symlink/pcf8574a.pdf which converts a 2 wire I2C bus to an 8 bit parallel bus to drive the parallel interface of the 16 x 2 LCD. The bit manipulation of the parallel bus is done by whatever LCD library you are using.

Yes for two reasons Bill, first it is showing an LCD which never has any problem with garbage characters and second because it it operating with my software that does a power cycle sequence prior to writing to the display. So far I have only found problems using a 16 x 2 OLED display, which is what drove me to invent a solution that would enable me to use it.