Documentation

ShillehTek LCD1602 16x2 LCD Display Module for Arduino Raspberry Pi DIY | ShillehTek Product Manual
Documentation / ShillehTek LCD1602 16x2 LCD Display Module for Arduino Raspberry Pi DIY | ShillehTek Product Manual

ShillehTek LCD1602 16x2 LCD Display Module for Arduino Raspberry Pi DIY | ShillehTek Product Manual

Overview

The LCD1602 is a 16-character by 2-line character LCD module based on the industry-standard HD44780 controller. It is the de facto standard for adding a low-cost, low-power text display to Arduino, Raspberry Pi, ESP32, ESP8266, and PIC projects. From bench multimeters to clocks, sensor readouts, and CNC controllers, this module has been the workhorse of hobbyist electronics for decades.

This module uses a 16-pin parallel interface and runs on a single 5V rail. It can be driven in 4-bit or 8-bit mode — most projects use 4-bit mode to save on GPIO. With the right backlight current and contrast trim, characters are crisp and readable in any indoor light.

If you're tight on GPIO, pair this module with a PCF8574 I2C backpack to drop the wiring down from 16 pins to 4 (VCC, GND, SDA, SCL). Without the backpack, the module is purely parallel — the wiring guides below cover the standard 4-bit hookup.

At a Glance

Display Size
16 x 2 chars
Operating Voltage
5V DC
Controller
HD44780
Interface
Parallel 4 / 8-bit
Pin Count
16 pins
Backlight
Built-in LED

Specifications

Parameter Value
Display Format 16 characters × 2 lines
Character Size 5 × 8 dots per character
Controller IC HD44780 (or compatible)
Operating Voltage 5V DC (typical)
Logic Voltage 5V
Operating Current ~1.5 mA (display) + 15-20 mA (backlight)
Interface 4-bit or 8-bit parallel
Backlight Yellow-green or blue with white text
Built-in Character Set ASCII + Japanese kana + 8 user-defined
Operating Temperature 0°C to 50°C
Module Dimensions ~80 × 36 × 13 mm

Pinout Diagram

LCD1602 16x2 LCD display module pinout diagram showing pin 1 VSS (GND), pin 2 VDD (+5V), pin 3 VE (contrast), pin 4 Register Select (RS), pin 5 Read/Write (RW), pin 6 Enable (E), pins 7-14 data pins D0 through D7, pin 15 LED Positive (anode), and pin 16 LED Negative (cathode)

Wiring Guide

Arduino Wiring (4-bit Mode)

The standard 4-bit hookup uses 6 GPIO lines: RS, E, and D4-D7. RW is tied to ground (write-only mode). A 10k potentiometer sets the contrast. The backlight gets a 220Ω current-limit resistor on the anode.

LCD Pin Arduino Pin Details
1 - VSS GND
2 - VDD 5V
3 - VE (V0) Wiper of 10k pot Pot ends to 5V and GND
4 - RS Digital 12
5 - RW GND Tie low for write-only
6 - E Digital 11
7 - D0 Not connected Unused in 4-bit mode
8 - D1 Not connected Unused in 4-bit mode
9 - D2 Not connected Unused in 4-bit mode
10 - D3 Not connected Unused in 4-bit mode
11 - D4 Digital 5
12 - D5 Digital 4
13 - D6 Digital 3
14 - D7 Digital 2
15 - A (LED+) 5V via 220Ω resistor Backlight anode
16 - K (LED-) GND Backlight cathode
Tip: If the screen is blank or shows two rows of solid blocks, adjust the contrast trim pot. The "blocks" pattern means power and contrast are connected but the controller hasn't been initialized yet.

ESP32 Wiring (4-bit Mode with 3.3V Logic)

ESP32 outputs 3.3V on its GPIO pins, but the LCD's HD44780 logic is 5V-tolerant on inputs. Most boards work fine with the LCD powered at 5V and driven by 3.3V GPIO directly. Power the backlight from 5V and use a 220Ω resistor.

LCD Pin ESP32 Pin Details
1 - VSS GND
2 - VDD 5V (VIN)
3 - VE Wiper of 10k pot Pot ends to 5V and GND
4 - RS GPIO 19
5 - RW GND
6 - E GPIO 23
11 - D4 GPIO 18
12 - D5 GPIO 17
13 - D6 GPIO 16
14 - D7 GPIO 15
15 - A 5V via 220Ω
16 - K GND
Info: If you have many sensors fighting for GPIO, switch to a PCF8574 I2C backpack and drop the LCD wiring down to four wires (VCC, GND, SDA, SCL). The LiquidCrystal_I2C library on Arduino and the I2C-LCD library on ESP32 both work cleanly.

Raspberry Pi Wiring (4-bit Mode)

The Raspberry Pi runs on 3.3V GPIO. The HD44780 is generally 5V-tolerant on inputs, so a direct 3.3V GPIO drive works. Power the LCD logic from 5V and the backlight from 5V via a current-limit resistor.

LCD Pin Raspberry Pi GPIO Details
1 - VSS Pin 6 (GND)
2 - VDD Pin 2 (5V)
3 - VE Wiper of 10k pot
4 - RS BCM 25 (Pin 22)
5 - RW GND
6 - E BCM 24 (Pin 18)
11 - D4 BCM 23 (Pin 16)
12 - D5 BCM 17 (Pin 11)
13 - D6 BCM 27 (Pin 13)
14 - D7 BCM 22 (Pin 15)
15 - A 5V via 220Ω
16 - K GND
Tip: The Adafruit_CharLCD library and the simpler RPLCD library both work on a Raspberry Pi. RPLCD's pure-Python implementation is easier to debug; Adafruit's is more featureful.

Raspberry Pi Pico Wiring (4-bit Mode)

The Pico is 3.3V logic but the HD44780 will accept 3.3V drive when its logic supply is 5V. Use VBUS (pin 40) as your 5V source if the Pico is powered over USB.

LCD Pin Pico Pin Details
1 - VSS GND
2 - VDD VBUS (5V) Pin 40, 5V from USB
3 - VE Wiper of 10k pot
4 - RS GP15
5 - RW GND
6 - E GP14
11 - D4 GP13
12 - D5 GP12
13 - D6 GP11
14 - D7 GP10
15 - A VBUS via 220Ω
16 - K GND

Code Examples

Arduino

lcd1602_arduino.ino
// LCD1602 16x2 LCD Display - Arduino Example
// 4-bit mode using LiquidCrystal library
// RS = 12, E = 11, D4 = 5, D5 = 4, D6 = 3, D7 = 2

#include <LiquidCrystal.h>

// (rs, enable, d4, d5, d6, d7)
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup() {
  // Tell the LCD it has 16 columns and 2 rows
  lcd.begin(16, 2);
  lcd.print("Hello, World!");

  lcd.setCursor(0, 1);
  lcd.print("ShillehTek LCD");
}

void loop() {
  // Move the cursor and print the seconds counter on row 2
  lcd.setCursor(0, 1);
  lcd.print("Uptime: ");
  lcd.print(millis() / 1000);
  lcd.print("s   ");
  delay(1000);
}

Raspberry Pi (Python)

lcd1602_rpi.py
#!/usr/bin/env python3
# LCD1602 16x2 LCD Display - Raspberry Pi Example
# Uses RPLCD library: pip install RPLCD

from RPLCD.gpio import CharLCD
from RPi import GPIO
import time

lcd = CharLCD(
    pin_rs=25,
    pin_e=24,
    pins_data=[23, 17, 27, 22],
    numbering_mode=GPIO.BCM,
    cols=16,
    rows=2,
    dotsize=8
)

try:
    lcd.write_string("Hello, World!")
    lcd.cursor_pos = (1, 0)
    lcd.write_string("ShillehTek LCD")
    while True:
        lcd.cursor_pos = (1, 0)
        lcd.write_string("Time: {:>4}s   ".format(int(time.time()) % 10000))
        time.sleep(1)
except KeyboardInterrupt:
    pass
finally:
    lcd.close(clear=True)
    GPIO.cleanup()

Raspberry Pi Pico (MicroPython)

lcd1602_pico.py
# LCD1602 16x2 LCD Display - Pico MicroPython Example
# Direct GPIO bit-banged 4-bit mode (no library needed).

from machine import Pin
import time

RS = Pin(15, Pin.OUT)
E  = Pin(14, Pin.OUT)
D4 = Pin(13, Pin.OUT)
D5 = Pin(12, Pin.OUT)
D6 = Pin(11, Pin.OUT)
D7 = Pin(10, Pin.OUT)

def pulse_e():
    E.value(1); time.sleep_us(1); E.value(0); time.sleep_us(50)

def write_nibble(value):
    D4.value((value >> 0) & 1)
    D5.value((value >> 1) & 1)
    D6.value((value >> 2) & 1)
    D7.value((value >> 3) & 1)
    pulse_e()

def write_byte(value, mode_data):
    RS.value(1 if mode_data else 0)
    write_nibble(value >> 4)
    write_nibble(value & 0x0F)

def cmd(c):  write_byte(c, False); time.sleep_ms(2)
def data(c): write_byte(c, True);  time.sleep_us(50)

def init_lcd():
    time.sleep_ms(50)
    write_nibble(0x03); time.sleep_ms(5)
    write_nibble(0x03); time.sleep_us(150)
    write_nibble(0x03); time.sleep_us(150)
    write_nibble(0x02)
    cmd(0x28)  # 4-bit, 2 line, 5x8
    cmd(0x0C)  # display on, no cursor
    cmd(0x06)  # entry mode
    cmd(0x01)  # clear

init_lcd()
for ch in "Hello, World!":
    data(ord(ch))
cmd(0xC0)  # row 2
for ch in "ShillehTek LCD":
    data(ord(ch))

Frequently Asked Questions

My LCD shows two rows of solid white blocks. What's wrong?
That pattern means the LCD has power but hasn't been initialized — usually a wiring or contrast issue. First, turn the contrast trim pot fully one way and then the other; if blocks fade in and out, contrast was the only problem. If they don't, recheck RS, E, and D4-D7 wiring against the table above.
Can I drive the 5V LCD from a 3.3V Raspberry Pi or ESP32?
Yes, in most cases. The HD44780 input logic threshold is around 2.2V, so 3.3V GPIO is high enough. Tie RW to GND so the LCD never tries to drive its data lines back to your 3.3V GPIO. Power the logic and backlight from 5V.
Why do I need to tie RW to ground?
RW lets you read busy/status flags from the LCD, but reading is rarely needed in maker projects, and reading puts 5V on the data lines (which is fine for Arduino but unsafe for 3.3V boards). Tying RW low forces write-only mode — simpler and safer.
How do I get this down to fewer wires?
Use a PCF8574 I2C backpack. It solders to the back of the LCD and converts the 16-pin parallel interface to a 4-wire I2C interface (VCC, GND, SDA, SCL). The backpack is sold separately or pre-soldered to LCD modules.
Can I display custom characters?
Yes. The HD44780 has 8 user-defined character slots (CGRAM addresses 0-7). On Arduino, use lcd.createChar(slot, byteArray) to upload a 5x8 bitmap, then print the character with lcd.write(byte(slot)). Common uses: degree symbols, battery icons, custom arrows, or a Wi-Fi indicator.
What library should I use?
Arduino: the built-in LiquidCrystal library (or LiquidCrystal_I2C if you have a backpack). Raspberry Pi: RPLCD or Adafruit_CharLCD. MicroPython on Pico: lcd_api / pico_i2c_lcd if you have a backpack, or a direct 4-bit GPIO driver like the one in the Pico code example above.