Get to Know ESP32 #4: Display Using I2C LCD
Yep, new project this week, and fortunately I’m still excited! This project is to print outputs in LCD (Liquid Crystal Display)— which is supported by I2C module. As always, my go-to guide is randomnerdtutorials. There are two types of output that we’re going to work on, static text, special character, and scrolling text.
Let’s talk about the I2C LCD. Compared to a regular LCD, it has a simpler wiring where you only have to wire 2 pins (SDA & SCL) in I2C LCD while the regular requires 14 pins. Ugh, such a no-no. And, it has a built-in potentiometer!
Preparation
These are the stuffs we need to get ready:
- 1 NodeMCU ESP32-S Development Board(mine with 38 pins)
- 1 Laptop with Arduino IDE installed and configured
- 4 Female-to-Female Wire Jumpers
- 1 USB-A to MicroUSB cable
For the libraries, we have to install this library called Liquid Crystal_I2C. When downloaded, these are the steps to make the library known to ArduinoIDE:
- Open the .zip file. There you’ll find a folder, rename it to LiquidCrystal_I2C
- Search your Arduino installation folder, open libraries and extract the LiquidCrystal_I2C folder to the libraries folder.
Circuit
Next, make a circuit as shown above. Connect the GND pin on LCD to GND pin on ESP32, SCL pin to GPIO22, SDA pin to GPIO21, and VCC pin to 5V. Use female-to-female jumpers.
Below is the circuit I managed to make.
Getting LCD Address
We need to know the I2C LCD address before moving forward. So, below is my program.
#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);
}
We’ll have to open Serial Monitor at baud rate 115200. Since I’m using a 16 x 2 LCD, I get the address 0x27.
Static Text
I edited the code that I got from randomnerdtutorials. Here’s now how it looks like.
#include <LiquidCrystal_I2C.h>// set the LCD number of columns and rows
int lcdColumns = 16; // this shows how many columns LCD has
int lcdRows = 2; // while this is how many rows LCD has// 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, second row
lcd.setCursor(0, 1);
// print message
lcd.print("Good morning!");
delay(1000);
// clears the display to print new message
lcd.clear();
// set cursor to first column, first row
lcd.setCursor(0,0);
lcd.print("Hello, World!");
delay(1000);
lcd.clear();
}
So, instead of printing the first output on the first row (as in randomnerdtutorials), I switched the sequence and got the first output on the second row. I also changed the first output to ‘Good morning!’ instead of ‘Hello, world!’.
P.S. If your address is not 0x27, change the value in this row according to your address.
LiquidCrystal_I2C lcd(0x27, lcdColumns, lcdRows)
As always, we’ll need to verify the code and upload it to ESP32 (make sure you have already connected ESP32 to laptop via USB-A to MicroUSB cable).
Scrolling Text
The LCD has 16 x 2 display, but it’s not enough, because we can’t only have 16 characters that we want to print, right? This is why scrolling text is needed. In this program, printed on the first row is static text which is less than 16 characters, and on the second row is the scrolling text which has more than 16 characters.
Again, I got the overall code from randomnerdtutorials and decided to mix it up a bit. Instead of printing ‘Static message’ on the first row and ‘This is a scrolling message with more than 16 characters’ on the second row, I printed ‘Hey!’ on the first row and ‘You look very wonderful today!’ on 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 = "Hey!";
String messageToScroll = "You look very wonderful today!";// 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);
}
P.S. Again, a friendly reminder. If your address is not 0x27, change the value in this row according to your address.
LiquidCrystal_I2C lcd(0x27, lcdColumns, lcdRows)
Here’s how my program worked.
Special Character
Let’s say we want to print charcters that are not numbers, alphabets, or symbols provided by keyboard. Fortunately, LCD got you covered. To find out how to generate the character byte by byte, go to this link.
Here, I made a heart emoji and printed it on all corners of the LCD. Here’s the program needed.
#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); // change the address value according to yours that you got from previous codebyte heart[8] = {
0b00000,
0b01010,
0b11111,
0b11111,
0b11111,
0b01110,
0b00100,
0b00000
};void setup(){
// initialize LCD
lcd.init();
// turn on LCD backlight
lcd.backlight();
lcd.createChar(0, heart);
}void loop(){
lcd.setCursor(0,0);
lcd.write(0);
lcd.setCursor(15,0);
lcd.write(0);
lcd.setCursor(0,1);
lcd.write(0);
lcd.setCursor(15,1);
lcd.write(0);}
And this is how it looks like. So cute, you know?
You need to know that there will be a warning when verifying or uploading that looks like this.
You can ignore it! No need to worry :)
Overall, this project went smoothly and I found no difficulties (well perhaps a little bit of wiring mismatch which is my error and little use of brain in editing the program). As always, you can drop comments if you face a problem with this project.
See you next week!