I2C 20x4 LCD not working on Mega

Hello everybody,

I recently got myself I2C 20x4 white on blue LCD as shown in the pictures. I am running Arduino 1.0.2 with an Arduino Mega R3 but I am unable to get this thing to display anything. I installed the New LCD Library (from Fmalpartida on Bitbucket Liquidcrystal V1.21) and use the 'Hello World' sample but all I see is randomly a block light up. The backlight is on and the address is 0x20 according to the scan-tool. I tried several other libraries but all without luck so far.

Is there anybody that has some insight on how to get this display to work, any help would be much appreciated. Attached are some pictures showing the back-side of the LCD with the I2C board and my simple Mega connections.

Please let me know if there is anything else you need from my side to diagnose this problem.

Thanks a lot in advance!


The reason that these various i2c libraries are not working is that the library has to map output bits
on the PCF8574 to LCD functions. How that mapping needs to be done depends on the wiring on the PCB
between the PCF8574 and the other components.
Not all i2c lcd boards are wired the same. If the mapping being performed in the library is incorrect,
then it simply won't work.
The actual code works fine, but since the code is talking to the lcd on the wrong pins, nothing works.
Most libraries do not allow configuring this mapping since the mapping is hard coded.

fm's library allows you configure this mapping so
fm's library will work with that module as long as your correctly fill in the constructor
to match the wiring for that board.

The issue is that the constructor defines how the PCF874 is wired up to the hd44780 module.
If you use the examples that come with the library, it is unlikely to work since the examples
do not specify the bit/pin mappings. When the bit/pin mappings are not specified
the library will use a set of defaults that are for fm's EXTRAIO i2c board.
The board you have more than likely does not use the same wiring so you must fill in the full constructor
to tell the library how the PCF8574 chip is wired up to the LCD module.
In order to do that you need to know how the PCF8574 is wired up to the hd44780 module.
(what output bit is attached to each lcd function)

See fm's thread for more details on this at my post #116.

A schematic would be most helpful as this information would then be clear.

From your photo I see that you have a 2TY transistor which is a PNP transistor so
the backlight polarity would be NEGATIVE.

The connections for all the output bits are not visible in the photo because
some of the traces are on the other side of the PCB.
Here is what can see:
8574 LCD

P0 D4
P1 D5
P2 D6
P3 D7
P4 ???? (can't see in photo)
P5 ???? (can't see in photo)
P6 ???? (can't see in photo)
P7 Backlight Transistor
The backlight is on P7

The signals that can't bee seen are RW, RS/DI and E

Fms' board uses:

I assume you used the default constructor that does not specify all the bits.
If so then you can eliminate fm's 3 bit mappings above since they are not working
for your board.

The best thing would be to have a schematic so you could look at the output
bits on the 8574 chip to get the information to fill in the constructor.
The next best thing would be look at the board.
In this case the bottom of the board has the needed visual information.
De-soldering the board is going to be tough.

That leaves you with 2 choices:

  • Ask the seller of the board for the information
  • guess.

Guessing is not really a good way of doing things as it can sometimes cause damage if
You can try guessing.
Just don't leave it hooked up too long. With these i2c boards, if it is correct,
it will spring to life immediately.

A fairly good/educated guess would be use the bit/pin mappings constructor for the mjkdz i2c backpack
noted in the newLiquidCrystal library linked to above.

--- bill

Hello Bill,

you are absolutely spot on with your reply, the definitions are wrong. I never realized that there are different maps between different LCD manufacturers with the same translator IC. Took some time guessing as you said and some traces I could follow on the piggy-back board and measure with a DMM where they go.

Here is what I did to get it to work, I added this to the sketch to define the pins:

#define I2C_ADDR 0x20 // Define the I2C Address where the PCF8574A is located on the bus

#define En_pin 4
#define Rw_pin 5
#define Rs_pin 6
#define D4_pin 0
#define D5_pin 1
#define D6_pin 2
#define D7_pin 3

#define LED_OFF 0
#define LED_ON 1

LiquidCrystal_I2C lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);

This works OK although the display seems top be a little slow when updating and the white characters are only white if you look not straight down on the display, playing with the contrast helps a little but at least it is working now after so many hours trying to figure this out.

Now how do I modify the library to have the definitions in there so that I do not have to do this in my sketch?

Thanks for your super quick reply, even at this hour....


While it's not difficult to modify the library's code to change the default mappings, I wouldn't.
The value of using the full constructor is that it is the only thing that must be changed/modified
for a given LCD interface or wiring.
Once that is done (and it can be only one line) all the rest of the sketch code works the same
regardless of the interface or wiring.
i2c, 4bit, shift register etc....
And that includes backlight control.

For your specific display you could simplify the constructor to use hard coded values:
LiquidCrystal_I2C lcd(0x20,4, 5, 6, 0, 1,2,3, 7, NEGATIVE);
to minimize the lines of code that has to be inserted/replaced.
You have to have a constructor anyway, so would it really save much by modifying
the library to use your particular boards wiring to shorten the constructor?
It would also mean that if you were to get a future updated version of the library, your code
would break until you once again modified the library for your board.

Yes the supplied examples won't work "as is" on your board without modifying the library or the examples,
but, IMHO, the example sketches are not really particularly great examples,
of how to use the library since they don't use the library's newer backlight capabilities/functions.
i.e. once you fully fill in the constructor, there is no need to use the setBacklightPin() or have
to do pinMode() or digitalWrite() functions to control the lcd backlight.
It can be done using backlight() and noBacklight() functions.

For me, modifying the library wouldn't work since I have 3 different i2c backpacks
and they are all wired differently.

On the speed, i2c is not particularly fast. The bit transfer rate is only 100kbit/sec
and there is some amount of i2c overhead per transfer as well.
i2c is great for minimizing pins or sharing pins across multiple devices, but
not so great for speed.

On the brightness, are you doing any clear() operations in a loop?
that can cause flickering or the appearance of dimming.

If not, it sounds like the backlight might be getting proper current.

Although from the photo, the backlight looks plenty bright enough.

Maybe check the backlight resistor.
The i2c module you have doesn't have a current limiting resistor
on it and I can't quite tell if there is one on your board.
Maybe it needs one and the backlight is dim because it is being overdriven.

--- bill

Hello Bill,

Got it all under control now, nice short and clean code for driving the LCD. I removed the setBackLightPin(), pinMode() and digitalWrite() and can still control the backlight with the library. I need the flashing backlight for alarm situations in this controller so it all works out OK.

These displays may not be the best you can get but they are dirt cheap. I checked the backlight and it is OK, current to the LCD is OK and I am using an external power supply for the entire controller anyway. Got 12 Dallas 18B20's hooked up, 2 brushless AC servo motors + drivers, a bunch of switches and a couple of relays to drive large valves. Now add the display for actual process status and information and it should be complete now. Process parameters are going to a Processing sketch for graphing and datalogging. Back up on a SD card inside the controller in case the USB connection gets lost. Super cool stuff. Time for a Due, need something faster I guess but first need to get this working the way I want.

Thanks for helping me out getting the library to work!! Happy camper here, off to bed now or maybe one more coffee and some more coding....


Hello Bill,
Time for a Due, need something faster I guess .....

Take a look at a Teensy 3 if you are considering a Due, if you don't need shield
compatibility. I really like Paul's stuff. His s/w typically works better and often is faster.
The lack of 5 volt capability and tolerance can make certain things more difficult.
There is also chipkit for more speed and 5v tolerance.

--- bill

Hello Bill,

The Teensy 3.0 looks very promising, will get one or two on order to see if I can use this to make an intelligent, stand alone mixing valve controller that handles all the low level controls for the motor, drive, switches and safety components so that I can simply send high level commands to the Teensy in the valves and have the Teensy take care of all the work inside the valves. Chipkit is nice because the digital lines are 5V tolerant which makes it much easier to hook sensors and stuff like the Dallas 18B20 up to it although the Dallas works on 3V also. I tried that already and see no problems with 3.3V except the libraries are not completed yet for the Due.

Will keep you posted on progress and problems, uuhh challenges I mean. :grin: