<< Click to Display Table of Contents >>

Navigation:  »No topics above this level«

LCD Character Display with I2C interface using PCF8574 - Arduino C++ and FEZ Duino C#

Return to chapter overview

These displays normally need 8 digital I/Os to connect to your microcontroller. But you can buy a very cheap adaptor which allows it to be connected to the serial I2C interface, so you need only the two I2C wires SCK and SDA, plus 5V and GND. This is an "I2C to LCD interface adaptor" which contains a PCF8574 chip. You can by the LCD modules with the adapter already fitted, or buy them separately and solder them together. The LCD requires a 5V supply, but the PCF8574 adapter can use 3.3V or 5V - this can cause problems when connecting to a 3.3V controller - see below.

 

Code for LCD1602 and LCD2004 displays

The code has been tested on an Arduino Uno R3 and an Arduino Zero, so it should run on all Arduinos. The C# version runs on GHI Electronics' TinyCLR operating system.

Arduino Sketch containing the example: LcdDisplayI2C-Uno.zip

C# version for the GHI Electronics FEZ Duino: LcdDisplayI2C-cs.zip

The code is not thread safe
As with most libraries, do not call these methods from different "threads", e.g. timer callbacks or interrupt handlers, because the display will misbehave. Use a mutex-type lock if methods are called from different threads, or ensure only one thread accesses the display, e.g. only loop().

 

Pretty pictures

lcd1602

 

The LCD board with the I2C adaptor fitted:

i2c-adaptor

 

In this picture, I have two 4k7 pull-ups to 5V, because I removed the pull-ups on the LCD board to use it with a 3.3V microcontroller, but the Uno is a 5V device.

lcd1602-uno

 

The 4-pin connector on the I2C adaptor

1

SCL

I2C clock

Warning! Has pull-up resistor to 5V, see below

2

SDA

I2C data

Warning! Has pull-up resistor to 5V, see below

3

VCC

5V supply

5V is needed, it does not work with 3.3V! *

4

GND

Ground

 

* Unless you have a fancy new 3.3V model, in which case you can skip the next section.

 

WARNING!!! DO NOT CONNECT A 5V LCD MODULE DIRECTLY TO A 3.3V MICROCONTROLLER!

Most modern microcontroller boards run at 3.3V, and if its inputs are not '5V tolerant' then they may be damaged if connected to a 5V I2C signal. Actually, I tried it, and it was ok because the internal protection diodes dump less than 2mA (5V / 4.7K = 1.06mA), but I wouldn't recommend it. The LCD module's supply voltage is 5V, so it's not supposed to be compatible with 3.3V controllers that don't have 5V-tolerant inputs. If the expander board has pull-up resistors to 5V on the I2C's SCL and SDA lines (pins 14 and 15 of the PCF8574) then it may damage your 3.3V microcontroller.

If you are using a 5V microcontroller to connect to the LCD, or if the microcontroller has 5V tolerant inputs, then it's all OK and you can skip this part.

There are 2 ways to fix the 3.3V/5V compatibility problem:

1) Remove the 5V pull-up resistors on the PCF8574 board's SCL and SDA lines, and add your own 4.7K pull-up resistors to the microcontroller's 3.3V instead of 5V. Use a continuity tester to find the two pull-up resistors on the adapter module. Each pull-up resistor will have one end connected to Vcc (pin 16 of the PCF8574 chip), and the other end connected to the SCL or SDA pin of the connector and pins 14 and 15 of the PCF8574 chip. On my module it was R8 and R9, both 4.7K ohms, marked '472'.

Next, add two new pull-up resistors on the microcontroller side. Two 4.7K resistors from the SCL and SDA pins to +3.3V. You can omit these if you have another device on the bus which already has pull-ups to 3.3V.

lcd-i2c-adapter-module-5

Remove the R8 and R9 pull-ups on the adapter board.

pcf8574-pullups

 

2) If you have more than one 5V I2C device connected, then you can use a "logic level converter" board to convert 3.3V to 5V. These are easy to find (Sparkfun, Adafruit etc.), and are cheap. Or you can make your own with two resistors and an N-CH mosfet with Vgs(th) of around 1.3V for each signal (BSS138 etc). Here's an LTspice simulation of the circuit:
https://muman.ch/pub/bidirectional-logic-level-translator.png

Or even better, use the fancy TXB0108 "8-bit bidirectional voltage level translator" chip:
https://www.ti.com/lit/ds/symlink/txb0108.pdf

 

Contrast adjustment
The contrast adjustment (the pot on the I2C adapter board) is very sensitive. One tenth of a turn can make the difference between a visible and an invisible display. At first, I thought my display was not working, but it *was* working - it was only the contrast adjustment that was wrong.

I2C slave address selection jumpers
The upper 4 bits of the card's 7-bit I2C address are fixed by the PCF8574 chip. The lower 3 bits are configured by the A2 A1 A0 jumpers on the expander board. The PCF8574 and PCF8574A have different internally hard-wired addresses.

 

A6

A5

A4

A3

A2

A1

A0

Addresses

PCF8574

0

1

0

0

x

x

x

0x20..0x27

PCF8574A

0

1

1

1

x

x

x

0x38..0x3f

If the jumper is in (closed), it is grounded, and the address bit is 0. If the jumper is out (open), it is pulled high by an internal resistor, and the bit is 1. For some boards, all jumpers are in (grounded, A2..A0 = 000), and a bit is set to 1 by cutting the trace. For others, all jumpers are out (pull-ups make A2..A0 = 111), and a bit is set to 0 with a blob of solder (which connects it to GND).

Default adapter address
The default address depends on how the I2C adapter is wired, with open or closed jumpers.
Default address with closed (grounded) jumpers:  000   PCF8574 = 0x20, PCF8574A = 0x38
Default address with open (pull-up) jumpers:        111   PCF8574 = 0x27, PCF8574A = 0x3f

PCF8574 output signals
The LCD display runs in 4-bit mode, using DB7..DB4 for each nibble. MS nibble is written first. The 8-bit outputs of the PCF8574 are connected as follows:

P7

DB7

4-bit data, for 8 bits write MS nibble then LS nibble

P6

DB6

''

P5

DB5

''

P4

DB4

''

P3

BL

Backlight: 1=on; 0=off (also controlled by jumper) [this masks the BUSY BF flag]

P2

EN

Enable: This is toggled to 'write' the data to the LCD

P1

RW

Read/Write: 0=Write mode; 1=Read mode

P0

RS

Register Select: 0=Instruction register (for write) or Busy register (for read),

1=Data register (for read and write)

 

References

Proto Supplies (USA) has a nice description of the I2C adapter board, this is where I found the schematics that matched my board
https://protosupplies.com/product/lcd-i2c-interface-adapter/

If you're in Switzerland, you can buy it here
https://www.bastelgarage.ch/i2c-schnittstelle-pcf8574-fur-lcd-display

Typical LCD1602 circuit diagram
https://muman.ch/pub/lcd1602-schematic.png

Typical LCD data sheet, there are differences with timing from different manufacturers
https://cdn-shop.adafruit.com/datasheets/TC1602A-01T.pdf

PCF8574 I2C 8-bit I/O expander data sheets
https://www.ti.com/lit/ds/symlink/pcf8574.pdf
https://www.nxp.com/docs/en/data-sheet/PCF8574_PCF8574A.pdf