Getting a 16×2 LCD screen to work and developing a LCD Contrast Tester

A while ago, thanks to the joys of eBay and manufacturing in China, I ordered some low-cost 16×2 LCD character screens, and they finally arrived.  Yeah, now I can get down to trying to output some text to the LCD screen, just one of the pieces of the puzzle for creating a metro ‘next train’ monitor.

The LCD screens have arrived!!

The LCD screens have arrived!!

For the first step, I just wanted to see if I could get it to work, so I started with the Hello World tutorial.  I wired it up using a breadboard, and put in a header that I had into the breadboard, and then set the LCD screen on top, unsoldered.

However, nothing.

At first, I thought it was that I did not have a 10k pot to start with, as some on the forums indicated that you need a minimum resistance, but this did not make sense to me, as really it is just acting as a voltage divider and the actual resistance amount should not matter.  However, I did eventually find a 10k pot and used that, but it was unnecessary: once I got it working I replaced the 10k pot with the 1k pot I had at first and it works just fine.  The pot resistance does not matter.

Second, the tutorial also did not have the backlight lit, which was a mistake.  My LCD was extremely difficult to read without the backlight, so I wired up the backlight by connecting the last two pins to +5v and ground respectively.  While the wiring was done correctly (I check multiple times), the LCD would just output square boxes on the top line.

Despite the wiring being correct and code being correct, just giving me boxes, at all contrast levels.

Despite the wiring being correct and code being correct, just giving me boxes, at all contrast levels.

So I went into investigative mode, first pulling out the multimeter to check the voltages (too clumsy as I needed two hands and had to hold wires to the multimeter leads), and instead used the analog in of the Arduino to read the voltage (1023 = 5v, and 0 = ground).  After several checks I found the problem:  the RW pin was not being successfully pulled to ground.  While on the breadboard it was at 0v, and on the header pin sticking up it was at 0v, when I touched to the plated part of the LCD pin ins, I was getting 5v.  No idea how, and why it was at 5v exactly and not a floating voltage is beyond me.  Either way, obviously not good and despite my attempts to move it around and to hold a wire to it to ground, did not get a change.  I was not sure if the LCD screen had been fried (again, forums had indicated this possibility if you used less than a 10k pot).

Solution was to solder it. As soon as I had done that (thanks to learning how to solder earlier), the LCD display made that first output:  Hello World!, along with the number of seconds since it started.

After soldering, the LCD displays successfully.

After soldering, the LCD displays successfully.

To get this to display properly, I needed to adjust the contrast:  too much to 0v and you get the boxes developing (you can still read the text, but the boxes are there and make it difficult), while too much to 5v and the display gets washed out completely.

I wanted to experiment, and instead of controlling via a pot, I wanted to control the contrast by a PWM pin.  This is also part of my objective in a future project.  So I build a display contrast tester, that automatically steps through the different PWM outputs from one of the Arduino PWM pins, changing the contrast based on that output and writing it to the LCD screen and to the serial monitor.  Thus the LCD Contrast Tester was created.

Testing the contrast of the LCD by changing the PWM output.

Testing the contrast of the LCD by changing the PWM output.

And see the LCD Contrast Tester in action.  You can see about 120 is the best contrast for this LCD, which approximately half (128 would be 50% of the way).

Mission accomplished:  the LCD is working!

However, one thing that happens is that after a random amount of time, the LCD screen screws up:  it starts scrolling random text, or instead of putting the numbers for the PWM in the right spot, starts changing things elsewhere.

Random characters and errors display on the LCD after varying time running the program.

Random characters and errors display on the LCD after varying time running the program.

The next step is to figure out why the random characters and errors occur!

And code for the LCD Contrast Tester.  Note that in this code I also added in digital control of the backlight pin, so that it goes through the first cycle with no backlight, then turns it on for the second cycle, off for the third, etc.  To avoid using this, just put the backlight positive from the LCD (second last pin in the LCD) to +5V, as opposed to digital pin 7.


LCD Contrast Tester

Demonstrates the use of a PWM pin to change the contrast of
a 16×2 LCD display.

Uses the LiquidCrystal library the works with all LCD displays
that are compatible with the Hitachi HD44780 driver. These
typically have a 16-pin interface.

The circuit:
* LCD RS pin to digital pin 12
* LCD Enable pin to digital pin 11
* LCD D4 pin to digital pin 5
* LCD D5 pin to digital pin 4
* LCD D6 pin to digital pin 3
* LCD D7 pin to digital pin 2
* LCD R/W pin to ground
* LCD VSS pin to ground
* LCD VCC pin to 5V
* LCD V0 pin to digital pin 10
* LCD backlight + (marked A on mine) to digital pin 7

// include the library code:
#include <LiquidCrystal.h>

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

// Initialize the PWM pin and output for the contrast adjustment
int V0Pin = 10;
int V0 = 0;
int increment = 0;

// initialize the backlight control
int backlightPin = 7;
int backlight = LOW;

void setup() {
// set up the LCD’s number of columns and rows:
lcd.begin(16, 2);

//set up V0 control pin, backlight control pin and communications
pinMode(V0Pin, OUTPUT);
pinMode(backlightPin, OUTPUT);

//turn on the backlight to start
digitalWrite(backlightPin, backlight);

// Print a message to the LCD.
lcd.print(“testing contrast”);
lcd.setCursor(0, 1);
lcd.print(“V0 PWM: “);
lcd.setCursor(12, 1);
lcd.print(“/255 “);
lcd.setCursor(8, 1);

analogWrite(V0Pin, 128);


void loop() {
//set the contrast
analogWrite(V0Pin, V0);

//clear seconds area on LCD. If don’t the
//transition from 3 numbers to 2 numbers makes
//for odd outputs.
lcd.setCursor(8, 1);
lcd.print(” “);

// print the number of seconds since reset:
lcd.setCursor(8, 1);
Serial.print(“V0 is “);

//increment V0
if (V0 == 255) {
//if at bottom, reverse and go down
increment = -1;
if (V0 == 0) {
//if at bottom, reverse and go up
increment = 1;

//if at zero, flip the backlight setting
backlight = !backlight;
digitalWrite(backlightPin, backlight);
//if V0 not equal to either of these, the increment
//and backlight stay at what it was earlier

V0 = V0 + increment;
Serial.print(” Increment is “);
Serial.print(” Backlight is “);



The random characters are appearing because of the use of the PWM to control the contrast on V0. Apparently, this causes some issue because of the nature of the PWM signal.

This forum post helped:

I put the V0 back to the pot output, reset the board, and it ran for an hour without an error or random character appearing. Then I put it to the PWM output and within 2 seconds the error had appeared. Going back to the pot output does not fix it: once the error is there, it is there!

The forum thread seemed to indicate that the PWM needed to be cleaned, so this could be something to evaluated in the future as ideally I would like to control the contrast from the board, not a physical pot.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s