In this article, we’ll learn how to utilize the Arduino IDE with the ESP32 (or ESP8266) and the I2C LCD Display module (PCF8574). We’ll use the LiquidCrystal I2C library in Arduino Core, together with the I2C Wire.h library, to connect the LCD 162 display to the I2C bus.

The library APIs are very similar to the standard LiquidCrystal library in Arduino.Except for the fact that it does use the I2C bus instead of parallel (4-Bit) data mode. Which does save a lot of GPIO pins and very suitable for many projects.

PARTS REQUIRED

To follow this tutorial you need these parts:

  • ESP32 DOIT DEVKIT V1 Board -The Esp32 DevKit v1 is one of the development boards created to evaluate the ESP-WROOM-32 module. It is based on the ESP32 microcontroller that boasts Wifi, Bluetooth, Ethernet and Low Power support all in a single chip.
  • Optional – ESP8266 12-E 
  • 16×2 I2C Liquid Crystal Display (LCD)-This I2C 16×2 Arduino LCD Screen is using an I2C communication interface. It means it only needs 4 pins for the LCD display: VCC, GND, SDA, SCL. It will save at least 4 digital/analog pins on Arduino. 
  • Female to female jumper wires

Wiring the LCD to the ESP32

Wire your LCD to the ESP32 by following the next schematic diagram. We’re using the ESP32 default I2C pins (GPIO 21 and GPIO 22).

Wiring the LCD to the ESP8266

You can also wire your LCD to the ESP8266 by following the next schematic diagram. We’re using the ESP8266 default I2C pins (GPIO 4 and GPIO 5).

Installing the LiquidCrystal_I2C Library

  1. Click here to download the LiquidCrystal_I2C library. You should have a .zip folder in your Downloads
  2. Unzip the .zip folder and you should get LiquidCrystal_I2C-master folder
  3. Rename your folder from LiquidCrystal_I2C-master to LiquidCrystal_I2C
  4. Move the LiquidCrystal_I2C folder to your Arduino IDE installation libraries folder
  5. Finally, re-open your Arduino IDE

Getting the LCD Address

Code

#include <Wire.h>
 
void setup() {
  Wire.begin();
  Serial.begin(115200);
  Serial.println("\nI2C Scanner");
}
 
void loop() {
  byte error, address;
  int nDevices;
  Serial.println("Scanning...");
  nDevices = 0;
  for(address = 1; address < 127; 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.println(address,HEX);
      nDevices++;
    }
    else if (error==4) {
      Serial.print("Unknow 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);          
}

After uploading the code, open the Serial Monitor at a baud rate of 115200. Press the ESP32 EN button. The I2C address should be displayed in the Serial Monitor.

Display Static Text on the LCD

Displaying static text on the LCD is very simple. All you have to do is select where you want the characters to be displayed on the screen, and then send the message to the display.

#include <LiquidCrystal_I2C.h>

// set the LCD number of columns and rows
int lcdColumns = 16;
int lcdRows = 2;

// set LCD address, number of columns and rows
// if you don't know your display address, run an I2C scanner sketch
LiquidCrystal_I2C lcd(0x27, lcdColumns, lcdRows);  

void setup(){
  // initialize LCD
  lcd.init();
  // turn on LCD backlight                      
  lcd.backlight();
}

void loop(){
  // set cursor to first column, first row
  lcd.setCursor(0, 0);
  // print message
  lcd.print("Hello, World!");
  delay(1000);
  // clears the display to print new message
  lcd.clear();
  // set cursor to first column, second row
  lcd.setCursor(0,1);
  lcd.print("Hello, World!");
  delay(1000);
  lcd.clear(); 
}

How the code works

First, you need to include theLiquidCrystal_I2C library.

#include <LiquidCrystal_I2C.h>

The next two lines set the number of columns and rows of your LCD display. If you’re using a display with another size, you should modify those variables.

int lcdColumns = 16;

int lcdRows = 2;

Then you must specify the display address, as well as the number of columns and rows. The display address you discovered in the previous step should be used.

LiquidCrystal_I2C lcd(0x27, lcdColumns, lcdRows);

In the setup(), first initialize the display with the init() method.

lcd.init();

Then, turn on the LCD backlight, so that you’re able to read the characters on the display.

lcd.backlight();

To display a message on the screen, first you need to set the cursor to where you want your message to be written. The following line sets the cursor to the first column, first row.

lcd.setCursor(0, 0);

Note: 0 corresponds to the first column, 1 to the second column, and so on…

Then, you can finally print your message on the display using the print() method.

lcd.print(“Hello, World!”);

Wait one second, and then clean the display with the clear() method.

lcd.clear();

After that, set the cursor to a new position: first column, second row.

lcd.setCursor(0,1);

Then, the process is repeated.

So, here’s a summary of the functions to manipulate and write on the display:

  • lcd.init(): initializes the display
  • lcd.backlight(): turns the LCD backlight on
  • lcd.setCursor(int column, int row): sets the cursor to the specified column and row
  • lcd.print(String message): displays the message on the display
  • lcd.clear(): clears the display

Display Scrolling Text on the LCD

When you need to display messages that are longer than 16 characters, scrolling text on the LCD is quite beneficial. Text scrolling is possible with the library’s built-in features. Many people, however, have issues with those functions because:

  • The function scrolls both rows of text. As a result, you can’t have a fixed row and a scrolling row at the same time.
  • If you try to display messages that are longer than 16 characters, it will not operate properly.

The following sketch displays a static message in the first row and a    scrolling message longer than 16 characters in the second row.

#include <LiquidCrystal_I2C.h>

// set the LCD number of columns and rows
int lcdColumns = 16;
int lcdRows = 2;

// set LCD address, number of columns and rows
// if you don't know your display address, run an I2C scanner sketch
LiquidCrystal_I2C lcd(0x27, lcdColumns, lcdRows);  

String messageStatic = "Static message";
String messageToScroll = "This is a scrolling message with more than 16 characters";

// Function to scroll text
// The function acepts the following arguments:
// row: row number where the text will be displayed
// message: message to scroll
// delayTime: delay between each character shifting
// lcdColumns: number of columns of your LCD
void scrollText(int row, String message, int delayTime, int lcdColumns) {
  for (int i=0; i < lcdColumns; i++) {
    message = " " + message;  
  } 
  message = message + " "; 
  for (int pos = 0; pos < message.length(); pos++) {
    lcd.setCursor(0, row);
    lcd.print(message.substring(pos, pos + lcdColumns));
    delay(delayTime);
  }
}

void setup(){
  // initialize LCD
  lcd.init();
  // turn on LCD backlight                      
  lcd.backlight();
}

void loop(){
  // set cursor to first column, first row
  lcd.setCursor(0, 0);
  // print static message
  lcd.print(messageStatic);
  // print scrolling message
  scrollText(1, messageToScroll, 250, lcdColumns);
}

After reading the previous section, you should be familiar on how this sketch works, so we’ll just take a look at the newly created function: scrollText()

void scrollText(int row, String message, int delayTime, int lcdColumns) {

  for (int i=0; i < lcdColumns; i++) {

    message = ” ” + message; 

  } 

  message = message + ” “; 

  for (int pos = 0; pos < message.length(); pos++) {

    lcd.setCursor(0, row);

    lcd.print(message.substring(pos, pos + lcdColumns));

    delay(delayTime);

  }

}

To use this function you should pass four arguments:

  • row: row number where the text will be display
  • message: message to scroll
  • delayTime: delay between each character shifting. Higher delay times will result in slower text shifting, and lower delay times will result in faster text shifting.
  • lcdColumns: number of columns of your LCD

In our code, here’s how we use the scrollText() function:

scrollText(1, messageToScroll, 250, lcdColumns);

The messageToScroll variable is displayed in the second row (1 corresponds to the second row), with a delay time of 250 ms (the GIF image is speed up 1.5x).

Display Custom Characters

There are 32 blocks in a 162 LCD where characters can be shown. Each block is composed of 588 individual pixels. By setting the state of each tiny pixel, you can display personalised characters. You can do this by storing the state of each pixel in a byte variable.

For example, a heart:

Copy the byte variable to your code (before the setup()). You can call it heart:

                  byte heart[8] = {

  0b00000,

  0b01010,

  0b11111,

  0b11111,

  0b11111,

  0b01110,

  0b00100,

  0b00000

};

Then, in setup(), use the createChar() function to create a new character. The following are the arguments to this function: a location to allocate the char and the char variable:

lcd.createChar(0, heart);

Then, in the loop(), set the cursor to where you want the character to be displayed:

lcd.setCursor(0, 0);

Use the write() method to display the character. Pass the location where the character is allocated, as follows:

lcd.write(0);

CONCLUSION

In conclusion, we’ve shown you how to use an I2C LCD display with the ESP32/ESP8266 and the Arduino IDE to display static text, scrolling text, and custom characters in this article. This tutorial can also be used with an Arduino board; simply alter the pin assignment to utilise the Arduino I2C pins.

Author

Write A Comment