Step-by-Step Guide: Arduino Integration With I2C LCD Screen

by AKP in Circuits > Arduino

270 Views, 1 Favorites, 0 Comments

Step-by-Step Guide: Arduino Integration With I2C LCD Screen

i2c-lcd-arduino-tutorial.png

If you’ve ever tried linking an LCD display to an Arduino, you likely observed that it consumes a substantial number of Arduino pins. Even in 4-bit mode, it demands seven connections, which is half of the available digital I/O pins on the Arduino.

The remedy is to opt for an I2C LCD display. This type of display only necessitates two I/O pins, which are distinct from the standard digital I/O pin set and can be utilized concurrently with other I2C devices.

Hardware Overview

Character-LCD-Internal-Pixel-Grid-Structure.jpg
PCF8574-Chip-On-I2C-LCD.jpg
I2C-LCD-Adapter-Hardware-Overview.jpg

An average I2C LCD display comprises a character LCD display based on HD44780 and an I2C LCD adapter. Let’s delve into their details.

Character LCD Display

True to its name, these LCDs excel in presenting characters. For instance, a 16×2 character LCD can exhibit 32 ASCII characters spread across two rows.

On close inspection, you’ll notice small rectangles for each character on the screen, along with the pixels forming a character. Each of these rectangles forms a grid of 5×8 pixels.

For more details about character LCD displays, please consult our comprehensive guide.

I2C LCD Adapter

The core of the adapter features an 8-bit I/O expander chip – PCF8574. This chip transforms the I2C data from an Arduino into the parallel data necessary for an LCD display.

The board is equipped with a small trimpot for precise adjustments to the display’s contrast.

A jumper on the board supplies power to the backlight. To regulate the backlight’s intensity, you can remove the jumper and apply external voltage to the header pin labeled ‘LED.’

LCD I2C Address Configuration

I2C-Address-selection-jumpers-on-I2C-LCD.jpg
NXP-Semiconductors-PCF8574-I2C-Address-Register.jpg
I2C-LCD-Address-Selection-Jumper-Table-for-NXP.jpg
I2C-LCD-Address-Selection-Jumper-Table-for-TI.jpg
NXP-Semiconductors-PCF8574-I2C-Address-Register.jpg

If you have multiple devices connected to the same I2C bus, it may be necessary to assign a unique I2C address to the LCD adapter to prevent conflicts with other I2C devices.

To achieve this, the adapter is equipped with three solder jumpers/pads labeled A0, A1, and A2. The I2C address is determined by shorting a jumper with a solder blob.

It’s important to note that various companies, such as Texas Instruments and NXP Semiconductors, produce the same PCF8574 chip, and the I2C address of your LCD is contingent on the chip manufacturer.

If your LCD utilizes Texas Instruments’ PCF8574 chip:

Referencing Texas Instruments’ datasheet, the three address selection bits (A0, A1, and A2) are positioned at the end of the 7-bit I2C address register.

Since there are three address inputs with two possible states, HIGH or LOW, eight (2^3) unique combinations (addresses) are feasible.

All three address inputs default to HIGH due to onboard pullups, resulting in the PCF8574 having a default I2C address of 0x27.

Shorting a solder jumper pulls the respective address input LOW. If all three jumpers are shorted, the address becomes 0x20. Consequently, the address range spans from 0x20 to 0x27.

You can configure a different I2C address as outlined in the provided table.

If your LCD features NXP’s PCF8574 chip:

According to NXP Semiconductors’ datasheet, the three address selection bits (A0, A1, and A2) are also found at the end of the 7-bit I2C address register, but the remaining bits in the address register differ.

With three address inputs capable of being either HIGH or LOW, eight (2^3) distinct combinations (addresses) are possible.

Similar to Texas Instruments, all three address inputs are pulled HIGH by onboard pullups, resulting in the PCF8574 having a default I2C address of 0x3F.

Shorting a solder jumper pulls the respective address input LOW. If all three jumpers are shorted, the address becomes 0x38. Consequently, the address range spans from 0x38 to 0x3F.

You can configure a different I2C address using the provided table.

I2C LCD Display Pinout

I2C-LCD-Display-Pinout.jpg

The I2C LCD Display has only four pins. The following is the pinout:

  • GND is a ground pin.
  • VCC is the power supply pin. Connect it to the 5V output of the Arduino or an external 5V power supply.
  • SDA is the I2C data pin.
  • SCL is the I2C clock pin.


Simple Arduino Sketch – Hello World

Interfacing-16x2-character-LCD-with-Arduino-Hello-world-Program-output.jpg

The provided test sketch will display ‘Hello World!’ on the first line of the LCD and ‘LCD Tutorial’ on the second line.

Prior to uploading the sketch, a minor modification is required to ensure its functionality for your setup. You need to specify the I2C address of your LCD, along with the display dimensions, in the LiquidCrystal_I2C constructor. If you’re utilizing a 16×2 character LCD, input 16 and 2; for a 20×4 character LCD, input 20 and 4.

#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x3F,16,2); // set the LCD address to 0x3F for a 16 chars and 2 line display

void setup() {
lcd.init();
lcd.clear();
lcd.backlight(); // Make sure backlight is on

// Print a message on both lines of the LCD.
lcd.setCursor(2,0); //Set cursor to character 2 on line 0
lcd.print("Hello world!");

lcd.setCursor(2,1); //Move cursor to character 2 on line 1
lcd.print("LCD Tutorial");
}

void loop() {
}


Arduino Example Code

Interfacing-16x2-LCD-with-Arduino-Custom-Character-Generation-Program-output.jpg

The sketch below demonstrates how to display custom characters on the LCD.

#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x3F, 16, 2); // set the LCD address to 0x3F for a 16 chars and 2 line display

// make some custom characters:
byte Heart[8] = {
0b00000,
0b01010,
0b11111,
0b11111,
0b01110,
0b00100,
0b00000,
0b00000
};

byte Bell[8] = {
0b00100,
0b01110,
0b01110,
0b01110,
0b11111,
0b00000,
0b00100,
0b00000
};


byte Alien[8] = {
0b11111,
0b10101,
0b11111,
0b11111,
0b01110,
0b01010,
0b11011,
0b00000
};

byte Check[8] = {
0b00000,
0b00001,
0b00011,
0b10110,
0b11100,
0b01000,
0b00000,
0b00000
};

byte Speaker[8] = {
0b00001,
0b00011,
0b01111,
0b01111,
0b01111,
0b00011,
0b00001,
0b00000
};


byte Sound[8] = {
0b00001,
0b00011,
0b00101,
0b01001,
0b01001,
0b01011,
0b11011,
0b11000
};


byte Skull[8] = {
0b00000,
0b01110,
0b10101,
0b11011,
0b01110,
0b01110,
0b00000,
0b00000
};

byte Lock[8] = {
0b01110,
0b10001,
0b10001,
0b11111,
0b11011,
0b11011,
0b11111,
0b00000
};

void setup()
{
lcd.init();
// Make sure backlight is on
lcd.backlight();

// create a new characters
lcd.createChar(0, Heart);
lcd.createChar(1, Bell);
lcd.createChar(2, Alien);
lcd.createChar(3, Check);
lcd.createChar(4, Speaker);
lcd.createChar(5, Sound);
lcd.createChar(6, Skull);
lcd.createChar(7, Lock);

// Clears the LCD screen
lcd.clear();

// Print a message to the lcd.
lcd.print("Custom Character");
}

// Print All the custom characters
void loop()
{
lcd.setCursor(0, 1);
lcd.write(0);

lcd.setCursor(2, 1);
lcd.write(1);

lcd.setCursor(4, 1);
lcd.write(2);

lcd.setCursor(6, 1);
lcd.write(3);

lcd.setCursor(8, 1);
lcd.write(4);

lcd.setCursor(10, 1);
lcd.write(5);

lcd.setCursor(12, 1);
lcd.write(6);

lcd.setCursor(14, 1);
lcd.write(7);
}


See Full Article Here