16×2 LCD Display with I2C | PCF8574 Library
16×2 LCD is an alphanumeric display that can show up to 32 characters on a single screen. You can display more characters by scrolling the texts one by one. We have already seen how to connect LCD Display directly with the Arduino using 4bit and 8bit modes in our previous tutorial. But those two modes will utilize many numbers of GPIO Pins of our Arduino and we would have to end up with less number of pins for other sensors and actuators.
To overcome this problem we use LCD I2C backpack with our LCD. This I2C Backpack uses PCF8574 Remote 8 bit I/O Expander. It translates the data received from the I2C Bus into Parallel data that is needed for the LCD Display.
I2C – Inter-Integrated Circuit:
Inter-integrated Circuit (in short I2C) is a two-wire short distance communication protocol. You can use multiple slave devices in the same two wires with one or more master controllers. You may wonder how does the master identifies which slave does the data to be sent. In I2C the external devices have an I2C address for different external devices like LCD Backpack, OLED Display, etc. By using the address the data is sent to the specific device connected on the same I2C Bus.
The message is broken into two frames and sent serially via the I2C Bus. The first frame contains the address, once the address matches with any device on I2C bus, that device will send an acknowledge signal to the master. After receiving the acknowledgment from the slave the data bits are sent. By this method an I2C bus works.
16×2 LCD Display:
A 16×2 LCD means it can display 16 characters per line and there are 2 such lines. In this LCD each character is displayed in the 5×7 pixel matrix.
LCD Pinout:
There are totally 16 pins in an LCD Display. You can use directly all the pins in 8-bit mode with Arduino or 12 pins using 4-bit mode. In this tutorial, we use the I2C module for LCD and multiplex it into just 4 pins. This pin details might not be useful while using I2C Method but this is the actual pin details of all the pins in LCD Display.
Vcc – Power Supply (5v)
Vdd/GND – Ground
V0 – Brightness Control using Potentiometer
RS – Register select. Specify what we are sending Command or Data. Sets to 0 for Command mode like setCursor, LCD Clear, TurnOFF LCD. Set 1 for data mode like sending Data/Characters.
R/W – Read/Write. Mostly we are writing data/characters to the registers.
E – Enable writing to Registers.
D0 to D7 – Data pins. Send 4bit/8bit data to display characters. The Arduino library provides 4bit and 8bit mode. The data will be in ASCII format.
A/LED+ – Anode (Backlight LED)
K/LED- – Cathode (Backlight LED)
I2C Pinout:
The LCD I2C Backpack only has 4 Pins. They are
GND – Ground
VCC – 5V Power Supply
SDA – Data Line
SCK – Clock Line
Circuit diagram:
The connection is simple just attach the LCD Backpack as shown in the image (Pins coming outwards). Connect
GND – Ground of Arduino
VCC – 5V Arduino Pin
SDA – SDA Pin of Arduino (mentioned in the backside of Arduino)
SCL – SCL Pin of Arduino (mentioned in the backside of Arduino)
Finding I2C Address of our backpack:
First, we need to find the address of our I2C LCD Backpack. For that, we will be using I2C Scanner code to display the address in the serial monitor. Upload the following code, then note down the I2C address from the serial monitor.
#include <Wire.h> void setup() { Wire.begin(); Serial.begin(9600); while (!Serial); // Leonardo: wait for serial monitor Serial.println("\nI2C Scanner"); } void loop() { byte error, address; int nDevices; Serial.println("Scanning..."); nDevices = 0; for(address = 1; address < 127; address++ ) { // The i2c_scanner uses the return value of // the Write.endTransmisstion to see if // a device did acknowledge to the address. Wire.beginTransmission(address); error = Wire.endTransmission(); if (error == 0) { Serial.print("I2C device found at address 0x"); if (address<16) Serial.print("0"); Serial.print(address,HEX); Serial.println(" !"); nDevices++; } else if (error==4) { Serial.print("Unknown error at address 0x"); if (address<16) Serial.print("0"); Serial.println(address,HEX); } } if (nDevices == 0) Serial.println("No I2C devices found\n"); else Serial.println("done\n"); delay(5000); // wait 5 seconds for next scan }
In my case, it is 0x27. Node down the address displayed for you. Mostly it will be 0x27 only. In case you have another I2C device connected on the same bus it will show that address too.
Now we will be using this address on our code.
Download and Install LiquidCrystal_I2C Library:
Download .zip LiquidCrystal_I2C library by Frank de Brabander from here and Install it in IDE by navigating Sketch>Include Library>Add .zip library and choose the downloaded LiquidCrystal_I2C.zip library file.
Now the LCD I2C library is installed. We need to define and initialize the library using its associated functions. The steps is as follows. Or you can copy the code given below to print Hello World example.
Declare the LiquidCrystal_I2C.h library by using the following line
#include <LiquidCrystal_I2C.h>
Set the address that we copied from I2C Scanner code. The address I got is 0x27 so I replaced it to 0x27 in the following line
LiquidCrystal_I2C lcd(0x27, 16, 2);
Inside the setup function, initialize the LCD by using the following function
lcd.begin();
Example Code to print ‘Hello World’:
#include <Wire.h> #include <LiquidCrystal_I2C.h> // Set the LCD address to 0x27 for a 16 chars and 2 line display LiquidCrystal_I2C lcd(0x27, 16, 2); void setup() { // initialize the LCD lcd.begin(); // Turn on the blacklight and print a message. lcd.backlight(); lcd.print("Hello, world!"); } void loop() { // Do nothing here... }
In the above code, we have created an LCD object for ‘LiquidCrystal_I2C’. So you can use directly use the regular LCD functions to work with I2C like lcd.begin(), lcd.print(“”), etc.
Frequently used LCD Functions:
To print a string we use lcd.print() function with string in its parameters. This prints ‘Factory’ string in the 1st row and ‘Forward’ in the 2nd row.
Important Note: The columns and rows position starts with 0th location.
Example: 7th column and 2nd row are mentioned as (6, 1).
lcd.print():
This function is used to print a message on LCD.
lcd.print("Factory"); // Prints "Factory" on first row delay(2000); // 2 seconds delay
lcd.setCursor(column,row):
This function sets the cursor on 7th column and 2nd row. Printing the string will gets displayed from this location on LCD.
lcd.setCursor(6,1); // Sets cursor column and row position lcd.print("Forward"); //Prints ‘Forward’ on 7th column of 2nd row.
lcd.clear():
The LCD will hold the previous data on its registers. You need to manually clear it using the lcd.clear() function.
lcd.clear();
Blinking Full Cursor:
By Using lcd.blink() function we can make the cursor blinking on LCD. To turn off the blinking cursor we use lcd.noBlink() function.
lcd.blink(); //Blinking cursor lcd.noBlink(); //Turns OFF blinking cursor
Underscore Cursor:
Use lcd.cursor() function for printing an underscore symbol. It is also used for notifying users to enter some values.
lcd.cursor(); // Prints an underscore symbol lcd.noCursor(); Clears the underscore only.
Comment (1)
I used this module to interface 2 displays using 1 Arduino Uno board to displaying LCD 16×2 , and graphical display interface the display but only one LCD was working is it possible using Arduino Uno board