jhd162a 1602 LCD - garbled characters when cursor set to column 0

Hi folks. I'm using an arduino UNO to drive this 16x2 LCD display - apparently well-known to the arduino people, as there is the 'liquidcrystal' library for it.

I'm running a very short and simple arduino sketch program for testing the display, and I'm using the '4-bit' data transfer method.

I've encountered 1 issue so far.

First.... what does work?

Well....I can make the LCD print "Hello LCD!!" on row 0 (ie. the top row). And I can also make it print "Hello LCD!!" on row 1 (ie. the bottom row). But the printing of those characters only work properly if I start printing at column '1' (which is physically the 'second' column).


Photo above: Start of print at column '1' (second-column from left) - no problem.

Now....what does not work?

Garbled characters are displayed if I try to print "Hello LCD!!" with the cursor initially set at column 0 (ie. physically the left-most column). That is, attempts to start the print at the left-most column (column '0') results in the same garbled pattern - regardless of which row I do the printing. The same pattern is displayed even when I reset the arduino. This is the issue I'm trying to sort out at the moment.


Photo above: Start of print at column 0 (left-most column) results in garbled characters.

I'll post my very short and simple code..... below. Can somebody let me know if I'm leaving out crucial steps? I'm getting identical results on two similar LCD modules ordered from different places.

At the moment, I'm just setting the cursor position (to say column 0, row 0), then sending the character string for displaying on the LCD. But getting the corrupted characters unfortunately.

Clearing the LCD using lcd.clear() didn't help either.

Thanks for any help in advance!

#include <SPI.h>
#include <LiquidCrystal.h>

int Contrast=5;
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

String mystring = "";

 void setup() 
{
  Serial.begin(9600);
  Serial.println("serial comms active");
  pinMode(13,OUTPUT);
  analogWrite(6,Contrast);  // pin 6 of UNO producing PWM, connecting to the Vee contrast pin of the LCD, and 'Contrast' is a PWM level.

  // set up the LCD's number of columns and rows: 
  delay(2000);
  
  lcd.begin(16, 2);
  delay(2000);

  // Print a message to the LCD.
  lcd.setCursor(0,1); //column 0, row 1
  delay(2000);
  mystring = String("Hello LCD!!");
  lcd.print(mystring.c_str());
}

void loop() 
{
}

I'm glad that you included the photos because they indicate that you (sometimes) have a timing problem whereby one nibble gets lost and the following characters are sent out-of-sync to the display.

This is evidenced by the two similar, but incorrect, characters appearing where the the two l's in hello belong. I haven't done so yet so but I am sure that if you check out the ASCII codes for the characters that you are seeing, using either Hex or Binary, you will see the pattern.

The problem is most likely a display that is close to the edge (or out of) of it's allowable specifications and the LiquidCrystal library does not handle these well.

It should work properly in the 8-bit mode.

Don

Hi Don! Very very much appreciated. Thanks a lot for your time to have looked at my post and the photos, and for letting me know what the issue is - and also for indicating that 8-bit mode should work. I'm certainly keen to go for the 8-bit mode. I will try that! Thanks again Don.

Hi again Don! It's working perfectly in the 8-bit mode. Absolutely appreciative here. Thanks for your help and time.

Actually, I didn't even know that the liquidcrystal library handled both 4-bit and 8-bit modes, as I was following all the tutorials online that used 4-bit operation. The liquidcrystal library is incredibly flexible, as I have now found out.

One thing had me confused for a little bit though with the online tutorials and example sketch code for 4-bit operation. Most of the online tutorials wired LCD pins D4, D5, D6 and D7 to the arduino pins 5, 4, 3, 2 (in that same order). So the arduino sketch setup function would look like LiquidCrystal lcd(12, 11, 5, 4, 3, 2); - which correctly follows the format: LiquidCrystal(rs, enable, d4, d5, d6, d7) - but a little confusing with the reversed order notation, since d4 is the least significant bit. Probably more convenient to look at if the wiring of LCD pins D4, D5, D6 and D7 were in the arduino pin order 2, 3 ,4, 5...... so give LiquidCrystal(rs, enable, 2, 3, 4, 5)

The 8-bit mode is doing great right now. Stable and no glitches at all after running for 25 mins or so.

Thanks again Don!!

Southpark,
I'd be very curious which version of the IDE you are using and if you are using the IDE supplied LiquidCrystal library or some other replacement library.
There have been some changes to the IDE LiquidCrystal library in the recent IDEs.

Don,
A slow LCD causing a timing issue would seem very odd to me in this case given that it looks like there is tons of extra margin in the IDE LiquidCrytal library code.

The sketch even does a 2 second delay after setting the display memory address and the LiquidCrystal library does 3 writes of En with delays after each nibble.

Here is the sequence it uses to send a nibble:
It sets the RS pin.
It sets the RW pin (if used)
It sets up the data lines. (older libraries also set the pin to OUTPUT mode)
En LOW - 1us delay
en HIGH - 1us delay
en LOW - 100us delay (on each nibble not just on each command/data byte)

Also considering that each digitalWrite() is very slow and takes over 5us that adds even more margin.

I would lean to some other sort of issue. Perhaps signal noise or ground bounce due to not enough decoupling on the power supply.

I'd be curious if the problem is the same when a simple pot is used vs using a PWM pin control the contrast.

--- bill

bperrybap:
Southpark,
I'd be very curious which version of the IDE you are using and if you are using the IDE supplied LiquidCrystal library or some other replacement library.
There have been some changes to the IDE LiquidCrystal library in the recent IDEs.

Hi Bill!! Still reading your post and very kind information right now. I can answer your first question at the moment..... I'm using Arduino Sketch 1.65 and using the liquidcrystal library that comes with it. I downloaded what appeared to be the latest liquidcrystal library, but reverted back to the inbuilt one (with 1.65) after getting the same result. I was even thinking of changing some values in the downloaded library ... like timing parameters to see if it helped, but I didn't get around to it.... I probably wouldn't have got anywhere with just tinkering with values. Thanks Bill. Just reading more of your post now.

bperrybap:
I'd be curious if the problem is the same when a simple pot is used vs using a PWM pin control the contrast.

I was going to focus on that particular feature. And can certainly check this one out for everybody Bill. Thanks for mentioning it. I'm going to see what happens if I don't use the PWM, and will get back to you on this one. Thanks Bill.

Thanks for teaching me the required sequence to send the nibble as well. I'll certainly use that knowledge for driving the LCD using other micro-controllers.

Back again Bill!

Good news Bill ..... what I did was this.... I left the PWM running on arduino pin 6. And unplugged the wire from arduino pin 6 (PWM), where this wire was originally used to connect the PWM signal to the LCD's contrast pin. I then connected that wire to 0V, which basically grounded the LCD's contrast pin (pin 3 of the LCD module).

The same software was applied. All this resolved the issue (thanks to you). It was great

I kept reverting back and forth between the PWM contrast condition and the grounded contrast condition. The PWM is certainly linked to my issue.

Actually, the reason I used PWM was because I didn't have a pot with me at the time. I had two same-sized resistors to form a voltage divider..... so I did have 2.5 V applied at one stage, but was likely an unsuitable contrast voltage level (- couldn't see the text). This turns out to be nice though, since it led to this situation.

My coloured wire that connects my chosen PWM output pin (of the arduino) to the LCD contrast pin is 16 cm in length. I tried another wire of the same kind. Same glitchy issue.

Then I used the same sort of wire, but longer (32 cm length). No more glitch. I then reverted back and forth between the short wire and the longer wire. The issue always occurs for the short wire, and doesn't occur for the longer wire.

With the long wire, the LCD is not glitching. The LCD has been counting time (in seconds) for the last half hour (4-bit mode with PWM contrast applied and the 32 cm wire). I'll grab some potentiometers today and use DC voltage instead.

Thanks very much again Bill and Don. Your help has been tremendous.

Ideally you want to use a RC filter as a D to A converter on the PWM signal as you feed it to the hd44780 Vo input pin.
Very strange about wire length affecting this.

--- bill

bperrybap:
Ideally you want to use a RC filter as a D to A converter on the PWM signal as you feed it to the hd44780 Vo input pin.
Very strange about wire length affecting this.

--- bill

Thanks Bill. I'll definitely try the RC filter on the PWM. I agree! .... the wire length really makes a difference. I used different 16 cm wires between the PWM pin and the contrast pin, and the glitch occurred every single time. And when I used the longer wires..... the glitch never occurred at all. Quite interesting!

The glitch set-up is LCD pins D4, D5, D6, D7 connected to arduino pins 5, 4, 3, 2 in this order (which I followed from an online tutorial, even though my own preference would be to just wire LCD pins D4 to D7 to arduino pins 2 to 5 in this order). And the LCD RW pin is grounded. And RS pin of LCD connected to pin 12 arduino. And the Enable (E) pin of LCD connected to pin 11 of arduino. 5V pin of arduino supplying power to the LCD. Remaining LCD pins connected in the usual way. Also, short wire connecting arduino pin 6 (my chosen pwm pin) to LCD pin 3 (contrast pin). And an electrolytic capacitor between 5V of arduino to 0V of arduino (and also a ceramic decoupling cap in parallel with the electrolytic).

Southpark:
. . .
One thing had me confused for a little bit though with the online tutorials and example sketch code for 4-bit operation. Most of the online tutorials wired LCD pins D4, D5, D6 and D7 to the arduino pins 5, 4, 3, 2 (in that same order). So the arduino sketch setup function would look like LiquidCrystal lcd(12, 11, 5, 4, 3, 2); - which correctly follows the format: LiquidCrystal(rs, enable, d4, d5, d6, d7) - but a little confusing with the reversed order notation, since d4 is the least significant bit. Probably more convenient to look at if the wiring of LCD pins D4, D5, D6 and D7 were in the arduino pin order 2, 3 ,4, 5...... so give LiquidCrystal(rs, enable, 2, 3, 4, 5)

Each of the microprocessor I/O pins has some special function associated with it but the LCD controller does not require any of these functions. Typically you would assign pins with special functions to devices that require those functions and then use the remaining pins for your LCD.

You can use any available I/O pin for any of the six LCD signals. The LiquidCrystal lcd( . . . ) statement is called the 'constructor'. It is the function of the numbers within the argument of the constructor (the string of numbers in parentheses) to tell the Liquid Crystal library which Arduino pin is connected to which LCD pin.

It would all be much clearer if the perpetrators of the library and the authors of the Tutorial had been more liberal with their use of comments:

//LiquidCrystal lcd(RS, E, D4, D5, D6, D7);
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);      // put your pin numbers here

The Arduino documentation cleverly makes it difficult to find information about this topic. It's here --> LiquidCrystal - Arduino Reference

Don

bperrybap:
. . .
Don,
A slow LCD causing a timing issue would seem very odd to me in this case given that it looks like there is tons of extra margin in the IDE LiquidCrytal library code.

This has shown up many times when using the LiquidCrystal library in the 4-bit mode. There's no question that a nibble got lost somewhere, just look at the desired results vs the ones on his display:

Desired

    H      e      l      l      o      space  L      C      D      !     !
    48     65     6C     6C     6F     20     4C     43     44     21    21

His (I can't identify some of these characters but they are on the HD44780 data sheet)

omega   blank  V     ??     ??     theta   ??     ??     4      B     blank blank
F4      86     56    C6     C6     F2      04     C4     34     42    12    1?

When John Raines wrote his LiquidCrystal440 program for 40x4 displays he paid attention to making it work with several of these questionable displays and some with this problem have had success in using his program where the standard library has failed.

Don

Southpark:
. . .
Thanks for teaching me the required sequence to send the nibble as well. I'll certainly use that knowledge for driving the LCD using other micro-controllers.

You might want to follow the LCD Programming Examples link at http://web.alfredstate.edu/weimandn for some complete programs. These examples were all originally written for other microcontrollers including the 8085, 68HC11, and various PICs. It is relatively straightforward to rewrite them, just use the comments as a guide as you substitute the code one step at a time. If you study these programs you will find that the comments are identical for the Assembly, C, and Arduinoeese versions.

Don

Hi Don,

I just went to that link you provided in the previous post. Really excellent information at that site. Thanks for showing me this site, and for letting me know a good way to make use of their code and procedures. Genuinely appreciated.

Kenny

floresta:
This has shown up many times when using the LiquidCrystal library in the 4-bit mode. There's no question that a nibble got lost somewhere,

I know there are some displays that run a bit slower and can potentially have trouble with the 4 bit initialization.
This case seems odd though especially since the same code with a different display address worked and the failure also varied depending on the length of the PWM wire and went away when PWM contrast control was not used.

From looking at the data, it does look like the display did enter 4 bit mode but it kind of looks like an extra nibble of 0xf got sent to the display rather than a nibble got dropped.

The last thing sent to the display before the 'H' of the "Hello" is a command to set the display ram address in setCursor()
which does:

command(LCD_SETDDRAMADDR | (col + _row_offsets[row]));

In this case for column 0 row 1 it will be sending 0x80 + 0x40 or 0xc0
Not sure where the 0xf nibble could come from as it isn't the lower nibble of that byte.
That is what leads me to think that it might be an inserted nibble from a false E clock rather than a lost nibble or out of nibble sync.

The '440' code actually strobes E for the nibbles a bit quicker than the stock IDE library.
The only real differences are that during the initialization in begin(), 440 code waits an extra 10ms before starting and waits 5ms vs 4.5ms for the initial 'goto to 4bit mode' command. (which could be anything if the display is out of nibble sync)
And during the nibble clocking to the display the IDE code waits an extra 100us between nibbles vs just after the 2nd nibble.

But the display does appear to have entered 4 bit mode so it isn't clear that added delay in the 440 begin() code mattered.

This is an odd case in that it doesn't seem obvious to me that it is timing issue or related to dropping a nibble.
A logic analyser picture of the signals could help solve the mystery.

--- bill

Hi Don and Bill! Paul__B (a forum member) told me in private messaging that the LCD pin 3 (contrast pin) has some details about it lacking (in the official documentation).

It turns out that this pin 3 (labelled as Vee or Vo) by itself (with nothing connected to it externally) can be "considered" to have an internally-connected 11 kilo-Ohm pull-up resistor. It gets pulled up to 5 Volt DC. And it can be considered that the input impedance to pin 3 (beyond the pull-up section) is relatively large. Open circuit voltage and short circuit current measurements will easily confirm this.

LCD pin3.jpg

The contrast will depend on the voltage at pin 3. So adding a variable resistance (of say variable 5K or variable 10K) between pin 3 and ground will form a voltage divider between that 'pullup resistor' and the variable resistance.

The usual voltage needed for good contrast is quite low.... eg 0.84 Volt, 1 Volt etc. Even zero volt could work nicely!

Anyway, it turns out that PWM wasn't the greatest idea...... due to the internal circuit configuration.

I'm just going to stop using PWM, and will instead use a 5K variable resistance between pin 3 and ground (no external voltage required at all).

I can't blame the tutorial guys for trying (the pwm), since the official documents don't seem to explain or show how pin 3 actually works.

You can use PWM to control the LCD contrast but you should add an RC circuit to filter it into a voltage vs feeding the raw PWM signal directly to the Vo input.

bperrybap:
You can use PWM to control the LCD contrast but you should add an RC circuit to filter it into a voltage vs feeding the raw PWM signal directly to the Vo input.

Absolutely agree with you Bill. That would be highly recommended. In this case, we'd have the internal 5V supply going to an 11K resistor, and the other side of this resistor will be our applied filtered (hopefully close to DC, or ideally DC) contrast control voltage.

Hi Don and Bill! Paul__B (a forum member) told me in private messaging that the LCD pin 3 (contrast pin) has some details about it lacking (in the official documentation).

I assumine that the 'official documentation' in question is the HD44780U data sheet. The reason that details about the pin 3 circuitry are lacking is that this documentation is for the controller itself, not the pc board on which the controller is mounted and where the circuitry in question is located.

In my version of the documentation the only relevant information that I have found is shown in Figure 21 'Drive Voltage Supply Example'. This diagram shows the connections for an 'extended temperature device' which may require a negative voltage at V5 (which is where pin 3 connects) and there are no component values indicated.

It appears that, so far at least - and it's been several decades, all of the display manufacturers have adopted this recommended circuitry with resistor values (R) of varying values*. For some reason (Paul has some theories about this) their limited documentation usually shows a potentiometer (voltage divider) connected to pin 3 instead of the rheostat (variable resistor). The lower side of either can go to GND if a normal rather than an extended temperature device is used.

Don

  • EDIT: On my devices all of the voltage divider resistors are the same value on any given board but they vary in value from one style board to another.

Thanks a lot Don. Excellent information and comments you posted. It's all making sense to me, thanks to you guys.

The larger the voltage span (Vlcd), the more prominent the LCD graphics characters become (assuming suitable resistors in that ladder are used). And Vlcd can be controlled by a variable resistor (connected between V5 and some other point (let's say X).... in this case a negative voltage -5V as was shown in the official documentation for HD44780U). In the LCD module, V5 is connected to Vo (or Vee, aka pin 3 of the LCD). If point X is ground, which is used in all these tutorials etc, then the maximum achievable Vlcd value is 5V. Adding a variable resistor between pin 3 to ground allows Vlcd to be adjusted. Setting that variable resistor to give a zero resistance between pin 3 and ground gives the maximum 5V span for Vlcd, which would give very visible LCD features (dots/matrix etc). Increasing the resistance makes the display less and less visible, since that is reducing the voltage span Vlcd. I'm just saying Vlcd .... but yep.... the voltage differences between those internal points V1, V2 etc are important.