Skip to main content

Tutorial 1 - LCD1602

YouTube Video

Introduction

LCD1602 is a 16-character by 2-line alphanumeric LCD module. It is commonly used to display text in clocks, robots, weather stations, and other embedded projects because it is simple, reliable, and easy to read.

The module includes a display controller and is often used through an I2C adapter, which reduces the number of GPIO connections needed on the Raspberry Pi.

Components Needed

ComponentQuantity
Raspberry Pi 51
Breadboard1
WiresSeveral
I2C LCD16021

Fritzing Diagram

Connect the LCD to your Raspberry Pi as shown in the following diagram.

LCD1602 schematic

Image credit: SunFounder

LCD Library

import smbus
import time

class LCD:
def __init__(self, pi_rev = 2, i2c_addr = 0x3F, backlight = True):

# device constants
self.I2C_ADDR = i2c_addr
self.LCD_WIDTH = 16 # Max. characters per line

self.LCD_CHR = 1 # Mode - Sending data
self.LCD_CMD = 0 # Mode - Sending command

self.LCD_LINE_1 = 0x80 # LCD RAM addr for line one
self.LCD_LINE_2 = 0xC0 # LCD RAM addr for line two

if backlight:
self.LCD_BACKLIGHT = 0x08
else:
self.LCD_BACKLIGHT = 0x00

self.ENABLE = 0b00000100 # Enable bit

self.E_PULSE = 0.0005
self.E_DELAY = 0.0005

if pi_rev == 2:
self.bus = smbus.SMBus(1)
elif pi_rev == 1:
self.bus = smbus.SMBus(0)
else:
raise ValueError('pi_rev param must be 1 or 2')

self.lcd_byte(0x33, self.LCD_CMD)
self.lcd_byte(0x32, self.LCD_CMD)
self.lcd_byte(0x06, self.LCD_CMD)
self.lcd_byte(0x0C, self.LCD_CMD)
self.lcd_byte(0x28, self.LCD_CMD)
self.lcd_byte(0x01, self.LCD_CMD)

def lcd_byte(self, bits, mode):
bits_high = mode | (bits & 0xF0) | self.LCD_BACKLIGHT
bits_low = mode | ((bits << 4) & 0xF0) | self.LCD_BACKLIGHT

self.bus.write_byte(self.I2C_ADDR, bits_high)
self.toggle_enable(bits_high)

self.bus.write_byte(self.I2C_ADDR, bits_low)
self.toggle_enable(bits_low)

def toggle_enable(self, bits):
time.sleep(self.E_DELAY)
self.bus.write_byte(self.I2C_ADDR, (bits | self.ENABLE))
time.sleep(self.E_PULSE)
self.bus.write_byte(self.I2C_ADDR, (bits & ~self.ENABLE))
time.sleep(self.E_DELAY)

def message(self, string, line = 1):
if line == 1:
lcd_line = self.LCD_LINE_1
elif line == 2:
lcd_line = self.LCD_LINE_2
else:
raise ValueError('line number must be 1 or 2')

string = string.ljust(self.LCD_WIDTH, " ")
self.lcd_byte(lcd_line, self.LCD_CMD)

for i in range(self.LCD_WIDTH):
self.lcd_byte(ord(string[i]), self.LCD_CHR)

def clear(self):
self.lcd_byte(0x01, self.LCD_CMD)

Code

You can verify the address of the connected I2C device using the following command:

i2cdetect -y 1

Addresses of any connected I2C devices will be shown.

I2C detect output

Make sure that the library and the following demo code are in the same directory.

import time
from LCD import LCD

# Initialize the LCD with specific parameters: Raspberry Pi revision, I2C address, and backlight status
lcd = LCD(2, 0x3f, True)

# Display messages on the LCD
lcd.message("NerdCave", 1)
lcd.message("Tutorials", 2)

# Keep the messages displayed for 5 seconds
time.sleep(5)

# Clear the LCD display
lcd.clear()

Code Explanation

import time
from LCD import LCD

time is the standard Python library for time-related tasks. LCD is a custom library used to communicate with the display.

lcd = LCD(2, 0x3f, True)

The constructor takes the Raspberry Pi revision, the I2C address of the LCD, and whether the backlight should be enabled.

lcd.message("NerdCave", 1)
lcd.message("Tutorials", 2)

These lines print text on line 1 and line 2 of the LCD.

time.sleep(5)

This leaves the message on the display for 5 seconds.

lcd.clear()

Finally, the display is cleared.