Arduino - LCD 20x4
In this Arduino LCD 20x4 I2C tutorial, we will learn how to connect an LCD 20x4 (Liquid Crystal Display) to the Arduino board via I2C Interface.
Or you can buy the following kits:
Disclosure: Some links in this section are Amazon affiliate links. If you make a purchase through these links, we may earn a commission at no extra cost to you.
Additionally, some links direct to products from our own brand,
DIYables .
Buy Note: Another option is to create the LCD I2C display by pairing LCD 2004 Display and PCF8574 I2C Adapter Module.
LCD 20x4 I2C uses I2C interface, so it has 4 pins:
GND pin: needs to be connected to GND (0V).
VCC pin: the power supply for the LCD, needs to be connected to VCC (5V).
SDA pin: I2C data signal
SCL pin: I2C clock signal
LCD I2C 20x4 includes 20 columns and 4 rows. the conlums and rows are indexed from 0.

This image is created using Fritzing. Click to enlarge image
| LCD I2C | Arduino Uno, Nano | Arduino Mega |
| Vin | 5V | 5V |
| GND | GND | GND |
| SDA | A4 | 20 |
| SCL | A5 | 21 |
Thanks to the DIYables_LCD_I2C library, the using LCD is a piece of cake.
#include <DIYables_LCD_I2C.h>
DIYables_LCD_I2C lcd(0x27, 20, 4);
lcd.init();
lcd.backlight();
lcd.setCursor(column_index, row_index);
lcd.print("Hello World!");
※ NOTE THAT:
The I2C address of LCD can vary according to the manufacturers. In the code, we used 0x27 that is specified by DIYables manufacturer
#include <DIYables_LCD_I2C.h>
DIYables_LCD_I2C lcd(0x27, 20, 4);
void setup() {
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("LCD 20x4");
lcd.setCursor(0, 1);
lcd.print("I2C Address: 0x27");
lcd.setCursor(0, 2);
lcd.print("DIYables");
lcd.setCursor(0, 3);
lcd.print("www.diyables.io");
}
void loop() {
}
Navigate to the Libraries icon on the left bar of the Arduino IDE.
Search "DIYables LCD I2C", then find the DIYables_LCD_I2C library by DIYables
Click Install button to install DIYables_LCD_I2C library.
There are various types of LCD I2C displays available on the market, differing mainly in background color and the I2C address selection option.
For Color Options: Typically, there are two background colors available: green and blue.
For I2C address selection option:
With a jumper: This option allows switching between two I2C addresses, which is useful if you are using two LCDs simultaneously in the code. However, when your code uses only one LCD is used, it can cause confusion with I2C addresses. And it also takes up more space.
Without a jumper: This configuration has a fixed I2C address, making it very convenient when your project involves using only one LCD display. Since most applications use a single LCD, this type is highly recommended.
We are considering to make the video tutorials. If you think the video tutorials are essential, please subscribe to our YouTube channel to give us motivation for making the videos.
The below video demo uses the below code. Note that the video shows Arduino Uno R4, but it works identically for Arduino Uno R3:
#include <Wire.h>
#include <DIYables_LCD_I2C.h>
#include <SPI.h>
#include <MFRC522.h>
#include <Servo.h>
DIYables_LCD_I2C lcd(0x27, 20, 4);
#define SS_PIN 10
#define RST_PIN 9
MFRC522 rfid(SS_PIN, RST_PIN);
Servo doorServo;
#define SERVO_PIN 6
#define BUZZER 8
byte adminUID[4] = {0x3C, 0x7F, 0xB3, 0x02};
enum State { IDLE, SCANNING, GRANTED, DENIED, LOCKED };
State systemState = IDLE;
int failCount = 0;
unsigned long stateTime = 0;
unsigned long lockTime = 0;
void beepOK() {
for (int i = 0; i < 2; i++) {
digitalWrite(BUZZER,HIGH);
delay(100);
digitalWrite(BUZZER,LOW);
delay(50);
}
}
void beepFail() {
for (int i = 0; i < 3; i++) {
digitalWrite(BUZZER,HIGH);
delay(150);
digitalWrite(BUZZER,LOW);
delay(80);
}
}
void beepLock() {
digitalWrite(BUZZER,HIGH);
delay(300);
digitalWrite(BUZZER,LOW);
}
void showIdle() {
lcd.clear();
lcd.setCursor(0,0); lcd.print("SYSTEM READY");
lcd.setCursor(0,1); lcd.print("PLEASE SCAN CARD");
lcd.setCursor(0,2); lcd.print("DOOR: LOCKED");
lcd.setCursor(0,3); lcd.print("SECURITY: ACTIVE");
Serial.println("[STATE] IDLE");
systemState = IDLE;
}
void showScanning() {
lcd.clear();
lcd.setCursor(0,1);
lcd.print("SCANNING CARD...");
Serial.println("[STATE] SCANNING");
systemState = SCANNING;
}
void showGranted() {
lcd.clear();
lcd.setCursor(0,0); lcd.print("SYSTEM: GRANTED");
lcd.setCursor(0,1); lcd.print("USER: ADMIN");
lcd.setCursor(0,2); lcd.print("OPENING DOOR...");
lcd.setCursor(0,3); lcd.print("AUTO LOCK 3s");
doorServo.write(90);
beepOK();
stateTime = millis();
systemState = GRANTED;
Serial.println("[STATE] GRANTED");
}
void showDenied(byte *uid) {
lcd.clear();
lcd.setCursor(0,0); lcd.print("SYSTEM: DENIED");
lcd.setCursor(0,1); lcd.print("UID: ");
for (byte i=0;i<4;i++) {
lcd.print(uid[i], HEX);
lcd.print(" ");
}
lcd.setCursor(0,2); lcd.print("ACCESS BLOCKED");
failCount++;
lcd.setCursor(0,3);
lcd.print("FAIL: ");
lcd.print(failCount);
lcd.print("/3");
beepFail();
stateTime = millis();
systemState = DENIED;
Serial.println("[STATE] DENIED");
}
bool isAdmin(byte *uid) {
for (byte i=0;i<4;i++) {
if (uid[i] != adminUID[i]) return false;
}
return true;
}
void lockSystem() {
systemState = LOCKED;
lcd.clear();
lcd.setCursor(0,1);
lcd.print("SYSTEM LOCKED!");
lcd.setCursor(0,2);
lcd.print("TOO MANY FAILS");
doorServo.write(0);
beepLock();
Serial.println("[STATE] LOCKED");
delay(3000);
failCount = 0;
showIdle();
}
void setup() {
Serial.begin(9600);
lcd.init();
lcd.backlight();
SPI.begin();
rfid.PCD_Init();
doorServo.attach(SERVO_PIN);
doorServo.write(0);
pinMode(BUZZER, OUTPUT);
showIdle();
}
void loop() {
if (failCount >= 3 && systemState != LOCKED) {
lockSystem();
return;
}
if (systemState == DENIED && millis() - stateTime > 2000) {
showIdle();
}
if (systemState == GRANTED && millis() - stateTime > 3000) {
doorServo.write(0);
beepLock();
showIdle();
}
if (!rfid.PICC_IsNewCardPresent()) return;
if (!rfid.PICC_ReadCardSerial()) return;
showScanning();
byte *uid = rfid.uid.uidByte;
Serial.print("UID: ");
for (byte i=0;i<rfid.uid.size;i++) {
Serial.print(uid[i], HEX);
Serial.print(" ");
}
Serial.println();
delay(300);
if (isAdmin(uid)) {
showGranted();
} else {
showDenied(uid);
}
rfid.PICC_HaltA();
}
※ OUR MESSAGES
You can share the link of this tutorial anywhere. Howerver, please do not copy the content to share on other websites. We took a lot of time and effort to create the content of this tutorial, please respect our work!